package parser import "asciigoat.org/core/lexer" // Run parses the source func (p *Parser) Run() error { p.setDefaults() return lexer.Run(p.lexStart) } func (p *Parser) lexStart() (lexer.StateFn, error) { for { r, _, err := p.p.ReadRune() switch { case err != nil: return p.emitError("", err) case IsNewLine(r): // new line p.p.UnreadRune() p.p.AcceptNewLine() p.stepLine() case IsSpace(r): // whitespace p.stepString() case IsCommentStart(r): // switch to comment lexer p.p.UnreadRune() return p.lexComment, nil case IsSectionStart(r): // section return p.lexSectionStart, nil default: // entry p.p.UnreadRune() return p.lexEntryStart, nil } } } func (p *Parser) lexComment() (lexer.StateFn, error) { // until the end of the line p.p.AcceptAll(IsNotNewLine) err := p.emitString(TokenComment) return p.lexStart, err } func (p *Parser) lexSectionStart() (lexer.StateFn, error) { if err := p.emitString(TokenSectionStart); err != nil { return nil, err } // remove whitespace between `[` and the name if p.p.AcceptAll(IsSpaceNotNewLine) { p.stepString() } if !p.p.AcceptAll(IsName) { // no name return p.emitError("section name missing", lexer.ErrUnacceptableRune) } if err := p.emitString(TokenSectionName); err != nil { return nil, err } // remove whitespace between the name and the closing `]` if p.p.AcceptAll(IsSpaceNotNewLine) { p.stepString() } r, _, err := p.p.ReadRune() switch { case err != nil: return p.emitError("", err) case IsSectionEnd(r): err := p.emitString(TokenSectionEnd) return p.lexStart, err default: return p.emitInvalidRune(r) } } func (p *Parser) lexEntryStart() (lexer.StateFn, error) { p.p.AcceptAll(IsName) if err := p.emitString(TokenFieldKey); err != nil { return nil, err } // ignore whitespace between key and the '=' sign if p.p.AcceptAll(IsSpaceNotNewLine) { p.stepString() } r, _, err := p.p.ReadRune() switch { case err != nil: return p.emitError("", err) case r != RuneFieldEqual: return p.emitInvalidRune(r) } // ignore whitespace between the '=' and the value if p.p.AcceptAll(IsSpaceNotNewLine) { p.stepString() } p.p.AcceptAll(IsNotNewLine) if err := p.emitString(TokenFieldValue); err != nil { return nil, err } return p.lexStart, err }