package expression import ( "math" "git.akyoto.dev/cli/q/src/build/token" ) var call = []byte("λ") // Parse generates an expression tree from tokens. func Parse(tokens token.List) *Expression { var ( cursor *Expression root *Expression groupLevel = 0 groupPosition = 0 ) for i, t := range tokens { if t.Kind == token.GroupStart { groupLevel++ if groupLevel == 1 { groupPosition = i + 1 } continue } if t.Kind == token.GroupEnd { groupLevel-- if groupLevel != 0 { continue } isFunctionCall := isComplete(cursor) if isFunctionCall { parameters := NewList(tokens[groupPosition:i]) node := New() node.Token.Kind = token.Operator node.Token.Position = tokens[groupPosition].Position node.Token.Bytes = call node.Precedence = precedence("λ") if cursor.Token.Kind == token.Operator && node.Precedence > cursor.Precedence { cursor.LastChild().Replace(node) } else { if cursor == root { root = node } cursor.Replace(node) } for _, param := range parameters { node.AddChild(param) } cursor = node continue } group := Parse(tokens[groupPosition:i]) if group == nil { continue } group.Precedence = math.MaxInt8 if cursor == nil { cursor = group root = group } else { cursor.AddChild(group) } continue } if groupLevel > 0 { continue } if t.Kind == token.Identifier || t.Kind == token.Number || t.Kind == token.String { if cursor != nil { node := NewLeaf(t) cursor.AddChild(node) } else { cursor = NewLeaf(t) root = cursor } continue } if t.Kind == token.Operator { if cursor == nil { cursor = NewLeaf(t) cursor.Precedence = precedence(t.Text()) root = cursor continue } node := NewLeaf(t) node.Precedence = precedence(t.Text()) if cursor.Token.Kind == token.Operator { oldPrecedence := cursor.Precedence newPrecedence := node.Precedence if newPrecedence > oldPrecedence { cursor.LastChild().Replace(node) } else { start := cursor for start != nil { precedence := start.Precedence if precedence < newPrecedence { start.LastChild().Replace(node) break } if precedence == newPrecedence { if start == root { root = node } start.Replace(node) break } start = start.Parent } if start == nil { root.Replace(node) root = node } } } else { node.AddChild(cursor) root = node } cursor = node continue } } return root }