|
|
@ -5,71 +5,42 @@ import "asciigoat.org/core/lexer" |
|
|
|
// Run parses the source
|
|
|
|
// Run parses the source
|
|
|
|
func (p *Parser) Run() error { |
|
|
|
func (p *Parser) Run() error { |
|
|
|
p.setDefaults() |
|
|
|
p.setDefaults() |
|
|
|
p.pos.Reset() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return lexer.Run(p.lexStart) |
|
|
|
return lexer.Run(p.lexStart) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) lexStart() (lexer.StateFn, error) { |
|
|
|
func (p *Parser) lexStart() (lexer.StateFn, error) { |
|
|
|
for { |
|
|
|
for { |
|
|
|
r, _, err := p.src.ReadRune() |
|
|
|
r, _, err := p.p.ReadRune() |
|
|
|
switch { |
|
|
|
switch { |
|
|
|
case err != nil: |
|
|
|
case err != nil: |
|
|
|
return p.emitError("", err) |
|
|
|
return p.emitError("", err) |
|
|
|
case IsNewLine(r): |
|
|
|
case IsNewLine(r): |
|
|
|
// new line
|
|
|
|
// new line
|
|
|
|
p.lexMoreNewLine(r) |
|
|
|
p.p.UnreadRune() |
|
|
|
|
|
|
|
p.p.AcceptNewLine() |
|
|
|
p.stepLine() |
|
|
|
p.stepLine() |
|
|
|
case IsSpace(r): |
|
|
|
case IsSpace(r): |
|
|
|
// whitespace
|
|
|
|
// whitespace
|
|
|
|
p.stepRune() |
|
|
|
p.stepString() |
|
|
|
case IsCommentStart(r): |
|
|
|
case IsCommentStart(r): |
|
|
|
// switch to comment lexer
|
|
|
|
// switch to comment lexer
|
|
|
|
p.src.UnreadRune() |
|
|
|
p.p.UnreadRune() |
|
|
|
return p.lexComment, nil |
|
|
|
return p.lexComment, nil |
|
|
|
case IsSectionStart(r): |
|
|
|
case IsSectionStart(r): |
|
|
|
// section
|
|
|
|
// section
|
|
|
|
return p.lexSectionStart, nil |
|
|
|
return p.lexSectionStart, nil |
|
|
|
default: |
|
|
|
default: |
|
|
|
// entry
|
|
|
|
// entry
|
|
|
|
p.src.UnreadRune() |
|
|
|
p.p.UnreadRune() |
|
|
|
return p.lexEntryStart, nil |
|
|
|
return p.lexEntryStart, nil |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) lexMoreNewLine(r1 rune) { |
|
|
|
|
|
|
|
// r1 is warrantied to be either '\r' or '\n'
|
|
|
|
|
|
|
|
r2, _, err := p.src.ReadRune() |
|
|
|
|
|
|
|
switch r1 { |
|
|
|
|
|
|
|
case '\n': |
|
|
|
|
|
|
|
switch { |
|
|
|
|
|
|
|
case r2 == '\r': |
|
|
|
|
|
|
|
// LN CR
|
|
|
|
|
|
|
|
case err == nil: |
|
|
|
|
|
|
|
// LN
|
|
|
|
|
|
|
|
p.src.UnreadRune() |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
// LN EOF
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case '\r': |
|
|
|
|
|
|
|
switch { |
|
|
|
|
|
|
|
case r2 == '\n': |
|
|
|
|
|
|
|
// CR LN
|
|
|
|
|
|
|
|
case err == nil: |
|
|
|
|
|
|
|
// CR
|
|
|
|
|
|
|
|
p.src.UnreadRune() |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
// CR EOF
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
panic("unreachable") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) lexComment() (lexer.StateFn, error) { |
|
|
|
func (p *Parser) lexComment() (lexer.StateFn, error) { |
|
|
|
// until the end of the line
|
|
|
|
// until the end of the line
|
|
|
|
p.src.AcceptAll(IsNotNewLine) |
|
|
|
p.p.AcceptAll(IsNotNewLine) |
|
|
|
|
|
|
|
|
|
|
|
err := p.emitString(TokenComment) |
|
|
|
err := p.emitString(TokenComment) |
|
|
|
return p.lexStart, err |
|
|
|
return p.lexStart, err |
|
|
@ -81,11 +52,11 @@ func (p *Parser) lexSectionStart() (lexer.StateFn, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// remove whitespace between `[` and the name
|
|
|
|
// remove whitespace between `[` and the name
|
|
|
|
if p.src.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
if p.p.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
p.stepString() |
|
|
|
p.stepString() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if !p.src.AcceptAll(IsName) { |
|
|
|
if !p.p.AcceptAll(IsName) { |
|
|
|
// no name
|
|
|
|
// no name
|
|
|
|
return p.emitError("section name missing", lexer.ErrUnacceptableRune) |
|
|
|
return p.emitError("section name missing", lexer.ErrUnacceptableRune) |
|
|
|
} |
|
|
|
} |
|
|
@ -94,12 +65,12 @@ func (p *Parser) lexSectionStart() (lexer.StateFn, error) { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// remove whitespace between the name andthe closing `]`
|
|
|
|
// remove whitespace between the name and the closing `]`
|
|
|
|
if p.src.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
if p.p.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
p.stepString() |
|
|
|
p.stepString() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
r, _, err := p.src.ReadRune() |
|
|
|
r, _, err := p.p.ReadRune() |
|
|
|
switch { |
|
|
|
switch { |
|
|
|
case err != nil: |
|
|
|
case err != nil: |
|
|
|
return p.emitError("", err) |
|
|
|
return p.emitError("", err) |
|
|
@ -112,17 +83,17 @@ func (p *Parser) lexSectionStart() (lexer.StateFn, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (p *Parser) lexEntryStart() (lexer.StateFn, error) { |
|
|
|
func (p *Parser) lexEntryStart() (lexer.StateFn, error) { |
|
|
|
p.src.AcceptAll(IsName) |
|
|
|
p.p.AcceptAll(IsName) |
|
|
|
if err := p.emitString(TokenFieldKey); err != nil { |
|
|
|
if err := p.emitString(TokenFieldKey); err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ignore whitespace between key and the '=' sign
|
|
|
|
// ignore whitespace between key and the '=' sign
|
|
|
|
if p.src.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
if p.p.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
p.stepString() |
|
|
|
p.stepString() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
r, _, err := p.src.ReadRune() |
|
|
|
r, _, err := p.p.ReadRune() |
|
|
|
switch { |
|
|
|
switch { |
|
|
|
case err != nil: |
|
|
|
case err != nil: |
|
|
|
return p.emitError("", err) |
|
|
|
return p.emitError("", err) |
|
|
@ -131,11 +102,11 @@ func (p *Parser) lexEntryStart() (lexer.StateFn, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ignore whitespace between the '=' and the value
|
|
|
|
// ignore whitespace between the '=' and the value
|
|
|
|
if p.src.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
if p.p.AcceptAll(IsSpaceNotNewLine) { |
|
|
|
p.stepString() |
|
|
|
p.stepString() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
p.src.AcceptAll(IsNotNewLine) |
|
|
|
p.p.AcceptAll(IsNotNewLine) |
|
|
|
if err := p.emitString(TokenFieldValue); err != nil { |
|
|
|
if err := p.emitString(TokenFieldValue); err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|