varaq-interpreter-go/varaq/parser.go

82 lines
1.5 KiB
Go
Executable File

package varaq
import (
"fmt"
"strings"
)
type Expr struct {
Tok TokenType
Exprs []Expr
Value any
Count int
}
type Parser struct {
tokens []Token
pos int
end int
}
func (p Parser) curr() Token {
return p.tokens[p.pos]
}
func parse(p Parser, stop TokenType, tt TokenType) (Expr, int) {
code := Expr{tt, make([]Expr, 0), nil, 0}
for {
if p.pos < 0 || p.pos > p.end-1 {
break
}
if p.curr().Toktype == stop {
p.pos += 1
break
}
if p.curr().Toktype == LEFTBRACE {
p.pos += 1
ex, pos := parse(p, RIGHTBRACE, FUNCTION)
p.pos = pos
code.Exprs = append(code.Exprs, ex)
code.Count += 1
} else if p.curr().Toktype == LEFTPAREN {
p.pos += 1
ex, pos := parse(p, RIGHTPAREN, LIST)
p.pos = pos
code.Exprs = append(code.Exprs, ex)
code.Count += 1
} else {
code.Exprs = append(code.Exprs, Expr{p.curr().Toktype, nil, p.curr().Literal, 0})
p.pos += 1
}
}
return code, p.pos
}
func Parse(tokens []Token) Expr {
parser := Parser{tokens, 0, len(tokens)}
ex, _ := parse(parser, EOF, SCRIPT)
return ex
}
func PrintDump(code Expr, depth int) {
for _, c := range code.Exprs {
if c.Tok == FUNCTION {
depth += 1
fmt.Printf("%s %s\n", strings.Repeat("-", depth), c.Tok)
PrintDump(c, depth)
depth -= 1
} else if c.Tok == LIST {
depth += 1
fmt.Printf("%s %s\n", strings.Repeat("-", depth), c.Tok)
PrintDump(c, depth)
depth -= 1
} else {
fmt.Printf("%s %s: %v\n", strings.Repeat("-", depth), c.Tok, c.Value)
}
}
}