initial commit
This commit is contained in:
135
schema/parse.go
Normal file
135
schema/parse.go
Normal file
@@ -0,0 +1,135 @@
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user