1239 lines
54 KiB
Python
1239 lines
54 KiB
Python
import pytest
|
|
from core.builtin_concepts import BuiltinConcepts
|
|
from core.concept import Concept, CC
|
|
from core.tokenizer import Tokenizer
|
|
from parsers.BaseNodeParser import utnode, ConceptNode, cnode, short_cnode, UnrecognizedTokensNode, \
|
|
SCWC, CNC, UTN
|
|
from parsers.PythonParser import PythonNode
|
|
from parsers.SyaNodeParser import SyaNodeParser, SyaConceptParserHelper, SyaAssociativity, \
|
|
NoneAssociativeSequenceErrorNode, TooManyParametersFound
|
|
|
|
import tests.parsers.parsers_utils
|
|
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
|
|
|
|
|
|
def compute_expected_array(concepts_map, expression, expected):
|
|
return tests.parsers.parsers_utils.compute_expected_array(concepts_map, expression, expected, sya=True)
|
|
|
|
|
|
cmap = {
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
"four": Concept("four"),
|
|
"plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
"minus": Concept("a minus b").def_var("a").def_var("b"),
|
|
"mult": Concept("a mult b").def_var("a").def_var("b"),
|
|
"prefixed": Concept("a prefixed").def_var("a"),
|
|
"suffixed": Concept("suffixed a").def_var("a"),
|
|
"infix": Concept("a infix b").def_var("a").def_var("b"),
|
|
"?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
"if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
|
|
"square": Concept("square(a)").def_var("a"),
|
|
"foo bar": Concept("foo bar(a)").def_var("a"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
}
|
|
|
|
|
|
class TestSyaNodeParser(TestUsingMemoryBasedSheerka):
|
|
sheerka = None
|
|
|
|
@classmethod
|
|
def setup_class(cls):
|
|
t = TestSyaNodeParser()
|
|
TestSyaNodeParser.sheerka, context, _ = t.init_parser(
|
|
cmap,
|
|
singleton=False,
|
|
create_new=True,
|
|
init_from_sheerka=True)
|
|
|
|
TestSyaNodeParser.sheerka.force_sya_def(context, [
|
|
(cmap["plus"].id, 5, SyaAssociativity.Right),
|
|
(cmap["mult"].id, 10, SyaAssociativity.Right),
|
|
(cmap["minus"].id, 10, SyaAssociativity.Right),
|
|
(cmap["square"].id, None, SyaAssociativity.No)])
|
|
|
|
def init_parser(self,
|
|
my_concepts_map=None,
|
|
sya_def=None,
|
|
post_init_concepts=None,
|
|
**kwargs):
|
|
|
|
if my_concepts_map is not None:
|
|
# a new concept map is given
|
|
# use it but
|
|
# do not instantiate a new sheerka
|
|
# do not update / init from sheerka
|
|
if 'singleton' not in kwargs:
|
|
kwargs["singleton"] = True
|
|
init_from_sheerka = kwargs.get("init_from_sheerka", False)
|
|
sheerka, context, *concepts = self.init_concepts(*my_concepts_map.values(), **kwargs)
|
|
else:
|
|
# No custom concept map is given -> Use the global cmap
|
|
# Sheerka is already initialized (the class instance)
|
|
# Use it to initialize the parser
|
|
init_from_sheerka = kwargs.get("init_from_sheerka", True)
|
|
sheerka = TestSyaNodeParser.sheerka
|
|
context = self.get_context(sheerka)
|
|
concepts = cmap.values()
|
|
|
|
if post_init_concepts:
|
|
post_init_concepts(sheerka, context)
|
|
|
|
if sya_def:
|
|
sya_def_to_use = {}
|
|
for k, v in sya_def.items():
|
|
sya_def_to_use[k.id] = v
|
|
else:
|
|
sya_def_to_use = None
|
|
|
|
if init_from_sheerka:
|
|
parser = SyaNodeParser(sheerka=sheerka)
|
|
else:
|
|
parser = SyaNodeParser()
|
|
if my_concepts_map:
|
|
parser.init_from_concepts(context, concepts, sya=sya_def_to_use)
|
|
|
|
return sheerka, context, parser
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("one plus two", [["one", "two", "plus"]]),
|
|
("1 + 1 plus two", [["1 + 1 ", "two", "plus"]]),
|
|
("one + two plus three", [
|
|
["one", " + ", "two", "three", "plus"],
|
|
["one + two ", "three", "plus"]]),
|
|
("twenty one plus two", [
|
|
["twenty ", "one", "two", "plus"],
|
|
[short_cnode("twenties", "twenty one"), "two", "plus"]
|
|
]),
|
|
("x$!# plus two", [["x$!# ", "two", "plus"]]),
|
|
|
|
("one plus 1 + 1", [["one", " 1 + 1", "plus"]]),
|
|
("1 + 1 plus 2 + 2", [["1 + 1 ", " 2 + 2", "plus"]]),
|
|
("one + two plus 1 + 1", [
|
|
["one", " + ", "two", " 1 + 1", "plus"],
|
|
["one + two ", " 1 + 1", "plus"]
|
|
]),
|
|
("twenty one plus 1 + 1", [
|
|
["twenty ", "one", " 1 + 1", "plus"],
|
|
[cnode("twenties", 0, 2, "twenty one"), " 1 + 1", "plus"]
|
|
]),
|
|
("x$!# plus 1 + 1", [["x$!# ", " 1 + 1", "plus"]]),
|
|
|
|
("one plus two + three", [
|
|
["one", "two", "plus", " + ", "three"],
|
|
["one", " two + three", "plus"],
|
|
]),
|
|
("1 + 1 plus two + three", [
|
|
["1 + 1 ", "two", "plus", (" + ", 1), "three"],
|
|
["1 + 1 ", " two + three", "plus"],
|
|
]),
|
|
("one + two plus two + three", [
|
|
["one", " + ", "two", ("two", 1), "plus", (" + ", 1), "three"],
|
|
["one + two ", ("two", 1), "plus", (" + ", 1), "three"],
|
|
["one", " + ", "two", " two + three", "plus"],
|
|
["one + two ", " two + three", "plus"],
|
|
]),
|
|
("twenty one plus two + three", [
|
|
["twenty ", "one", "two", "plus", " + ", "three"],
|
|
[cnode("twenties", 0, 2, "twenty one"), "two", "plus", " + ", "three"],
|
|
["twenty ", "one", " two + three", "plus"],
|
|
[cnode("twenties", 0, 2, "twenty one"), " two + three", "plus"],
|
|
]),
|
|
("x$!# plus two + three", [
|
|
["x$!# ", "two", "plus", " + ", "three"],
|
|
["x$!# ", " two + three", "plus"],
|
|
]),
|
|
|
|
("one plus twenty two", [
|
|
["one", " twenty ", "plus", "two"],
|
|
["one", cnode("twenties", 4, 6, "twenty two"), "plus"],
|
|
]),
|
|
("1 + 1 plus twenty one", [
|
|
["1 + 1 ", " twenty ", "plus", "one"],
|
|
["1 + 1 ", cnode("twenties", 8, 10, "twenty one"), "plus"],
|
|
]),
|
|
("one + two plus twenty one", [
|
|
["one", " + ", "two", " twenty ", "plus", ("one", 1)],
|
|
["one + two ", " twenty ", "plus", ("one", 1)],
|
|
["one", " + ", "two", cnode("twenties", 8, 10, "twenty one"), "plus"],
|
|
["one + two ", cnode("twenties", 8, 10, "twenty one"), "plus"],
|
|
]),
|
|
("twenty one plus twenty two",
|
|
[
|
|
["twenty ", "one", " twenty ", "plus", "two"],
|
|
[cnode("twenties", 0, 2, "twenty one"), " twenty ", "plus", "two"],
|
|
["twenty ", "one", cnode("twenties", 6, 8, "twenty two"), "plus"],
|
|
[cnode("twenties", 0, 2, "twenty one"), cnode("twenties", 6, 8, "twenty two"), "plus"],
|
|
]),
|
|
("x$!# plus twenty two", [
|
|
["x$!# ", " twenty ", "plus", "two"],
|
|
["x$!# ", cnode("twenties", 7, 9, "twenty two"), "plus"]
|
|
]),
|
|
|
|
("one plus z$!#", [["one", " z$!#", "plus"]]),
|
|
("1 + 1 plus z$!#", [["1 + 1 ", " z$!#", "plus"]]),
|
|
("one + two plus z$!#", [
|
|
["one", " + ", "two", " z$!#", "plus"],
|
|
["one + two ", " z$!#", "plus"],
|
|
]),
|
|
("twenty one plus z$!#", [
|
|
["twenty ", "one", " z$!#", "plus"],
|
|
[cnode("twenties", 0, 2, "twenty one"), " z$!#", "plus"],
|
|
]),
|
|
("x$!# plus z$!#", [["x$!# ", " z$!#", "plus"]]),
|
|
])
|
|
def test_i_can_post_fix_simple_infix_concepts(self, expression, expected_sequences):
|
|
# concepts_map = {
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
assert len(res_i.errors) == 0
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("one plus plus plus 1 + 1", [["one", " 1 + 1", "plus plus plus"]]),
|
|
("x$!# another long name infix twenty two", [
|
|
["x$!# ", " twenty ", "another long name infix", "two"],
|
|
["x$!# ", cnode("twenties", 13, 15, "twenty two"), "another long name infix"],
|
|
]),
|
|
])
|
|
def test_i_can_post_fix_infix_concepts_with_long_name(self, expression, expected_sequences):
|
|
concepts_map = {
|
|
"plus plus plus": Concept("a plus plus plus b").def_var("a").def_var("b"),
|
|
"another long name infix": Concept("a another long name infix b").def_var("a").def_var("b"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, init_from_sheerka=True)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
assert len(res_i.errors) == 0
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("one prefixed", [["one", "prefixed"]]),
|
|
("1 + 1 prefixed", [["1 + 1 ", "prefixed"]]),
|
|
("one + two prefixed", [
|
|
["one", " + ", "two", "prefixed"],
|
|
["one + two ", "prefixed"],
|
|
]),
|
|
("twenty one prefixed", [
|
|
["twenty ", "one", "prefixed"],
|
|
[cnode("twenties", 0, 2, "twenty one"), "prefixed"],
|
|
]),
|
|
("x$!# prefixed", [["x$!# ", "prefixed"]]),
|
|
])
|
|
def test_i_can_post_fix_simple_prefixed_concepts(self, expression, expected_sequences):
|
|
# concepts_map = {
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
assert len(res_i.errors) == 0
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("one prefixed prefixed", [["one", "prefixed prefixed"]]),
|
|
("1 + 1 prefixed prefixed", [["1 + 1 ", "prefixed prefixed"]]),
|
|
("one + two prefixed prefixed", [
|
|
["one", " + ", "two", "prefixed prefixed"],
|
|
["one + two ", "prefixed prefixed"],
|
|
]),
|
|
("twenty one prefixed prefixed", [
|
|
["twenty ", "one", "prefixed prefixed"],
|
|
[cnode("twenties", 0, 2, "twenty one"), "prefixed prefixed"],
|
|
]),
|
|
("x$!# prefixed prefixed", [["x$!# ", "prefixed prefixed"]]),
|
|
|
|
("one long name prefixed", [["one", "long name prefixed"]]),
|
|
("1 + 1 long name prefixed", [["1 + 1 ", "long name prefixed"]]),
|
|
("one + two long name prefixed", [
|
|
["one", " + ", "two", "long name prefixed"],
|
|
["one + two ", "long name prefixed"],
|
|
]),
|
|
("twenty one long name prefixed", [
|
|
["twenty ", "one", "long name prefixed"],
|
|
[cnode("twenties", 0, 2, "twenty one"), "long name prefixed"],
|
|
]),
|
|
("x$!# long name prefixed", [["x$!# ", "long name prefixed"]]),
|
|
])
|
|
def test_i_can_post_fix_prefixed_concepts_with_long_names(self, expression, expected_sequences):
|
|
concepts_map = {
|
|
"prefixed prefixed": Concept("a prefixed prefixed").def_var("a"),
|
|
"long name prefixed": Concept("a long name prefixed").def_var("a"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, init_from_sheerka=True)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
assert len(res_i.errors) == 0
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("suffixed one", [["one", "suffixed"]]),
|
|
("suffixed 1 + 1", [[" 1 + 1", "suffixed"]]),
|
|
("suffixed one + two", [
|
|
["one", "suffixed", " + ", "two"],
|
|
[" one + two", "suffixed"],
|
|
]),
|
|
("suffixed twenty one", [
|
|
[" twenty ", "suffixed", "one"],
|
|
[cnode("twenties", 2, 4, "twenty one"), "suffixed"],
|
|
]),
|
|
("suffixed x$!#", [[" x$!#", "suffixed"]]),
|
|
])
|
|
def test_i_can_post_fix_simple_suffixed_concepts(self, expression, expected_sequences):
|
|
# concepts_map = {
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
assert len(res_i.errors) == 0
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("suffixed suffixed one", ["one", "suffixed suffixed"]),
|
|
("long name suffixed one", ["one", "long name suffixed"]),
|
|
])
|
|
def test_i_can_post_fix_suffixed_concepts_with_long_names(self, expression, expected):
|
|
concepts_map = {
|
|
"suffixed suffixed": Concept("suffixed suffixed a").def_var("a"),
|
|
"long name suffixed": Concept("long name suffixed a").def_var("a"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("one ? two : three", [["one", "two", "three", "?"]]),
|
|
("1+1 ? one + two : twenty one", [
|
|
["1+1 ", "one", " + ", "two"], # an error is detected
|
|
["1+1 ", " one + two ", " twenty ", "?", ("one", 1)],
|
|
["1+1 ", " one + two ", short_cnode("twenties", "twenty one"), "?"],
|
|
]),
|
|
("x$!# ? y$!# : z$!#", [["x$!# ", " y$!# ", " z$!#", "?"]]),
|
|
|
|
("if one then two else three end", [["one", "two", "three", "if"]]),
|
|
("if 1+1 then x$!# else twenty one end", [
|
|
[" 1+1 ", " x$!# ", " twenty ", "one"], # an error is detected
|
|
[" 1+1 ", " x$!# ", short_cnode("twenties", "twenty one"), "if"],
|
|
]),
|
|
("if x$!# then one + two else z$!# end", [
|
|
[" x$!# ", "one", " + ", "two"], # an error is detected
|
|
[" x$!# ", " one + two ", " z$!# ", "if"],
|
|
]),
|
|
])
|
|
def test_i_can_post_fix_ternary_concepts(self, expression, expected_sequences):
|
|
"""
|
|
The purpose of this test is to validate concepts like
|
|
that have at least 3 parameters separated by tokens
|
|
Example :
|
|
var_0 token var_1 token var_2
|
|
token var_0 token var_1 token var_2
|
|
token var_0 token var_1 token var_2 token
|
|
var_0 token var_1 token var_2 token
|
|
etc...
|
|
:return:
|
|
"""
|
|
|
|
# concepts_map = {
|
|
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
# assert len(res_i.errors) == 0 # Do not validate errors
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
("one ? ? two : : three", [["one", "two", "three", "? ?"]]),
|
|
("1+1 ? ? one + two : : twenty one", [
|
|
["1+1 ", "one", " + ", "two"], # error
|
|
["1+1 ", " one + two ", " twenty ", "? ?", ("one", 1)],
|
|
["1+1 ", " one + two ", short_cnode("twenties", "twenty one"), "? ?"],
|
|
]),
|
|
|
|
("if if one then then two else else three end end ", [["one", "two", "three", "if if"]]),
|
|
("if if 1+1 then then x$!# else else twenty one end end ", [
|
|
[" 1+1 ", " x$!# ", " twenty ", "one"], # error
|
|
[" 1+1 ", " x$!# ", short_cnode("twenties", "twenty one"), "if if"]]),
|
|
])
|
|
def test_i_can_post_fix_ternary_concept_with_long_names(self, expression, expected_sequences):
|
|
concepts_map = {
|
|
"? ?": Concept("a ? ? b : : c").def_var("a").def_var("b").def_var("c"),
|
|
"if if": Concept("if if a then then b else else c end end").def_var("a").def_var("b").def_var("c"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
"twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, create_new=True, init_from_sheerka=True)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
# assert len(res_i.errors) == 0 # Do not validate errors
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("foo bar baz", ["baz", "bar", "foo"]),
|
|
("foo bar x$!#", [" x$!#", "bar", "foo"]),
|
|
("foo bar 1 + 1", [" 1 + 1", "bar", "foo"]),
|
|
])
|
|
def test_i_can_post_fix_suffixed_unary_composition(self, expression, expected):
|
|
concepts_map = {
|
|
"foo": Concept("foo a").def_var("a"),
|
|
"bar": Concept("bar a").def_var("a"),
|
|
"baz": Concept("baz"),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("baz bar foo", ["baz", "bar", "foo"]),
|
|
("x$!# bar foo", ["x$!# ", "bar", "foo"]),
|
|
("1 + 1 bar foo", ["1 + 1 ", "bar", "foo"]),
|
|
])
|
|
def test_i_can_post_fix_prefixed_unary_composition(self, expression, expected):
|
|
concepts_map = {
|
|
"foo": Concept("a foo").def_var("a"),
|
|
"bar": Concept("a bar").def_var("a"),
|
|
"baz": Concept("baz"),
|
|
}
|
|
sya_def = {
|
|
concepts_map["foo"]: (5, SyaAssociativity.Left),
|
|
concepts_map["bar"]: (5, SyaAssociativity.Left), # precedence greater than plus
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("one plus two mult three", ["one", "two", "three", "mult", "plus"]),
|
|
("one mult two plus three", ["one", "two", "mult", "three", "plus"]),
|
|
("(one plus two) mult three", ["one", "two", "plus", "three", "mult"]),
|
|
("one mult (two plus three)", ["one", "two", "three", "plus", "mult"]),
|
|
])
|
|
def test_i_can_post_fix_binary_with_precedence(self, expression, expected):
|
|
# concepts_map = {
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "mult": Concept("a mult b").def_var("a").def_var("b"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# }
|
|
# sya_def = {
|
|
# concepts_map["plus"]: (5, SyaAssociativity.Right),
|
|
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
def test_i_can_post_fix_unary_with_precedence(self):
|
|
concepts_map = {
|
|
"suffixed": Concept("suffixed a").def_var("a"),
|
|
"prefixed": Concept("a prefixed").def_var("a"),
|
|
"a": Concept("a"),
|
|
}
|
|
|
|
sya_def = {
|
|
concepts_map["prefixed"]: (10, SyaAssociativity.Left),
|
|
concepts_map["suffixed"]: (5, SyaAssociativity.Right),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
expression = "suffixed a prefixed"
|
|
expected = ["a", "prefixed", "suffixed"]
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
# change the precedence
|
|
sya_def = {
|
|
concepts_map["prefixed"]: (5, SyaAssociativity.Left),
|
|
concepts_map["suffixed"]: (10, SyaAssociativity.Right),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
expression = "suffixed a prefixed"
|
|
expected = ["a", "suffixed", "prefixed"]
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
def test_i_can_post_fix_right_associated_binary(self):
|
|
concepts_map = {
|
|
"equals": Concept("a equals b").def_var("a").def_var("b"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
}
|
|
|
|
sya_def = {
|
|
concepts_map["equals"]: (None, SyaAssociativity.Right),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
expression = "one equals two equals three"
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
expected = ["one", "two", "three", ("equals", 1), "equals"]
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
def test_i_can_post_fix_left_associated_binary(self):
|
|
concepts_map = {
|
|
"plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
}
|
|
|
|
sya_def = {
|
|
concepts_map["plus"]: (None, SyaAssociativity.Left),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
expression = "one plus two plus three"
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
expected = ["one", "two", "plus", "three", ("plus", 1)]
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("x$!# ? y$!# : z$!# ? two : three", ["x$!# ", " y$!# ", " z$!# ", "two", "three", ("?", 1), "?"]),
|
|
("x$!# ? y$!# : (z$!# ? two : three)", ["x$!# ", " y$!# ", "z$!# ", "two", "three", ("?", 1), "?"]),
|
|
|
|
("one ? x$!# ? y$!# : z$!# : three", ["one", " x$!# ", " y$!# ", " z$!# ", ("?", 1), "three", "?"]),
|
|
("one ? (x$!# ? y$!# : z$!#) : three", ["one", "x$!# ", " y$!# ", " z$!#", ("?", 1), "three", "?"]),
|
|
|
|
("one ? two : x$!# ? y$!# : z$!#", ["one", "two", " x$!# ", " y$!# ", " z$!#", ("?", 1), "?"]),
|
|
("one ? two : (x$!# ? y$!# : z$!#)", ["one", "two", "x$!# ", " y$!# ", " z$!#", ("?", 1), "?"]),
|
|
])
|
|
def test_i_can_post_fix_right_associated_ternary(self, expression, expected):
|
|
concepts_map = {
|
|
"?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
}
|
|
sya_def = {
|
|
concepts_map["?"]: (5, SyaAssociativity.Right),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("x$!# ? y$!# : z$!# ? two : three", ["x$!# ", " y$!# ", " z$!# ", "?", "two", "three", ("?", 1)]),
|
|
("(x$!# ? y$!# : z$!#) ? two : three", ["x$!# ", " y$!# ", " z$!#", "?", "two", "three", ("?", 1)]),
|
|
|
|
# the following one is not possible when Left association
|
|
# ("one ? x$!# ? y$!# : z$!# : three", ["one", " x$!# ", " y$!# ", " z$!# ", ("?", 1), "three", "?"]),
|
|
|
|
("one ? two : x$!# ? y$!# : z$!#", ["one", "two", " x$!# ", "?", " y$!# ", " z$!#", ("?", 1)]),
|
|
("(one ? two : x$!#) ? y$!# : z$!#", ["one", "two", " x$!#", "?", " y$!# ", " z$!#", ("?", 1)]),
|
|
])
|
|
def test_i_can_post_fix_left_associated_ternary(self, expression, expected):
|
|
concepts_map = {
|
|
"?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
}
|
|
sya_def = {
|
|
concepts_map["?"]: (5, SyaAssociativity.Left),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
def test_i_can_post_fix_when_multiple_concepts_are_found(self):
|
|
concepts_map = {
|
|
"foo": Concept("foo a").def_var("a"),
|
|
"foo bar": Concept("foo bar a").def_var("a"),
|
|
"baz": Concept("baz"),
|
|
}
|
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
|
|
|
expression = "foo bar baz"
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_sequences = [
|
|
[UTN(" bar "), "foo", "baz"],
|
|
["baz", "foo bar"]
|
|
]
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
assert len(res_i.errors) == 0
|
|
expected_array = compute_expected_array(concepts_map, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
# I can't manage source code functions :-(
|
|
# ("function(one plus three) minus two", []),
|
|
|
|
("(one plus two) ", ["one", "two", "plus"]),
|
|
("(one prefixed) ", ["one", "prefixed"]),
|
|
("(suffixed one) ", ["one", "suffixed"]),
|
|
("(one ? two : three)", ["one", "two", "three", "?"]),
|
|
("square(square(one))", ["one", ("square", 1), "square"]),
|
|
("square ( square ( one ) )", ["one", ("square", 1), "square"]),
|
|
|
|
("square(one plus three) minus two", ["one", "three", "plus", "square", "two", "minus"]),
|
|
("square( one plus three ) minus two", ["one", "three", "plus", "square", "two", "minus"]),
|
|
("one minus square( two plus three ) ", ["one", "two", "three", "plus", "square", "minus"]),
|
|
|
|
("(one prefixed) prefixed)", ["one", "prefixed", ("prefixed", 1)]),
|
|
("( one prefixed ) prefixed)", ["one", "prefixed", ("prefixed", 1)]),
|
|
("( square( one ) prefixed ) prefixed)", ["one", "square", "prefixed", ("prefixed", 1)]),
|
|
|
|
("suffixed (suffixed one)", ["one", ("suffixed", 1), "suffixed"]),
|
|
("suffixed ( suffixed one) ", ["one", ("suffixed", 1), "suffixed"]),
|
|
("suffixed (suffixed square(one))", ["one", "square", ("suffixed", 1), "suffixed"]),
|
|
("suffixed ( suffixed square ( one ) )", ["one", "square", ("suffixed", 1), "suffixed"]),
|
|
|
|
("one plus (two minus three)", ["one", "two", "three", "minus", "plus"]),
|
|
("one plus ( two minus three )", ["one", "two", "three", "minus", "plus"]),
|
|
("(one plus two) minus three", ["one", "two", "plus", "three", "minus"]),
|
|
("( one plus two ) minus three )", ["one", "two", "plus", "three", "minus"]),
|
|
|
|
("foo bar (one)", ["one", "foo bar"]),
|
|
("foo bar ( one )", ["one", "foo bar"]),
|
|
])
|
|
def test_i_can_pos_fix_when_parenthesis(self, expression, expected):
|
|
# concepts_map = {
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "square": Concept("square(a)").def_var("a"),
|
|
# "foo bar": Concept("foo bar(a)").def_var("a"),
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "minus": Concept("a minus b").def_var("a").def_var("b"),
|
|
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
|
|
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# }
|
|
#
|
|
# sya_def = {
|
|
# concepts_map["square"]: (None, SyaAssociativity.No),
|
|
# concepts_map["plus"]: (10, SyaAssociativity.Right),
|
|
# concepts_map["minus"]: (10, SyaAssociativity.Right),
|
|
# }
|
|
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected_sequences", [
|
|
# composition
|
|
("function(suffixed one)", [[SCWC("function(", ")", "one", "suffixed")]]),
|
|
("function(one prefixed)", [[SCWC("function(", ")", "one", "prefixed")]]),
|
|
("function(if one then two else three end)", [[SCWC("function(", ")", "one", "two", "three", "if")]]),
|
|
("function(suffixed twenty two)", [
|
|
[SCWC("function(", ")", " twenty ", "suffixed", "two")],
|
|
[SCWC("function(", ")", short_cnode("twenties", "twenty two"), "suffixed")]]),
|
|
("function(twenty two prefixed)", [
|
|
[SCWC("function(", ")", "twenty ", "two", "prefixed")],
|
|
[SCWC("function(", ")", short_cnode("twenties", "twenty two"), "prefixed")],
|
|
]),
|
|
("function(if one then twenty two else three end)", [
|
|
["')'", "one", " twenty ", "two"], # error
|
|
[SCWC("function(", ")", "one", short_cnode("twenties", "twenty two"), "three", "if")]
|
|
]),
|
|
("func1(func2(one two) three)", [
|
|
[SCWC("func1(", (")", 1), SCWC("func2(", ")", "one", "two"), "three")]]),
|
|
|
|
("twenty two(suffixed one)", [
|
|
["twenty ", SCWC("two(", ")", "one", "suffixed")],
|
|
[SCWC("twenty two(", ")", "one", "suffixed")],
|
|
]),
|
|
("twenty two(one prefixed)", [
|
|
["twenty ", SCWC("two(", ")", "one", "prefixed")],
|
|
[SCWC("twenty two(", ")", "one", "prefixed")],
|
|
]),
|
|
("f1(one plus two mult three) plus f2(suffixed x$!# prefixed)", [
|
|
[SCWC("f1(", ")", "one", "two", "three", "mult", "plus"),
|
|
SCWC(" f2(", (")", 1), " x$!# ", "prefixed", "suffixed"),
|
|
("plus", 1)]
|
|
]),
|
|
|
|
# plus, suffixed, prefixed, ternary
|
|
("func1(one) plus func2(two)", [[SCWC("func1(", ")", "one"), SCWC(" func2(", (")", 1), "two"), "plus"]]),
|
|
("suffixed function(one)", [[SCWC(" function(", ")", "one"), "suffixed"]]),
|
|
("function(one) prefixed", [[SCWC("function(", ")", "one"), "prefixed"]]),
|
|
("if f1(one) then f2(two) else f3(three) end", [
|
|
[SCWC(" f1(", ")", "one"), SCWC(" f2(", (")", 1), "two"), SCWC(" f3(", (")", 2), "three"), "if"]]),
|
|
|
|
# Sequence
|
|
("if one then two else three end function(x$!#)", [
|
|
["one", "two", "three", "if", SCWC(" function(", ")", "x$!#")]]),
|
|
("one prefixed function(two)", [["one", "prefixed", SCWC(" function(", ")", "two")]]),
|
|
("suffixed one function(two)", [["one", "suffixed", SCWC(" function(", ")", "two")]]),
|
|
])
|
|
def test_i_can_post_fix_when_parenthesis_and_unknown(self, expression, expected_sequences):
|
|
# concepts_map = {
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "mult": Concept("a mult b").def_var("a").def_var("b"),
|
|
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
# sya_def = {
|
|
# concepts_map["plus"]: (5, SyaAssociativity.Right),
|
|
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == len(expected_sequences)
|
|
for res_i, expected in zip(res, expected_sequences):
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
assert res_i.out == expected_array
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("(", ("(", 0)),
|
|
("one plus ( 1 + ", ("(", 4)),
|
|
("one( 1 + ", ("(", 1)),
|
|
("one ( 1 + ", ("(", 2)),
|
|
("function( 1 + ", ("(", 1)),
|
|
("function ( 1 + ", ("(", 2)),
|
|
("one plus ) 1 + ", (")", 4)),
|
|
("one ) 1 + ", (")", 2)),
|
|
("function ) 1 + ", (")", 2)),
|
|
("one ? ( : two", ("(", 4)),
|
|
("one ? one plus ( : two", ("(", 8)),
|
|
("one ? ) : two", (")", 4)),
|
|
("one ? one plus ) : two", (")", 8)),
|
|
("(one plus ( 1 + )", ("(", 0)),
|
|
])
|
|
def test_i_can_detect_parenthesis_mismatch_error_when_post_fixing(self, expression, expected):
|
|
# concepts_map = {
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].errors == [expected]
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("one ? one two : three", ("?", ":")),
|
|
])
|
|
def test_i_can_detected_when_too_many_parameters(self, expression, expected):
|
|
# concepts_map = {
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser(cmap, None)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
assert len(res) == 1
|
|
assert len(res[0].errors) == 1
|
|
error = res[0].errors[0]
|
|
assert isinstance(error, TooManyParametersFound)
|
|
assert error.concept == cmap[expected[0]]
|
|
assert error.token.value == expected[1]
|
|
|
|
@pytest.mark.parametrize("expression, expected", [
|
|
("one infix two x$!#", ["one", "two", "infix", " x$!#"]),
|
|
("x$!# one infix two", ["x$!# ", "one", "two", "infix"]),
|
|
("one prefixed x$!#", ["one", "prefixed", " x$!#"]),
|
|
("x$!# one prefixed", ["x$!# ", "one", "prefixed"]),
|
|
("suffixed one x$!#", ["one", "suffixed", " x$!#"]),
|
|
("x$!# suffixed one", ["x$!# ", "one", "suffixed"]),
|
|
("one ? two : three x$!#", ["one", "two", "three", "?", " x$!#"]),
|
|
("x$!# one ? two : three", ["x$!# ", "one", "two", "three", "?"]),
|
|
|
|
("one infix two three infix four", ["one", "two", "infix", "three", "four", ("infix", 1)]),
|
|
("one infix two three prefixed", ["one", "two", "infix", "three", "prefixed"]),
|
|
("one infix two suffixed three", ["one", "two", "infix", "three", "suffixed"]),
|
|
("one infix two x$!# ? y$!# : z$!#", ["one", "two", "infix", " x$!# ", " y$!# ", " z$!#", "?"]),
|
|
|
|
("one prefixed two infix three", ["one", "prefixed", "two", "three", "infix"]),
|
|
("one prefixed two prefixed", ["one", "prefixed", "two", ("prefixed", 1)]),
|
|
("one prefixed suffixed two", ["one", "prefixed", "two", "suffixed"]),
|
|
("one prefixed x$!# ? y$!# : z$!#", ["one", "prefixed", " x$!# ", " y$!# ", " z$!#", "?"]),
|
|
|
|
("(one infix two) (three prefixed)", ["one", "two", "infix", "three", "prefixed"]),
|
|
])
|
|
def test_i_can_post_fix_sequences(self, expression, expected):
|
|
# concepts_map = {
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "infix": Concept("a infix b").def_var("a").def_var("b"),
|
|
# "?": Concept("a ? b : c").def_var("a").def_var("b").def_var("c"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "four": Concept("four"),
|
|
# }
|
|
|
|
sheerka, context, parser = self.init_parser(cmap, None)
|
|
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
def test_the_more_concepts_the_more_results(self):
|
|
concepts_map = {
|
|
"plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
"plus plus": Concept("a plus plus").def_var("a"),
|
|
"plus equals": Concept("a plus equals b").def_var("a").def_var("b"),
|
|
}
|
|
|
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
|
|
|
expression = "a plus plus equals b"
|
|
res = parser.infix_to_postfix(context, expression)
|
|
expected_array = tests.parsers.parsers_utils.compute_debug_array(res)
|
|
assert expected_array == [
|
|
["a", "a plus b", "a plus b", "equals", "b"],
|
|
["a", "a plus b", "a plus plus", "equals", "b"],
|
|
["a", "a plus b", "a plus equals b", "equals", "b"],
|
|
["a", "a plus plus", "plus", "equals", "b"],
|
|
["a", "a plus plus", "plus", "equals", "b"],
|
|
["a", "a plus plus", "plus", "equals", "b"],
|
|
["a", "a plus equals b", "a plus b", "equals", "b"],
|
|
["a", "a plus equals b", "a plus plus", "equals", "b"],
|
|
["a", "a plus equals b", "a plus equals b", "equals", "b"],
|
|
]
|
|
|
|
def test_i_can_use_string_instead_of_identifier(self):
|
|
concepts_map = {
|
|
"ternary": Concept("a ? ? b '::' c").def_var("a").def_var("b").def_var("c"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
}
|
|
|
|
sheerka, context, parser = self.init_parser(concepts_map, None)
|
|
|
|
res = parser.infix_to_postfix(context, "one ? ? two '::' three")
|
|
assert len(res) == 1
|
|
assert res[0].out == [
|
|
cnode("one", start=0, end=0, source="one"),
|
|
cnode("two", start=6, end=6, source="two"),
|
|
cnode("three", start=10, end=10, source="three"),
|
|
SyaConceptParserHelper(concepts_map["ternary"], 2),
|
|
]
|
|
|
|
def test_i_cannot_chain_non_associative(self):
|
|
concepts_map = {
|
|
"less than": Concept("a less than b").def_var("a").def_var("b"),
|
|
"one": Concept("one"),
|
|
"two": Concept("two"),
|
|
"three": Concept("three"),
|
|
}
|
|
sya_def = {
|
|
concepts_map["less than"]: (None, SyaAssociativity.No),
|
|
}
|
|
|
|
sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
|
|
res = parser.infix_to_postfix(context, "one less than two less than three")
|
|
assert len(res) == 1
|
|
assert res[0].errors == [NoneAssociativeSequenceErrorNode(concepts_map["less than"], 2, 8)]
|
|
|
|
def test_i_can_post_fix_bnf_definition(self):
|
|
"""
|
|
The definition of a BNF concept is considered as an atom concept
|
|
Not quite sure why this test is here
|
|
:return:
|
|
"""
|
|
# concepts_map = {
|
|
# "foo": Concept("foo a").def_var("a"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser(cmap, None)
|
|
|
|
expression = "suffixed twenties"
|
|
res = parser.infix_to_postfix(context, expression)
|
|
|
|
expected = [cnode("twenties", 2, 2, "twenties"), "suffixed"]
|
|
expected_array = compute_expected_array(cmap, expression, expected)
|
|
assert len(res) == 1
|
|
assert res[0].out == expected_array
|
|
|
|
def test_i_can_parse_when_concept_atom_only(self):
|
|
# concepts_map = {
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "mult": Concept("a mult b").def_var("a").def_var("b"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# }
|
|
# sya_def = {
|
|
# concepts_map["plus"]: (5, SyaAssociativity.Right),
|
|
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
text = "one plus two mult three"
|
|
res = parser.parse(context, text)
|
|
wrapper = res.body
|
|
lexer_nodes = res.body.body
|
|
|
|
assert res.status
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == [ConceptNode(cmap["plus"], 0, 8, source=text)]
|
|
|
|
# check the compiled
|
|
expected_concept = lexer_nodes[0].concept
|
|
assert expected_concept.compiled["a"] == cmap["one"]
|
|
assert expected_concept.compiled["b"] == cmap["mult"]
|
|
assert expected_concept.compiled["b"].compiled["a"] == cmap["two"]
|
|
assert expected_concept.compiled["b"].compiled["b"] == cmap["three"]
|
|
|
|
def test_i_can_parse_when_python_code(self):
|
|
# concepts_map = {
|
|
# "foo": Concept("foo a").def_var("a")
|
|
# }
|
|
sheerka, context, parser = self.init_parser(cmap, None)
|
|
|
|
text = "suffixed 1 + 1"
|
|
res = parser.parse(context, text)
|
|
wrapper = res.body
|
|
lexer_nodes = res.body.body
|
|
|
|
assert res.status
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == [ConceptNode(cmap["suffixed"], 0, 6, source=text)]
|
|
|
|
# check the compiled
|
|
expected_concept = lexer_nodes[0].concept
|
|
assert len(expected_concept.compiled["a"]) == 1
|
|
|
|
return_value_a = expected_concept.compiled["a"][0]
|
|
assert sheerka.isinstance(return_value_a, BuiltinConcepts.RETURN_VALUE)
|
|
assert return_value_a.status
|
|
assert sheerka.isinstance(return_value_a.body, BuiltinConcepts.PARSER_RESULT)
|
|
assert return_value_a.body.source == " 1 + 1"
|
|
assert isinstance(return_value_a.body.body, PythonNode)
|
|
|
|
def test_i_can_parse_when_bnf_concept(self):
|
|
# concepts_map = {
|
|
# "foo": Concept("foo a").def_var("a"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
text = "suffixed twenty one"
|
|
res = parser.parse(context, text)
|
|
assert len(res) == 2
|
|
assert res[1].status
|
|
|
|
wrapper = res[1].body
|
|
lexer_nodes = res[1].body.body
|
|
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == [ConceptNode(cmap["suffixed"], 0, 4, source=text)]
|
|
|
|
# check the compiled
|
|
expected_concept = lexer_nodes[0].concept
|
|
assert sheerka.isinstance(expected_concept.compiled["a"], "twenties")
|
|
assert expected_concept.compiled["a"].compiled["unit"] == cmap["one"]
|
|
|
|
def test_i_can_parse_sequences(self):
|
|
# concepts_map = {
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "foo": Concept("foo a").def_var("a"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser(cmap, None)
|
|
|
|
text = "one plus 1 + 1 suffixed two"
|
|
res = parser.parse(context, text)
|
|
wrapper = res.body
|
|
lexer_nodes = res.body.body
|
|
|
|
assert res.status
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == [
|
|
ConceptNode(cmap["plus"], 0, 9, source="one plus 1 + 1 "),
|
|
ConceptNode(cmap["suffixed"], 10, 12, source="suffixed two")]
|
|
|
|
# check the compiled
|
|
concept_plus_a = lexer_nodes[0].concept.compiled["a"]
|
|
concept_plus_b = lexer_nodes[0].concept.compiled["b"]
|
|
concept_suffixed_a = lexer_nodes[1].concept.compiled["a"]
|
|
|
|
assert concept_plus_a == cmap["one"]
|
|
assert len(concept_plus_b) == 1
|
|
assert sheerka.isinstance(concept_plus_b[0], BuiltinConcepts.RETURN_VALUE)
|
|
assert isinstance(concept_plus_b[0].body.body, PythonNode)
|
|
assert concept_suffixed_a == cmap["two"]
|
|
|
|
@pytest.mark.parametrize("text, expected_status, expected_result", [
|
|
("function(suffixed one)", True, [
|
|
SCWC("function(", ")", CNC("suffixed", 2, 4, a="one"))]),
|
|
("function(one plus two mult three)", True, [
|
|
SCWC("function(", ")", CNC("plus", 2, 10, a="one", b=CC("mult", a="two", b="three")))]),
|
|
("f1(one prefixed) plus f2(suffixed two)", True, [
|
|
CNC("plus",
|
|
a=SCWC("f1(", ")", CNC("prefixed", a="one")),
|
|
b=SCWC(" f2(", (")", 1), CNC("suffixed", a="two")))
|
|
]),
|
|
("function(suffixed x$!#)", False, [
|
|
SCWC("function(", ")", CNC("suffixed", 2, 7, a=" x$!#"))]),
|
|
])
|
|
def test_i_can_parse_when_one_result(self, text, expected_status, expected_result):
|
|
# concepts_map = {
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "mult": Concept("a mult b").def_var("a").def_var("b"),
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
# sya_def = {
|
|
# concepts_map["plus"]: (5, SyaAssociativity.Right),
|
|
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
wrapper = res.body
|
|
lexer_nodes = res.body.body
|
|
|
|
expected_array = compute_expected_array(cmap, text, expected_result)
|
|
assert res.status == expected_status
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == expected_array
|
|
|
|
# @pytest.mark.parametrize("text, list_of_expected", [
|
|
# ("1 plus twenty one", [
|
|
# (False, [CNC("plus", a=scnode(0, 0, "1"), b=UTN(" twenty ")), CN("one")]),
|
|
# (True, [CNC("plus", a=scnode(0, 0, "1"), b=CN("twenties", source="twenty one"))])
|
|
# ])
|
|
# ])
|
|
# def test_i_can_parse_when_multiple_results(self, text, list_of_expected):
|
|
# concepts_map = {
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "mult": Concept("a mult b").def_var("a").def_var("b"),
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "if": Concept("if a then b else c end").def_var("a").def_var("b").def_var("c"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
# sya_def = {
|
|
# concepts_map["plus"]: (5, SyaAssociativity.Right),
|
|
# concepts_map["mult"]: (10, SyaAssociativity.Right), # precedence greater than plus
|
|
# }
|
|
# sheerka, context, parser = self.init_parser(concepts_map, sya_def)
|
|
#
|
|
# list_of_res = parser.parse(context, text)
|
|
# assert len(list_of_res) == len(list_of_expected)
|
|
#
|
|
# for res, expected in zip(list_of_res, list_of_expected):
|
|
# wrapper = res.body
|
|
# lexer_nodes = res.body.body
|
|
# assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
#
|
|
# expected_array = compute_expected_array(concepts_map, text, expected[1])
|
|
# assert res.status == expected[0]
|
|
# assert lexer_nodes == expected_array
|
|
|
|
@pytest.mark.parametrize("text, expected_concept, expected_unrecognized", [
|
|
("x$!# prefixed", "prefixed", ["a"]),
|
|
("suffixed x$!#", "suffixed", ["a"]),
|
|
("one infix x$!#", "infix", ["b"]),
|
|
("x$!# infix one", "infix", ["a"]),
|
|
("x$!# infix z$!#", "infix", ["a", "b"]),
|
|
])
|
|
def test_i_cannot_parse_when_unrecognized(self, text, expected_concept, expected_unrecognized):
|
|
# concepts_map = {
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "infix": Concept("a infix b").def_var("a").def_var("b"),
|
|
# "one": Concept("one")
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
wrapper = res.body
|
|
lexer_nodes = res.body.body
|
|
expected_end = len(list(Tokenizer(text))) - 2
|
|
|
|
assert not res.status
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == [ConceptNode(cmap[expected_concept], 0, expected_end, source=text)]
|
|
|
|
concept_found = lexer_nodes[0].concept
|
|
for unrecognized in expected_unrecognized:
|
|
assert isinstance(concept_found.compiled[unrecognized], UnrecognizedTokensNode)
|
|
|
|
@pytest.mark.parametrize("text, expected", [
|
|
("x$!# suffixed one", [utnode(0, 4, "x$!# "), cnode("suffixed __var__0", 5, 7, "suffixed one")]),
|
|
("one prefixed x$!#", [cnode("__var__0 prefixed", 0, 2, "one prefixed"), utnode(3, 7, " x$!#")]),
|
|
])
|
|
def test_i_cannot_parse_when_part_of_the_sequence_is_not_recognized(self, text, expected):
|
|
# concepts_map = {
|
|
# "suffixed": Concept("suffixed a").def_var("a"),
|
|
# "prefixed": Concept("a prefixed").def_var("a"),
|
|
# "infix": Concept("a infix b").def_var("a").def_var("b"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
wrapper = res.body
|
|
lexer_nodes = res.body.body
|
|
|
|
assert not res.status
|
|
assert context.sheerka.isinstance(wrapper, BuiltinConcepts.PARSER_RESULT)
|
|
assert lexer_nodes == expected
|
|
|
|
@pytest.mark.parametrize("text", [
|
|
"one",
|
|
"1 + 1",
|
|
"x$!# ",
|
|
"twenty one"
|
|
"",
|
|
"function(not an sya concept)",
|
|
])
|
|
def test_i_cannot_parse_when_no_concept_is_recognized(self, text):
|
|
"""
|
|
it's actually no concept with property
|
|
Atoms concepts, source code or BNF concepts alone are discarded by the lexer
|
|
:return:
|
|
"""
|
|
# concepts_map = {
|
|
# "plus": Concept("a plus b").def_var("a").def_var("b"),
|
|
# "one": Concept("one"),
|
|
# "two": Concept("two"),
|
|
# "three": Concept("three"),
|
|
# "twenties": Concept("twenties", definition="'twenty' (one|two)=unit").def_var("unit"),
|
|
# }
|
|
sheerka, context, parser = self.init_parser()
|
|
|
|
res = parser.parse(context, text)
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOR_ME)
|
|
assert res.body.body == text
|
|
|
|
def test_i_cannot_parse_empty_string(self):
|
|
sheerka, context, parser = self.init_parser({}, None)
|
|
|
|
res = parser.parse(context, "")
|
|
|
|
assert not res.status
|
|
assert sheerka.isinstance(res.body, BuiltinConcepts.IS_EMPTY)
|