136 lines
2.9 KiB
Go
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")
|
|
}
|