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") }