Implemented expression parsing

This commit is contained in:
2024-06-16 16:57:33 +02:00
parent 864c9c7b43
commit ef16bdb4c7
18 changed files with 618 additions and 99 deletions

View File

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