Skip to content

Commit bc59d7a

Browse files
committed
added basic evaluator
1 parent 9c4ca8d commit bc59d7a

File tree

3 files changed

+404
-1
lines changed

3 files changed

+404
-1
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ test-src/android/pathfinder.db
3636
.vscode/cody.json
3737

3838
coverage.out
39-
coverage.html
39+
coverage.html
40+
41+
.windsurfrules

sourcecode-parser/antlr/evaluator.go

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package parser
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"github.com/expr-lang/expr"
7+
)
8+
9+
// EvaluateExpressionTree evaluates the expression tree against input data
10+
// and returns filtered data based on the expression conditions
11+
func EvaluateExpressionTree(tree *ExpressionNode, data []map[string]interface{}) ([]map[string]interface{}, error) {
12+
if tree == nil {
13+
return data, nil
14+
}
15+
16+
var result []map[string]interface{}
17+
for _, item := range data {
18+
matches, err := evaluateNode(tree, item)
19+
if err != nil {
20+
return nil, fmt.Errorf("evaluation error: %w", err)
21+
}
22+
23+
// Only include items that match the expression
24+
if matches.(bool) {
25+
result = append(result, item)
26+
}
27+
}
28+
return result, nil
29+
}
30+
31+
// evaluateNode recursively evaluates a single node in the expression tree
32+
// returns interface{} to support different types (bool, string, number)
33+
func evaluateNode(node *ExpressionNode, data map[string]interface{}) (interface{}, error) {
34+
if node == nil {
35+
return nil, fmt.Errorf("nil node")
36+
}
37+
38+
// Convert expression node to expr-lang expression string
39+
exprStr, err := nodeToExprString(node)
40+
if err != nil {
41+
return nil, fmt.Errorf("failed to convert node to expr: %w", err)
42+
}
43+
44+
// Compile the expression
45+
program, err := expr.Compile(exprStr, expr.Env(data))
46+
if err != nil {
47+
return nil, fmt.Errorf("failed to compile expression: %w", err)
48+
}
49+
50+
// Run the expression with the data
51+
result, err := expr.Run(program, data)
52+
if err != nil {
53+
return nil, fmt.Errorf("failed to evaluate expression: %w", err)
54+
}
55+
56+
return result, nil
57+
}
58+
59+
// nodeToExprString converts an ExpressionNode to an expr-lang expression string
60+
func nodeToExprString(node *ExpressionNode) (string, error) {
61+
switch node.Type {
62+
case "binary":
63+
left, err := nodeToExprString(node.Left)
64+
if err != nil {
65+
return "", err
66+
}
67+
right, err := nodeToExprString(node.Right)
68+
if err != nil {
69+
return "", err
70+
}
71+
return fmt.Sprintf("(%s %s %s)", left, node.Operator, right), nil
72+
73+
case "literal":
74+
return node.Value, nil
75+
76+
case "method_call":
77+
// Format method call with arguments
78+
args := make([]string, 0, len(node.Args))
79+
for _, arg := range node.Args {
80+
argStr, err := nodeToExprString(&arg)
81+
if err != nil {
82+
return "", err
83+
}
84+
args = append(args, argStr)
85+
}
86+
return fmt.Sprintf("%s(%s)", node.Value, strings.Join(args, ", ")), nil
87+
88+
case "predicate_call":
89+
// Similar to method_call
90+
args := make([]string, 0, len(node.Args))
91+
for _, arg := range node.Args {
92+
argStr, err := nodeToExprString(&arg)
93+
if err != nil {
94+
return "", err
95+
}
96+
args = append(args, argStr)
97+
}
98+
return fmt.Sprintf("%s(%s)", node.Value, strings.Join(args, ", ")), nil
99+
100+
case "variable":
101+
return node.Value, nil
102+
103+
case "unary":
104+
right, err := nodeToExprString(node.Right)
105+
if err != nil {
106+
return "", err
107+
}
108+
return fmt.Sprintf("%s%s", node.Operator, right), nil
109+
110+
default:
111+
return "", fmt.Errorf("unknown node type: %s", node.Type)
112+
}
113+
}
114+
115+

0 commit comments

Comments
 (0)