First implementation of questions management
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
from core.builtin_concepts import BuiltinConcepts, ReturnValueConcept
|
||||
from core.concept import Concept
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.tokenizer import Tokenizer, TokenKind
|
||||
from parsers.BaseParser import UnexpectedEof, UnexpectedTokenErrorNode
|
||||
from parsers.ExpressionParser import PropertyEqualsNode, PropertyEqualsSequenceNode, PropertyContainsNode, AndNode, \
|
||||
OrNode, NotNode, LambdaNode, IsaNode
|
||||
OrNode, NotNode, LambdaNode, IsaNode, NameExprNode, ExpressionParser, LeftPartNotFoundError, TrueifyVisitor
|
||||
|
||||
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
||||
|
||||
@@ -16,8 +20,93 @@ class Obj:
|
||||
parent: object = None
|
||||
|
||||
|
||||
def n(value):
|
||||
return NameExprNode(Tokenizer(value, yield_eof=False))
|
||||
|
||||
|
||||
class TestExpressionParser(TestUsingMemoryBasedSheerka):
|
||||
|
||||
def init_parser(self):
|
||||
sheerka, context = self.init_concepts()
|
||||
parser = ExpressionParser()
|
||||
return sheerka, context, parser
|
||||
|
||||
@pytest.mark.parametrize("expression, expected", [
|
||||
("one complicated expression", n("one complicated expression")),
|
||||
("function_call(a,b,c)", n("function_call(a,b,c)")),
|
||||
("one expression or another expression", OrNode(n("one expression"), n("another expression"))),
|
||||
("one expression and another expression", AndNode(n("one expression"), n("another expression"))),
|
||||
("one or two or three", OrNode(n("one"), n("two"), n("three"))),
|
||||
("one and two and three", AndNode(n("one"), n("two"), n("three"))),
|
||||
("one or two and three", OrNode(n("one"), AndNode(n("two"), n("three")))),
|
||||
("one and two or three", OrNode(AndNode(n("one"), n("two")), n("three"))),
|
||||
("one and (two or three)", AndNode(n("one"), OrNode(n("two"), n("three")))),
|
||||
])
|
||||
def test_i_can_parse_expression(self, expression, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput(expression))
|
||||
wrapper = res.body
|
||||
expressions = res.body.body
|
||||
|
||||
assert res.status
|
||||
assert sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
||||
assert expressions == expected
|
||||
|
||||
@pytest.mark.parametrize("expression, expected_errors", [
|
||||
("one or", [UnexpectedEof("When parsing 'or'")]),
|
||||
("one and", [UnexpectedEof("When parsing 'and'")]),
|
||||
("and one", [LeftPartNotFoundError()]),
|
||||
("or one", [LeftPartNotFoundError()]),
|
||||
("or", [LeftPartNotFoundError(), UnexpectedEof("When parsing 'or'")]),
|
||||
("and", [LeftPartNotFoundError(), UnexpectedEof("When parsing 'and'")]),
|
||||
])
|
||||
def test_i_can_detect_error(self, expression, expected_errors):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput(expression))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert res.body.body == expected_errors
|
||||
|
||||
def test_i_can_detect_unbalanced_parenthesis(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
|
||||
res = parser.parse(context, ParserInput("("))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.EOF
|
||||
assert res.body.body[0].expected_tokens == [TokenKind.RPAR]
|
||||
|
||||
res = parser.parse(context, ParserInput(")"))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.RPAR
|
||||
assert res.body.body[0].expected_tokens == []
|
||||
|
||||
res = parser.parse(context, ParserInput("one and two)"))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.RPAR
|
||||
assert res.body.body[0].expected_tokens == []
|
||||
|
||||
res = parser.parse(context, ParserInput("one and two)"))
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.ERROR)
|
||||
assert isinstance(res.body.body[0], UnexpectedTokenErrorNode)
|
||||
assert res.body.body[0].token.type == TokenKind.RPAR
|
||||
assert res.body.body[0].expected_tokens == []
|
||||
|
||||
def test_i_can_detect_empty_expression(self):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
res = parser.parse(context, ParserInput(""))
|
||||
|
||||
assert not res.status
|
||||
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
|
||||
|
||||
def test_i_can_test_property_equals(self):
|
||||
node = PropertyEqualsNode("prop_a", "good value")
|
||||
|
||||
@@ -101,3 +190,21 @@ class TestExpressionParser(TestUsingMemoryBasedSheerka):
|
||||
assert concept_node2.eval(Concept("foo").init_key())
|
||||
assert not concept_node2.eval(Obj)
|
||||
assert not concept_node2.eval(Concept())
|
||||
|
||||
@pytest.mark.parametrize("expression, to_trueify, to_skip, expected", [
|
||||
("a", ["b"], ["a"], "a"),
|
||||
("b", ["b"], ["a"], "True"),
|
||||
("a and b", ["b"], ["a"], "a and True"),
|
||||
("b or a", ["b"], ["a"], "True or a"),
|
||||
("isinstance(b, str)", ["b"], ["a"], "True"),
|
||||
("isinstance(b, str) or instance(a, str)", ["b"], ["a"], "True or instance(a, str)"),
|
||||
("a and b or c", ["b", "c"], ["a"], "a and True or True"),
|
||||
("a + b or a + c", ["b", "c"], ["a"], "a + b or a + c"),
|
||||
])
|
||||
def test_i_can_trueify(self, expression, to_trueify, to_skip, expected):
|
||||
sheerka, context, parser = self.init_parser()
|
||||
expr_node = parser.parse(context, ParserInput(expression)).body.body
|
||||
|
||||
translated_node = TrueifyVisitor(to_trueify, to_skip).visit(expr_node)
|
||||
|
||||
assert str(translated_node) == expected
|
||||
|
||||
Reference in New Issue
Block a user