Fixed #131 : Implement ExprToConditions

Fixed #130 : ArithmeticOperatorParser
Fixed #129 : python_wrapper : create_namespace
Fixed #128 : ExpressionParser: Cannot parse func(x) infixed concept 'xxx'
This commit is contained in:
2021-10-13 16:06:57 +02:00
parent a61a1c0d2b
commit 89e1f20975
76 changed files with 5867 additions and 3206 deletions
@@ -0,0 +1,129 @@
import pytest
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.ArithmericOperatorParser import ArithmeticOperatorParser
from parsers.BaseExpressionParser import LeftPartNotFoundError, ParenthesisMismatchError, RightPartNotFoundError
from parsers.BaseParser import ErrorSink
from parsers.ExpressionParser import ExpressionParser
from parsers.FunctionParser import FunctionParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
from tests.parsers.parsers_utils import ADD, DIV, EXPR, FDIV, FN, LT, MOD, MULT, POW, SEQ, SUB, VAR, \
get_expr_node_from_test_node
class TestArithmeticOperatorParser(TestUsingMemoryBasedSheerka):
def init_parser(self, expr_parser=None, function_parser=None):
sheerka, context = self.init_concepts()
expr_parser = expr_parser or ExpressionParser(auto_compile=False)
parser = ArithmeticOperatorParser(expr_parser=expr_parser, function_parser=function_parser)
return sheerka, context, parser
@pytest.mark.parametrize("expression, expected", [
("one complicated expression", VAR("one complicated expression")),
("a + b", ADD(VAR("a"), VAR("b"))),
("a - b", SUB("a", "b")),
("a * b", MULT("a", "b")),
("a / b", DIV("a", "b")),
("a // b", FDIV("a", "b")),
("a % b", MOD("a", "b")),
("a ** b", POW("a", "b")),
("a + b * c", ADD("a", MULT("b", "c"))),
("a * b + c", ADD(MULT("a", "b"), "c")),
("a * b ** c", MULT("a", POW("b", "c"))),
("a ** b * c", MULT(POW("a", "b"), "c")),
("(a + b) * c", MULT(ADD("a", "b"), "c", source="(a + b) * c")),
("a * (b + c)", MULT("a", ADD("b", "c"), source="a * (b + c)")),
("func(a, b) * 3", MULT(FN(EXPR("func"), EXPR("a"), EXPR("b")), EXPR("3"))),
("3 * func(a, b)", MULT(EXPR("3"), FN(EXPR("func"), EXPR("a"), EXPR("b")))),
("a + b + c", ADD("a", "b", "c")),
("a - b - c", SUB("a", "b", "c")),
("a + b - c - d", SUB(ADD("a", "b"), "c", "d")),
("a * b * c + d + e + f", ADD(MULT("a", "b", "c"), "d", "e", "f")),
("a + b < c", ADD("a", LT("b", "c"))), # this is possible is function_parser is not set
("foo x + y", SEQ(EXPR("foo "), ADD("x", "y"))), # to manager concept call
("long name concept x + y + z", SEQ(EXPR("long name concept "), ADD("x", "y", "z"))),
("long name concept x + y - z", SEQ(EXPR("long name concept "), SUB(ADD("x", "y"), "z"))),
("long name concept x + y * z", SEQ(EXPR("long name concept "), ADD("x", MULT("y", "z")))),
("long name concept x * y + z", SEQ(EXPR("long name concept "), ADD(MULT("x", "y"), "z"))),
("(foo x) + y", ADD("foo x", "y", source="(foo x) + y")),
("a + foo x + y", ADD("a", SEQ(EXPR("foo "), ADD("x", "y")))),
("a + b * foo x * y + z", ADD("a", MULT("b", SEQ(EXPR("foo "), ADD(MULT("x", "y"), "z"))))),
("a + foo b + c + bar e + f", ADD("a", SEQ(EXPR("foo "), ADD("b", "c", SEQ(EXPR("bar "), ADD("e", "f")))))),
("a + foo x", ADD("a", "foo x")),
("a + x y bar + b - c", ADD("a", SEQ(EXPR("x y "), SUB(ADD("bar", "b"), "c")))),
("a + x + y bar + b - c", ADD("a", "x", SEQ(EXPR("y "), SUB(ADD("bar", "b"), "c")))),
("a + x ? y : z + b - c", ADD("a", SEQ(EXPR("x ? y : "), SUB(ADD("z", "b"), "c")))),
("twenty one + 3", SEQ(EXPR("twenty "), ADD("one", EXPR("3")))),
("(foo x) * (bar y)", MULT("foo x", "bar y", source="(foo x) * (bar y)"))
])
def test_i_can_parse_input_expression(self, expression, expected):
sheerka, context, parser = self.init_parser()
parser_input = ParserInput(expression).reset()
parser_input.next_token()
error_sink = ErrorSink()
expr = parser.parse_input(context, parser_input, error_sink)
assert not error_sink.has_error
expected = get_expr_node_from_test_node(expression, expected, default_expr_obj=VAR)
assert expr == expected
@pytest.mark.parametrize("expression, expected", [
("one complicated expression", VAR("one complicated expression")),
("a + b", ADD(VAR("a"), VAR("b"))),
("func(a, b) * 3", MULT(FN(EXPR("func"), EXPR("a"), EXPR("b")), EXPR("3"))),
("3 * func(a, b)", MULT(EXPR("3"), FN(EXPR("func"), EXPR("a"), EXPR("b")))),
("a + b < c", ADD("a", EXPR("b < c"))), # the comparison is no longer recognized
("foo x + y", SEQ(EXPR("foo "), ADD("x", "y"))), # to manager concept call
("long name concept x + y + z", SEQ(EXPR("long name concept "), ADD("x", "y", "z"))),
("long name concept x + y - z", SEQ(EXPR("long name concept "), SUB(ADD("x", "y"), "z"))),
("long name concept x + y * z", SEQ(EXPR("long name concept "), ADD("x", MULT("y", "z")))),
("long name concept x * y + z", SEQ(EXPR("long name concept "), ADD(MULT("x", "y"), "z"))),
("(foo x) + y", ADD("foo x", "y", source="(foo x) + y")),
("a + foo x + y", ADD("a", SEQ(EXPR("foo "), ADD("x", "y")))),
("a + b * foo x * y + z", ADD("a", MULT("b", SEQ(EXPR("foo "), ADD(MULT("x", "y"), "z"))))),
("a + foo b + c + bar e + f", ADD("a", SEQ(EXPR("foo "), ADD("b", "c", SEQ(EXPR("bar "), ADD("e", "f")))))),
("a + foo x", ADD("a", "foo x")),
("a + x y bar + b - c", ADD("a", SEQ(EXPR("x y "), SUB(ADD("bar", "b"), "c")))),
("a + x + y bar + b - c", ADD("a", "x", SEQ(EXPR("y "), SUB(ADD("bar", "b"), "c")))),
("a + x ? y : z + b - c", ADD("a", SEQ(EXPR("x ? y : "), SUB(ADD("z", "b"), "c")))),
("(foo x) * (bar y) + 2", ADD(MULT("foo x", "bar y", source="(foo x) * (bar y)"), EXPR("2"))),
])
def test_i_can_parse_input_when_function_parser_is_set(self, expression, expected):
sheerka, context, parser = self.init_parser(function_parser=FunctionParser())
parser_input = ParserInput(expression).reset()
parser_input.next_token()
error_sink = ErrorSink()
expr = parser.parse_input(context, parser_input, error_sink)
assert not error_sink.has_error
expected = get_expr_node_from_test_node(expression, expected, default_expr_obj=VAR)
assert expr == expected
@pytest.mark.parametrize("expression, expected_error, expr_is_none", [
("a +", [RightPartNotFoundError], False),
("+ a", [LeftPartNotFoundError], True),
("a ++ b", [RightPartNotFoundError], False),
("(a + b", [ParenthesisMismatchError], False),
# ("a + b)", [ParenthesisMismatchError], False), # only detected is strict is on
])
def test_i_can_detect_errors(self, expression, expected_error, expr_is_none):
sheerka, context, parser = self.init_parser()
parser_input = ParserInput(expression).reset()
parser_input.next_token()
error_sink = ErrorSink()
expr = parser.parse_input(context, parser_input, error_sink)
assert error_sink.has_error
assert (expr is None) == expr_is_none
resolved_errors = [type(e) for e in error_sink.sink]
assert resolved_errors == expected_error