3 Commits

Author SHA1 Message Date
amery ed04fe873b build-sys: use local asciigoat.org/core [DO-NOT-MERGE]
Signed-off-by: Alejandro Mery <amery@jpi.io>
2023-08-30 01:54:45 +00:00
amery 2b9996da7c parser: implement initial tokeniser
only logging position, errors and non-whitespace elements

Signed-off-by: Alejandro Mery <amery@jpi.io>
2023-08-30 01:53:23 +00:00
amery 00fcde4c5b parser: add placeholder for ini Parser
Signed-off-by: Alejandro Mery <amery@jpi.io>
2023-08-30 02:06:31 +01:00
4 changed files with 118 additions and 1 deletions
+6 -1
View File
@@ -2,7 +2,12 @@ module asciigoat.org/ini
go 1.19 go 1.19
require github.com/mgechev/revive v1.3.3 replace asciigoat.org/core => ../core
require (
asciigoat.org/core v0.3.4
github.com/mgechev/revive v1.3.3
)
require ( require (
github.com/BurntSushi/toml v1.3.2 // indirect github.com/BurntSushi/toml v1.3.2 // indirect
+71
View File
@@ -0,0 +1,71 @@
package parser
import (
"log"
"asciigoat.org/core/lexer"
)
// Run parses the source
func (p *Parser) Run() error {
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
log.Printf("%s: %s: %s", p.pos, "error", err)
return nil, err
case IsNewLine(r):
// new line
p.lexNewLine(r)
case IsSpace(r):
// whitespace
p.lexWhitespace()
default:
// token
p.src.UnreadRune()
return p.lexToken, nil
}
}
}
func (p *Parser) lexToken() (lexer.StateFn, error) {
p.src.AcceptAll(IsNotSpace)
s := p.src.Emit()
log.Printf("%s: %s: %q", p.pos, "token", s)
p.pos.StepN(len(s))
return p.lexStart, nil
}
func (p *Parser) lexWhitespace() {
p.src.Discard()
p.pos.Step()
}
func (p *Parser) lexNewLine(r1 rune) {
// r1 is warrantied to be either \n or \r
r2, _, err := p.src.ReadRune()
switch {
case r1 == '\r' && r2 == '\n':
// CR LN
case r1 == '\r' && err == nil:
// CR
p.src.UnreadRune()
case r2 == '\r':
// LN CR
case err == nil:
// LN
p.src.UnreadRune()
}
p.src.Discard()
p.pos.StepLine()
}
+14
View File
@@ -0,0 +1,14 @@
package parser
import "asciigoat.org/core/lexer"
var (
// IsNewLine tells if a rune represents a line break or the start of one
IsNewLine = lexer.NewIsIn("\n\r")
// IsSpace tells if a rune is considered whitespace by unicode
IsSpace = lexer.IsSpace
// IsNotNewLine tells if a rune is anything other than line breaks
IsNotNewLine = lexer.NewIsNot(IsNewLine)
// IsNotSpace tells if a rune is anything other than whitespace
IsNotSpace = lexer.NewIsNot(IsSpace)
)
+27
View File
@@ -0,0 +1,27 @@
// Package parser parses dosini-style files
package parser
import (
"io"
"asciigoat.org/core/lexer"
)
// Parser parses a dosini-style document
type Parser struct {
src *lexer.Reader
pos lexer.Position
}
// NewParser creates a dosini-style parser using
// an [io.Reader] as source
func NewParser(r io.Reader) *Parser {
if r == nil {
return nil
}
return &Parser{
src: lexer.NewReader(r),
}
}