Files
azalea/schema/parse.go
2026-01-23 03:20:34 -06:00

136 lines
2.9 KiB
Go

package schema
import (
"fmt"
)
type Node struct {
Function string
Left, Right *Node
*Token
}
type RawArgument struct {
Index uintptr
Size uintptr
}
func (n *Node) String() string {
if n.Token != nil {
return n.Token.String()
}
return fmt.Sprintf("(%s %s %s)", n.Function, n.Left, n.Right)
}
func Parse(tokens [][]*Token) ([]*Node, error) {
trees := make([]*Node, len(tokens))
for i, statement := range tokens {
node, err := parse(statement, 0)
if err != nil {
return nil, err
}
trees[i] = node
}
return trees, nil
}
func parse(statement []*Token, depth uintptr) (*Node, error) {
if len(statement) == 0 || (len(statement) == 2 && statement[0].Type == OpenParenTokenType && statement[1].Type == CloseParenTokenType) {
return &Node{
Function: "",
Left: nil,
Right: nil,
Token: nil,
}, nil
}
if len(statement) < 3 {
return nil, fmt.Errorf("statement too short")
}
if statement[0].Type != OpenParenTokenType || statement[len(statement)-1].Type != CloseParenTokenType {
return nil, fmt.Errorf("malformed statement")
}
statement = statement[1 : len(statement)-1]
expressions := make([]*Node, len(statement))
exprCounter := 0
lastBegin := -1
for i := 0; i < len(statement); i++ {
if lastBegin == -1 {
switch statement[i].Type {
case OpenParenTokenType:
if statement[i].Number == int64(depth)+1 {
lastBegin = i
}
break
case CloseParenTokenType:
return nil, fmt.Errorf("unexpected end of statement")
default:
expressions[exprCounter] = &Node{
Function: "",
Left: nil,
Right: nil,
Token: statement[i],
}
exprCounter++
break
}
}
if statement[i].Type == CloseParenTokenType && statement[i].Number == int64(depth)+1 {
res, err := parse(statement[lastBegin:i+1], depth+1)
if err != nil {
return nil, err
}
expressions[exprCounter] = res
exprCounter++
lastBegin = -1
}
}
for i, expr := range expressions {
if expr == nil {
expressions = expressions[:i]
break
}
}
switch len(expressions) {
case 1:
node := expressions[0]
if node.Token != nil && node.Type == NameTokenType {
return &Node{
Function: node.Value,
Left: nil,
Right: nil,
Token: nil,
}, nil
}
return node, nil
case 2, 3:
first := expressions[0]
if first.Token != nil && first.Type == NameTokenType {
var right *Node = nil
if len(expressions) == 3 {
right = expressions[2]
}
return &Node{
Function: first.Value,
Left: expressions[1],
Right: right,
Token: nil,
}, nil
}
//fallthrough
default:
root := &Node{
Function: ".",
}
current := root
for _, expr := range expressions[:len(expressions)-2] {
current.Left = expr
current.Right = &Node{
Function: ".",
}
current = current.Right
}
current.Left = expressions[len(expressions)-2]
current.Right = expressions[len(expressions)-1]
return root, nil
}
return nil, fmt.Errorf("parsing error")
}