89e1f20975
Fixed #130 : ArithmeticOperatorParser Fixed #129 : python_wrapper : create_namespace Fixed #128 : ExpressionParser: Cannot parse func(x) infixed concept 'xxx'
130 lines
7.0 KiB
Python
130 lines
7.0 KiB
Python
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
|