package parser import ( "asciigoat.org/core/lexer" ) // Run parses the source func (p *Parser) Run() error { p.setDefaults() p.pos.Reset() return lexer.Run(p.lexStart) } func (p *Parser) lexStart() (lexer.StateFn, error) { for { r, _, err := p.src.ReadRune() switch { case err != nil: // read error return p.emitError("", err) case IsNewLine(r): // new line p.lexNewLine(r) p.stepLine() case IsSpace(r): // whitespace p.stepRune() case IsCommentStart(r): // switch to comment lexer p.src.UnreadRune() return p.lexComment, nil case IsSectionStart(r): // section p.stepRune() return p.lexSectionStart, nil default: // entry p.src.UnreadRune() return p.lexEntryStart, nil } } } func (p *Parser) lexNewLine(r1 rune) { // r1 is warrantied to be either \n or \r r2, _, err := p.src.ReadRune() switch r1 { case '\r': switch { case r2 == '\n': // CR LN case err == nil: // CR p.src.UnreadRune() default: // CR EOF } case '\n': switch { case r2 == '\r': // LN CR case err == nil: // LN p.src.UnreadRune() default: // LN EOF } default: panic("unreachable") } } func (p *Parser) lexComment() (lexer.StateFn, error) { // until the end of the line p.src.AcceptAll(IsNotNewLine) err := p.OnComment(p.pos, p.src.Emit()) return p.lexStart, err } func (p *Parser) lexSectionStart() (lexer.StateFn, error) { // remove whitespace between `[` and the name if p.src.AcceptAll(IsSpaceNotNewLine) { p.stepString() } if !p.src.AcceptAll(IsName) { // no name return p.emitError("section name missing", lexer.ErrUnacceptableRune) } p.pushString(TokenSectionName) var s0, s1 string // name starts start := p.pos s0 = p.src.String() if p.src.AcceptAll(IsSpaceNotNewLine) { s1 = p.src.String() } } else { } return nil, nil } func (*Parser) lexEntryStart() (lexer.StateFn, error) { return nil, nil } func (p *Parser) lexToken() (lexer.StateFn, error) { p.src.AcceptAll(IsNotSpace) p.pushString(TokenUnknown) return p.lexStart, nil }