ast: now supports espression forest (multi expressions)
This commit is contained in:
parent
aa705e68bf
commit
4e361f938e
37
ast.go
37
ast.go
@ -13,6 +13,7 @@ import (
|
||||
//-------- ast
|
||||
|
||||
type ast struct {
|
||||
forest []*term
|
||||
root *term
|
||||
}
|
||||
|
||||
@ -20,6 +21,16 @@ func NewAst() *ast {
|
||||
return &ast{}
|
||||
}
|
||||
|
||||
func (self *ast) ToForest() {
|
||||
if self.root != nil {
|
||||
if self.forest == nil {
|
||||
self.forest = make([]*term, 0)
|
||||
}
|
||||
self.forest = append(self.forest, self.root)
|
||||
self.root = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ast) String() string {
|
||||
var sb strings.Builder
|
||||
if self.root == nil {
|
||||
@ -77,10 +88,31 @@ func (self *ast) insert(tree, node *term) (root *term, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (self *ast) eval(ctx exprContext) (result any, err error) {
|
||||
func (self *ast) Finish() {
|
||||
if self.root == nil && self.forest != nil && len(self.forest) >= 1 {
|
||||
self.root = self.forest[len(self.forest)-1]
|
||||
self.forest = self.forest[0:len(self.forest) - 1]
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ast) Eval(ctx exprContext) (result any, err error) {
|
||||
self.Finish()
|
||||
|
||||
if self.root != nil {
|
||||
initDefaultVars(ctx)
|
||||
result, err = self.root.compute(ctx)
|
||||
if self.forest != nil {
|
||||
for i, root := range self.forest {
|
||||
if result, err = root.compute(ctx); err == nil {
|
||||
ctx.SetValue(preset_last_result, result)
|
||||
} else {
|
||||
err = fmt.Errorf("error in expression nr %d: %v", i+1, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
result, err = self.root.compute(ctx)
|
||||
}
|
||||
} else {
|
||||
err = errors.New("empty expression")
|
||||
}
|
||||
@ -89,6 +121,7 @@ func (self *ast) eval(ctx exprContext) (result any, err error) {
|
||||
|
||||
// Preset variables
|
||||
const (
|
||||
preset_last_result = "_last"
|
||||
preset_bool_shortcut = "_bool_shortcut"
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,7 @@ func EvalString(ctx exprContext, source string) (result any, err error) {
|
||||
parser := NewParser(ctx)
|
||||
|
||||
if tree, err = parser.parse(scanner); err == nil {
|
||||
result, err = tree.eval(ctx)
|
||||
result, err = tree.Eval(ctx)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func TestParser(t *testing.T) {
|
||||
/* 39 */ {`(((1)))`, int64(1), nil},
|
||||
/* 40 */ {`"uno_" + var2`, `uno_abc`, nil},
|
||||
/* 41 */ {`0 || 0.0 && "hello"`, false, nil},
|
||||
/* 42 */ {`"s" + true`, nil, errors.New(`left operand 's' [string] is not compatible with right operand 'true' [bool] with respect to operator "+"`)},
|
||||
/* 42 */ {`"s" + true`, nil, errors.New(`left operand 's' [string] and right operand 'true' [bool] are not compatible with operator "+"`)},
|
||||
/* 43 */ {`+false`, nil, errors.New(`prefix/postfix operator "+" do not support operand 'false' [bool]`)},
|
||||
/* 44 */ {`false // very simple expression`, false, nil},
|
||||
/* 45 */ {`1 + // Missing right operator`, nil, errors.New(`infix operator "+" requires two operands, got 1`)},
|
||||
@ -108,7 +108,7 @@ func TestParser(t *testing.T) {
|
||||
/* 82 */ {`5 % 2`, int64(1), nil},
|
||||
/* 83 */ {`5 % (-2)`, int64(1), nil},
|
||||
/* 84 */ {`-5 % 2`, int64(-1), nil},
|
||||
/* 85 */ {`5 % 2.0`, nil, errors.New(`left operand '5' [int64] is not compatible with right operand '2' [float64] with respect to operator "%"`)},
|
||||
/* 85 */ {`5 % 2.0`, nil, errors.New(`left operand '5' [int64] and right operand '2' [float64] are not compatible with operator "%"`)},
|
||||
/* 86 */ {`"a" < "b" AND NOT (2 < 1)`, true, nil},
|
||||
/* 87 */ {`"a" < "b" AND NOT (2 == 1)`, true, nil},
|
||||
/* 88 */ {`"a" < "b" AND ~ 2 == 1`, true, nil},
|
||||
@ -147,7 +147,7 @@ func TestParser(t *testing.T) {
|
||||
|
||||
good := true
|
||||
if expr, gotErr = parser.parse(scanner); gotErr == nil {
|
||||
gotResult, gotErr = expr.eval(ctx)
|
||||
gotResult, gotErr = expr.Eval(ctx)
|
||||
}
|
||||
|
||||
if gotResult != input.wantResult {
|
||||
@ -221,7 +221,7 @@ func NoTestListParser(t *testing.T) {
|
||||
|
||||
good := true
|
||||
if expr, gotErr = parser.parse(scanner); gotErr == nil {
|
||||
gotResult, gotErr = expr.eval(ctx)
|
||||
gotResult, gotErr = expr.Eval(ctx)
|
||||
}
|
||||
|
||||
if (gotResult == nil && input.wantResult != nil) || (gotResult != nil && input.wantResult == nil) {
|
||||
|
2
term.go
2
term.go
@ -188,7 +188,7 @@ func (self *term) compute(ctx exprContext) (v any, err error) {
|
||||
|
||||
func (self *term) errIncompatibleTypes(leftValue, rightValue any) error {
|
||||
return fmt.Errorf(
|
||||
"left operand '%v' [%T] is not compatible with right operand '%v' [%T] with respect to operator %q",
|
||||
"left operand '%v' [%T] and right operand '%v' [%T] are not compatible with operator %q",
|
||||
leftValue, leftValue,
|
||||
rightValue, rightValue,
|
||||
self.source())
|
||||
|
Loading…
Reference in New Issue
Block a user