177 lines
7.0 KiB
Python
177 lines
7.0 KiB
Python
import pytest
|
|
from core.builtin_concepts import BuiltinConcepts
|
|
from core.concept import Concept
|
|
from core.sheerka.services.SheerkaExecute import ParserInput
|
|
from parsers.BaseNodeParser import SCN, SCWC, CN, UTN, CNC
|
|
from parsers.FunctionParser import FunctionParser, FN
|
|
|
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
from tests.parsers.parsers_utils import compute_expected_array
|
|
|
|
cmap = {
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
"plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
}
|
|
|
|
|
|
class TestFunctionParser(TestUsingMemoryBasedSheerka):
|
|
sheerka = None
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
t = cls()
|
|
cls.sheerka, context, _ = t.init_parser(cmap)
|
|
|
|
def init_parser(self, concepts_map=None):
|
|
if concepts_map is not None:
|
|
sheerka, context, *concepts = self.init_concepts(*concepts_map.values(), create_new=True)
|
|
else:
|
|
sheerka = TestFunctionParser.sheerka
|
|
context = self.get_context(sheerka)
|
|
|
|
parser = FunctionParser()
|
|
return sheerka, context, parser
|
|
|
|
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_input_must_be_a_parser_input(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
parser.parse(context, "not a parser input") is None
|
|
|
|
def test_i_cannot_parse_when_not_a_function(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
res = parser.parse(context, ParserInput("not a function"))
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("func()", FN("func(", ")", [])),
|
|
("concept(one)", FN("concept(", ")", ["one"])),
|
|
("func(one)", FN("func(", ")", ["one"])),
|
|
("func(a long two, 'three', ;:$*)", FN("func(", ")", ["a long two, ", "'three', ", ";:$*"])),
|
|
("func(func1(one), two, func2(func3(), func4(three)))", FN("func(", ")", [
|
|
(FN("func1(", ")", ["one"]), ", "),
|
|
"two, ",
|
|
(FN("func2(", ")", [
|
|
(FN("func3(", ")", []), ", "),
|
|
(FN("func4(", ")", ["three"]), None),
|
|
]), None)
|
|
])),
|
|
])
|
|
def test_i_can_parse_function(self, expression, expected):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
parser.reset_parser(context, ParserInput(expression))
|
|
res = parser.parse_function()
|
|
|
|
assert res == expected
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("func()", SCN("func()")),
|
|
(" func()", SCN("func()")),
|
|
("func(one)", SCWC("func(", ")", CN("one"))),
|
|
("func(one, unknown, two)", SCWC("func(", ")", CN("one"), ", ", UTN("unknown"), (", ", 1), CN("two"))),
|
|
("func(one, twenty two)", SCWC("func(", ")", "one", ", ", CN("twenties", source="twenty two"))),
|
|
("func(one plus two, three)", SCWC("func(", ")", CNC("plus", a="one", b="two"), ", ", UTN("three"))),
|
|
("func(func1(one), two)", SCWC("func(", (")", 1), SCWC("func1(", ")", "one"), ", ", "two"))
|
|
])
|
|
def test_i_can_parse(self, text, expected):
|
|
sheerka, context, parser = self.init_parser()
|
|
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
|
|
|
|
res = parser.parse(context, ParserInput(text))
|
|
parser_result = res.body
|
|
expression = res.body.body
|
|
|
|
assert res.status
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert expression == resolved_expected
|
|
assert expression.python_node is not None
|
|
assert expression.return_value is not None
|
|
|
|
def test_i_can_parse_when_multiple_results_when_requested(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
parser.longest_concepts_only = False
|
|
text = "func(one, twenty two)"
|
|
expected = [SCWC("func(", ")", "one", ", ", "twenty ", "two"),
|
|
SCWC("func(", ")", "one", ", ", CN("twenties", source="twenty two"))]
|
|
all_resolved_expected = compute_expected_array(cmap, text, expected)
|
|
|
|
results = parser.parse(context, ParserInput(text))
|
|
|
|
assert len(results) == 2
|
|
|
|
for res, resolved_expected in zip(results, all_resolved_expected):
|
|
parser_result = res.body
|
|
expressions = res.body.body
|
|
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert expressions == resolved_expected
|
|
|
|
@pytest.mark.parametrize("text, expected_error_type", [
|
|
("one", BuiltinConcepts.NOT_FOR_ME),
|
|
("$*!", BuiltinConcepts.NOT_FOR_ME),
|
|
("func(", BuiltinConcepts.ERROR),
|
|
("func(one", BuiltinConcepts.ERROR),
|
|
("func(one, two, ", BuiltinConcepts.ERROR),
|
|
("func(one) and func(two)", BuiltinConcepts.ERROR),
|
|
("one func(one)", BuiltinConcepts.NOT_FOR_ME),
|
|
])
|
|
def test_i_cannot_parse(self, text, expected_error_type):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, ParserInput(text))
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(res.body, expected_error_type)
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("func(one two)", SCWC("func(", ")", "one", "two")),
|
|
])
|
|
def test_i_can_detect_non_function(self, text, expected):
|
|
sheerka, context, parser = self.init_parser()
|
|
resolved_expected = compute_expected_array(cmap, text, [expected])[0]
|
|
|
|
res = parser.parse(context, ParserInput(text))
|
|
parser_result = res.body
|
|
expression = res.body.body
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(parser_result, BuiltinConcepts.PARSER_RESULT)
|
|
assert expression == resolved_expected
|
|
assert expression.python_node is None
|
|
assert expression.return_value is None
|
|
|
|
@pytest.mark.parametrize("sequence, expected", [
|
|
(None, None),
|
|
([["a"]], [["a"]]),
|
|
([["a"], ["b", "c"]], [["a"]]),
|
|
([["b", "c"], ["a"]], [["a"]]),
|
|
([["b", "c"], ["a"], ["d", "e"], ["f"]], [["a"], ["f"]]),
|
|
])
|
|
def test_i_can_get_the_longest_concept_sequence(self, sequence, expected):
|
|
assert FunctionParser.get_longest_concepts(sequence) == expected
|
|
|
|
def test_concepts_found_are_fully_initialized(self):
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, ParserInput("func(one plus three)"))
|
|
concept = res.body.body.nodes[0].concept
|
|
|
|
assert res.status
|
|
assert isinstance(concept.compiled["a"], Concept)
|
|
|
|
# three is not recognized,
|
|
# so it will be transformed into list of ReturnValueConcept that indicate how to recognized it
|
|
assert isinstance(concept.compiled["b"], list)
|
|
for item in concept.compiled["b"]:
|
|
assert sheerka.isinstance(item, BuiltinConcepts.RETURN_VALUE)
|