From 28e3b2f7411595bae8d4d2554a6e35ca5b589c10 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Sun, 31 Mar 2024 06:10:27 +0200 Subject: [PATCH] parser: accepts espression forest (multi expressions) --- parser.go | 5 ++ parser_test.go | 211 +++++++++++++++++++++++++------------------------ 2 files changed, 112 insertions(+), 104 deletions(-) diff --git a/parser.go b/parser.go index e73da2a..ed266a3 100644 --- a/parser.go +++ b/parser.go @@ -81,6 +81,11 @@ func (self *parser) parse(scanner *scanner, termSymbols ...Symbol) (tree *ast, e continue } + if tk.Sym == SymSemiColon { + tree.ToForest() + continue + } + //fmt.Println("Token:", tk) if firstToken && (tk.Sym == SymMinus || tk.Sym == SymPlus) { if tk.Sym == SymMinus { diff --git a/parser_test.go b/parser_test.go index dfa6421..33888b2 100644 --- a/parser_test.go +++ b/parser_test.go @@ -19,112 +19,115 @@ func TestParser(t *testing.T) { } // inputs1 := []inputType{ - // {`true AND true`, true, nil}, + // {`a=5; a`, int64(5), nil}, + // {`a=5; b=2; add(a, b*3)`, int64(11), nil}, // {`"a" < "b" AND ~ 2 == 1`, true, nil}, // } inputs := []inputType{ - /* 1 */ {`1+/*5*/2`, int64(3), nil}, - /* 2 */ {`3 == 4`, false, nil}, - /* 3 */ {`3 != 4`, true, nil}, - /* 4 */ {`4 == (3-1)*(10/5)`, true, nil}, - /* 5 */ {`3 <= 4`, true, nil}, - /* 6 */ {`3 < 4`, true, nil}, - /* 7 */ {`4 < 3`, false, nil}, - /* 8 */ {`1+5 < 4`, false, nil}, - /* 9 */ {`3 > 4`, false, nil}, - /* 10 */ {`4 >= 4`, true, nil}, - /* 11 */ {`4 > 3`, true, nil}, - /* 12 */ {`1+5 > 4`, true, nil}, - /* 13 */ {`true`, true, nil}, - /* 14 */ {`not true`, false, nil}, - /* 15 */ {`true and false`, false, nil}, - /* 16 */ {`true or false`, true, nil}, - /* 17 */ {`"uno" + "due"`, `unodue`, nil}, - /* 18 */ {`"uno" + 2`, `uno2`, nil}, - /* 19 */ {`"uno" + (2+1)`, `uno3`, nil}, - /* 20 */ {`"uno" * (2+1)`, `unounouno`, nil}, - /* 21 */ {"1", int64(1), nil}, - /* 22 */ {"1.5", float64(1.5), nil}, - /* 23 */ {"1.5*2", float64(3.0), nil}, - /* 24 */ {"+1", int64(1), nil}, - /* 25 */ {"-1", int64(-1), nil}, - /* 26 */ {"435 + 105 * 2 - 1", int64(644), nil}, - /* 27 */ {"200 / 2 - 1", int64(99), nil}, - /* 28 */ {"(1+1)", int64(2), nil}, - /* 29 */ {"-(1+1)", int64(-2), nil}, - /* 30 */ {"-(-2+1)", int64(1), nil}, - /* 31 */ {"(1+1)*5", int64(10), nil}, - /* 32 */ {"200 / (1+1) - 1", int64(99), nil}, - /* 33 */ {`add(1,2,3)`, int64(6), nil}, - /* 34 */ {`mulX(1,2,3)`, nil, errors.New(`unknown function mulX()`)}, - /* 35 */ {`add(1+4,3+2,5*(3-2))`, int64(15), nil}, - /* 36 */ {`add(add(1+4),3+2,5*(3-2))`, int64(15), nil}, - /* 37 */ {`add(add(1,4),/*3+2,*/5*(3-2))`, int64(10), nil}, - /* 38 */ {`1+(1+(1+(1)+1)+1)+1`, int64(7), nil}, - /* 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] 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`)}, - /* 46 */ {"", nil, errors.New(`empty expression`)}, - /* 47 */ {"4!", int64(24), nil}, - /* 48 */ {"(-4)!", nil, errors.New(`factorial of a negative integer (-4) is not allowed`)}, - /* 49 */ {"-4!", int64(-24), nil}, - /* 50 */ {"1.5 < 7", true, nil}, - /* 51 */ {"1.5 > 7", false, nil}, - /* 52 */ {"1.5 <= 7", true, nil}, - /* 53 */ {"1.5 >= 7", false, nil}, - /* 54 */ {"1.5 != 7", true, nil}, - /* 55 */ {"1.5 == 7", false, nil}, - /* 56 */ {`"1.5" < "7"`, true, nil}, - /* 57 */ {`"1.5" > "7"`, false, nil}, - /* 58 */ {`"1.5" == "7"`, false, nil}, - /* 59 */ {`"1.5" != "7"`, true, nil}, - /* 60 */ {"1.5 < ", nil, errors.New(`infix operator "<" requires two operands, got 1`)}, - /* 61 */ {"1.5 > ", nil, errors.New(`infix operator ">" requires two operands, got 1`)}, - /* 62 */ {"1.5 <= ", nil, errors.New(`infix operator "<=" requires two operands, got 1`)}, - /* 63 */ {"1.5 >= ", nil, errors.New(`infix operator ">=" requires two operands, got 1`)}, - /* 64 */ {"1.5 != ", nil, errors.New(`infix operator "!=" requires two operands, got 1`)}, - /* 65 */ {"1.5 == ", nil, errors.New(`infix operator "==" requires two operands, got 1`)}, - /* 66 */ {`"1.5" < `, nil, errors.New(`infix operator "<" requires two operands, got 1`)}, - /* 67 */ {`"1.5" > `, nil, errors.New(`infix operator ">" requires two operands, got 1`)}, - /* 68 */ {`"1.5" == `, nil, errors.New(`infix operator "==" requires two operands, got 1`)}, - /* 69 */ {`"1.5" != `, nil, errors.New(`infix operator "!=" requires two operands, got 1`)}, - /* 70 */ {"+1.5", float64(1.5), nil}, - /* 71 */ {"+", nil, errors.New(`prefix operator "+" requires one operand`)}, - /* 72 */ {"4 / 0", nil, errors.New(`division by zero`)}, - /* 73 */ {"4.0 / 0", nil, errors.New(`division by zero`)}, - /* 74 */ {"4.0 / \n2", float64(2.0), nil}, - /* 75 */ {`123`, int64(123), nil}, - /* 76 */ {`1.`, float64(1.0), nil}, - /* 77 */ {`1.E-2`, float64(0.01), nil}, - /* 78 */ {`1E2`, float64(100), nil}, - /* 79 */ {`1 / 2`, int64(0), nil}, - /* 80 */ {`1.0 / 2`, float64(0.5), nil}, - /* 81 */ {`1 ./ 2`, float64(0.5), nil}, - /* 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] 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}, - /* 89 */ {`~ 2 > 1`, false, nil}, - /* 90 */ {`~ true && true`, false, nil}, - /* 91 */ {`~ false || true`, true, nil}, - /* 92 */ {`false but true`, true, nil}, - /* 93 */ {`2+3 but 5*2`, int64(10), nil}, - /* 94 */ {`add(1,2) but var2`, "abc", nil}, - /* 95 */ {`x=2`, int64(2), nil}, - /* 96 */ {`x=2 but x*10`, int64(20), nil}, - /* 97 */ {`false and true`, false, nil}, - /* 98 */ {`false and (x==2)`, false, nil}, - /* 99 */ {`false and (x=2 but x==2) or x==2`, nil, errors.New(`undefined variable "x"`)}, - /*100 */ {`false or true`, true, nil}, - /*101 */ {`false or (x==2)`, nil, errors.New(`undefined variable "x"`)}, + /* 1 */ {`1+/*5*/2`, int64(3), nil}, + /* 2 */ {`3 == 4`, false, nil}, + /* 3 */ {`3 != 4`, true, nil}, + /* 4 */ {`4 == (3-1)*(10/5)`, true, nil}, + /* 5 */ {`3 <= 4`, true, nil}, + /* 6 */ {`3 < 4`, true, nil}, + /* 7 */ {`4 < 3`, false, nil}, + /* 8 */ {`1+5 < 4`, false, nil}, + /* 9 */ {`3 > 4`, false, nil}, + /* 10 */ {`4 >= 4`, true, nil}, + /* 11 */ {`4 > 3`, true, nil}, + /* 12 */ {`1+5 > 4`, true, nil}, + /* 13 */ {`true`, true, nil}, + /* 14 */ {`not true`, false, nil}, + /* 15 */ {`true and false`, false, nil}, + /* 16 */ {`true or false`, true, nil}, + /* 17 */ {`"uno" + "due"`, `unodue`, nil}, + /* 18 */ {`"uno" + 2`, `uno2`, nil}, + /* 19 */ {`"uno" + (2+1)`, `uno3`, nil}, + /* 20 */ {`"uno" * (2+1)`, `unounouno`, nil}, + /* 21 */ {"1", int64(1), nil}, + /* 22 */ {"1.5", float64(1.5), nil}, + /* 23 */ {"1.5*2", float64(3.0), nil}, + /* 24 */ {"+1", int64(1), nil}, + /* 25 */ {"-1", int64(-1), nil}, + /* 26 */ {"435 + 105 * 2 - 1", int64(644), nil}, + /* 27 */ {"200 / 2 - 1", int64(99), nil}, + /* 28 */ {"(1+1)", int64(2), nil}, + /* 29 */ {"-(1+1)", int64(-2), nil}, + /* 30 */ {"-(-2+1)", int64(1), nil}, + /* 31 */ {"(1+1)*5", int64(10), nil}, + /* 32 */ {"200 / (1+1) - 1", int64(99), nil}, + /* 33 */ {`add(1,2,3)`, int64(6), nil}, + /* 34 */ {`mulX(1,2,3)`, nil, errors.New(`unknown function mulX()`)}, + /* 35 */ {`add(1+4,3+2,5*(3-2))`, int64(15), nil}, + /* 36 */ {`add(add(1+4),3+2,5*(3-2))`, int64(15), nil}, + /* 37 */ {`add(add(1,4),/*3+2,*/5*(3-2))`, int64(10), nil}, + /* 38 */ {`1+(1+(1+(1)+1)+1)+1`, int64(7), nil}, + /* 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] 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`)}, + /* 46 */ {"", nil, errors.New(`empty expression`)}, + /* 47 */ {"4!", int64(24), nil}, + /* 48 */ {"(-4)!", nil, errors.New(`factorial of a negative integer (-4) is not allowed`)}, + /* 49 */ {"-4!", int64(-24), nil}, + /* 50 */ {"1.5 < 7", true, nil}, + /* 51 */ {"1.5 > 7", false, nil}, + /* 52 */ {"1.5 <= 7", true, nil}, + /* 53 */ {"1.5 >= 7", false, nil}, + /* 54 */ {"1.5 != 7", true, nil}, + /* 55 */ {"1.5 == 7", false, nil}, + /* 56 */ {`"1.5" < "7"`, true, nil}, + /* 57 */ {`"1.5" > "7"`, false, nil}, + /* 58 */ {`"1.5" == "7"`, false, nil}, + /* 59 */ {`"1.5" != "7"`, true, nil}, + /* 60 */ {"1.5 < ", nil, errors.New(`infix operator "<" requires two operands, got 1`)}, + /* 61 */ {"1.5 > ", nil, errors.New(`infix operator ">" requires two operands, got 1`)}, + /* 62 */ {"1.5 <= ", nil, errors.New(`infix operator "<=" requires two operands, got 1`)}, + /* 63 */ {"1.5 >= ", nil, errors.New(`infix operator ">=" requires two operands, got 1`)}, + /* 64 */ {"1.5 != ", nil, errors.New(`infix operator "!=" requires two operands, got 1`)}, + /* 65 */ {"1.5 == ", nil, errors.New(`infix operator "==" requires two operands, got 1`)}, + /* 66 */ {`"1.5" < `, nil, errors.New(`infix operator "<" requires two operands, got 1`)}, + /* 67 */ {`"1.5" > `, nil, errors.New(`infix operator ">" requires two operands, got 1`)}, + /* 68 */ {`"1.5" == `, nil, errors.New(`infix operator "==" requires two operands, got 1`)}, + /* 69 */ {`"1.5" != `, nil, errors.New(`infix operator "!=" requires two operands, got 1`)}, + /* 70 */ {"+1.5", float64(1.5), nil}, + /* 71 */ {"+", nil, errors.New(`prefix operator "+" requires one operand`)}, + /* 72 */ {"4 / 0", nil, errors.New(`division by zero`)}, + /* 73 */ {"4.0 / 0", nil, errors.New(`division by zero`)}, + /* 74 */ {"4.0 / \n2", float64(2.0), nil}, + /* 75 */ {`123`, int64(123), nil}, + /* 76 */ {`1.`, float64(1.0), nil}, + /* 77 */ {`1.E-2`, float64(0.01), nil}, + /* 78 */ {`1E2`, float64(100), nil}, + /* 79 */ {`1 / 2`, int64(0), nil}, + /* 80 */ {`1.0 / 2`, float64(0.5), nil}, + /* 81 */ {`1 ./ 2`, float64(0.5), nil}, + /* 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] 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}, + /* 89 */ {`~ 2 > 1`, false, nil}, + /* 90 */ {`~ true && true`, false, nil}, + /* 91 */ {`~ false || true`, true, nil}, + /* 92 */ {`false but true`, true, nil}, + /* 93 */ {`2+3 but 5*2`, int64(10), nil}, + /* 94 */ {`add(1,2) but var2`, "abc", nil}, + /* 95 */ {`x=2`, int64(2), nil}, + /* 96 */ {`x=2 but x*10`, int64(20), nil}, + /* 97 */ {`false and true`, false, nil}, + /* 98 */ {`false and (x==2)`, false, nil}, + /* 99 */ {`false and (x=2 but x==2) or x==2`, nil, errors.New(`undefined variable "x"`)}, + /* 100 */ {`false or true`, true, nil}, + /* 101 */ {`false or (x==2)`, nil, errors.New(`undefined variable "x"`)}, + /* 102 */ {`a=5; a`, int64(5), nil}, + /* 103 */ {`a=5; b=2; add(a, b*3)`, int64(11), nil}, } succeeded := 0 failed := 0 @@ -272,8 +275,8 @@ func NoTestListParser(t *testing.T) { func logTest(t *testing.T, n int, source string, wantResult any, wantErr error) { if wantErr == nil { - t.Log(fmt.Sprintf("[+]Test nr %2d -- %q --> %v", n, source, wantResult)) + t.Log(fmt.Sprintf("[+]Test nr %3d -- %q --> %v", n, source, wantResult)) } else { - t.Log(fmt.Sprintf("[-]Test nr %2d -- %q --> %v", n, source, wantErr)) + t.Log(fmt.Sprintf("[-]Test nr %3d -- %q --> %v", n, source, wantErr)) } }