Improved expression parser

This commit is contained in:
2024-06-16 22:48:14 +02:00
parent ef16bdb4c7
commit 23c6134d9a
5 changed files with 152 additions and 138 deletions

View File

@ -1,92 +1,117 @@
package expression
import (
"math"
"git.akyoto.dev/cli/q/src/build/token"
)
var call = []byte("call")
var call = []byte("λ")
// 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:
for i, t := range tokens {
if t.Kind == token.GroupStart {
groupLevel++
if groupLevel == 1 {
groupPosition = i + 1
}
case token.GroupEnd:
continue
}
if t.Kind == token.GroupEnd {
groupLevel--
if groupLevel == 0 {
isFunctionCall := isComplete(cursor)
if groupLevel != 0 {
continue
}
if isFunctionCall {
parameters := List(tokens[groupPosition:i])
isFunctionCall := isComplete(cursor)
node := New()
node.Token.Kind = token.Operator
node.Token.Position = tokens[groupPosition].Position
node.Token.Bytes = call
cursor.Replace(node)
if isFunctionCall {
parameters := List(tokens[groupPosition:i])
for _, param := range parameters {
node.AddChild(param)
}
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
}
i++
continue
cursor.Replace(node)
}
group := Parse(tokens[groupPosition:i])
if group == nil {
i++
continue
for _, param := range parameters {
node.AddChild(param)
}
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++
cursor = node
continue
}
node := NewLeaf(tokens[i])
group := Parse(tokens[groupPosition:i])
if group == nil {
continue
}
group.Precedence = math.MaxInt
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 := precedence(cursor.Token.Text())
newPrecedence := precedence(node.Token.Text())
oldPrecedence := cursor.Precedence
newPrecedence := node.Precedence
if newPrecedence > oldPrecedence {
cursor.LastChild().Replace(node)
@ -94,7 +119,7 @@ func Parse(tokens token.List) *Expression {
start := cursor
for start != nil {
precedence := precedence(start.Token.Text())
precedence := start.Precedence
if precedence < newPrecedence {
start.LastChild().Replace(node)
@ -124,18 +149,8 @@ func Parse(tokens token.List) *Expression {
}
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)
}
continue
}
i++
}
return root