Files
ini/parser/lexer.go
T
amery 78d20c1359 WIP
Signed-off-by: Alejandro Mery <amery@jpi.io>
2023-08-30 23:50:34 +01:00

120 lines
2.0 KiB
Go

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
}