82 lines
1.5 KiB
Go
Executable File
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)
|
|
}
|
|
}
|
|
}
|