Fixed #55 : DefConceptParser: failed to recognize concept

Fixed #62 : DefConceptParser: parsing error
Fixed #64 : DefConceptParser: Failed to parse when too many concept keyword
Fixed #65 : DefConceptParser : Add auto_eval keyword
Fixed #66 : DefConceptParser : Add def_var keyword
Fixed #67 : Add get_errors()
This commit is contained in:
2021-04-13 15:15:17 +02:00
parent 81e67147e9
commit bef5f3208c
17 changed files with 838 additions and 235 deletions
+115 -58
View File
@@ -7,7 +7,7 @@ from core.concept import VARIABLE_PREFIX, Concept, DEFINITION_TYPE_BNF, DEFINITI
from core.sheerka.services.SheerkaConceptManager import NoFirstTokenError
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Tokenizer
from evaluators.DefConceptEvaluator import DefConceptEvaluator
from evaluators.DefConceptEvaluator import DefConceptEvaluator, PossibleVariable, CertainVariable
from parsers.BaseParser import BaseParser
from parsers.BnfDefinitionParser import BnfDefinitionParser
from parsers.BnfNodeParser import Sequence, StrMatch, ZeroOrMore, ConceptExpression, VariableExpression
@@ -144,20 +144,112 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert created_concept.get_metadata().definition == "hello a"
assert created_concept.get_metadata().definition_type == "def"
def test_i_can_add_concept_with_the_correct_variables_when_referencing_other_concepts(self):
@pytest.mark.parametrize("expression, name, expected", [
("isinstance(a, str)", "a b", {"a"}),
("a.location = b", "a is in b", {"a", "b"}),
("a.location = b", "'a' is in b", {"b"}),
("date.today()", "what is the date", set()),
("a.location", "where is a", {"a"})
])
def test_i_can_get_variables_from_python_node_when_long_name(self, expression, name, expected):
ret_val = self.get_concept_part(expression)
context = self.get_context()
def_concept_return_value = self.get_def_concept(
name="x plus y",
where=self.pretval(Concept("u is a v").def_var("u").def_var("v"), source="x is a number"),
body=self.pretval(Concept("add a b").def_var("a").def_var("b"), source="add x y"), )
evaluated = DefConceptEvaluator().eval(context, def_concept_return_value)
resolved_expected = [PossibleVariable(e) for e in expected]
assert DefConceptEvaluator.get_variables(context, ret_val, name.split()) == resolved_expected
def test_i_can_get_variables_when_keywords(self):
sheerka, context = self.init_concepts()
def_concept = self.get_def_concept("condition pre").value.value
name_to_use = DefConceptEvaluator.get_name_to_use(def_concept)
concept_part = self.get_concept_part("pre")
assert DefConceptEvaluator.get_variables(context, concept_part, name_to_use) == [PossibleVariable("pre")]
def test_i_can_get_variable_when_rule_is_defined(self):
sheerka, context = self.init_test().unpack()
def_concept_parser = DefConceptParser()
parsed_ret_val = def_concept_parser.parse(context, ParserInput("def concept rule x as r:|x:"))
assert parsed_ret_val.status # sanity check
evaluated = DefConceptEvaluator().eval(context, parsed_ret_val)
assert evaluated.status
assert evaluated.body.body.key == "rule __var__0"
assert evaluated.body.body.get_metadata().variables == [("x", None)]
def test_i_cannot_get_variables_from_python_node_when_name_has_only_one_token(self):
ret_val = self.get_concept_part("isinstance(a, str)")
context = self.get_context()
assert DefConceptEvaluator.get_variables(context, ret_val, ["a"]) == []
def test_i_can_get_variables_from_definition(self):
parsing_expression = Sequence(ConceptExpression('mult'),
ZeroOrMore(Sequence(StrMatch("+"), ConceptExpression("add"))))
ret_val = self.get_return_value("mult (('+'|'-') add)?", parsing_expression)
expected = [CertainVariable("mult"), CertainVariable("add")]
assert DefConceptEvaluator.get_variables(self.get_context(), ret_val, []) == expected
def test_i_can_get_variable_from_bnf_definition_2(self):
sheerka, context, one, two = self.init_concepts("one", "two")
text = "def concept twenties from bnf 'twenty' (one|two)=unit as 20 + unit"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
concept_definition = def_ret_val.value.body.definition
expected = [CertainVariable("unit"), CertainVariable("one"), CertainVariable("two")]
assert DefConceptEvaluator.get_variables(context, concept_definition, []) == expected
def test_i_can_recognize_variables_when_referencing_other_concepts(self):
sheerka, context, isa_concept = self.init_concepts(Concept("x is an y").def_var("x").def_var("y"))
text = "def concept what x is y pre is_question() where x is an adjective as get_attr(x, y)"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
new_concept = evaluated.body.body
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
assert new_concept.get_metadata().variables == [('x', None), ('y', None)]
created_concept = evaluated.body.body
assert created_concept.get_metadata().variables == [("x", None), ("y", None)]
def test_i_can_recognize_variables_when_given_in_concept_definition(self):
sheerka, context = self.init_test().unpack()
text = "def concept a plus b as a + b def_var plus"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
new_concept = evaluated.body.body
assert evaluated.status
assert new_concept.get_metadata().variables == [('plus', None)]
def test_i_can_recognize_variables_when_referencing_other_concepts_with_variable_mapping(self):
sheerka, context, number, isa, add = self.init_concepts(
"number",
Concept("u is a v").def_var("u").def_var("v"),
Concept("add a b").def_var("a").def_var("b")
)
text = "def concept x plus y where x is a number as add x y"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
new_concept = evaluated.body.body
assert evaluated.status
assert new_concept.get_metadata().variables == [('x', None), ('y', None)]
def test_i_do_no_mixed_up_concept_and_variable_name(self):
sheerka, context, activate_debug = self.init_concepts(Concept("activate debug"))
text = "def concept debug on as activate debug"
def_ret_val = DefConceptParser().parse(context, ParserInput(text))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
new_concept = evaluated.body.body
assert evaluated.status
assert new_concept.get_metadata().variables == []
def test_other_concepts_are_not_variables(self):
sheerka, context, *concepts = self.init_test().with_concepts("little", "size", create_new=True).unpack()
@@ -166,7 +258,7 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
name_to_use = DefConceptEvaluator.get_name_to_use(def_concept_node)
concept_part = self.get_concept_part("set_attr(x, size, little)")
assert DefConceptEvaluator.get_variables(context, concept_part, name_to_use) == {"x"}
assert DefConceptEvaluator.get_variables(context, concept_part, name_to_use) == [PossibleVariable("x")]
def test_that_the_new_concept_is_correctly_saved_in_db(self):
context = self.get_context()
@@ -199,41 +291,6 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert from_db.get_compiled() == {} # ast is not saved in db
@pytest.mark.parametrize("expression, name, expected", [
("isinstance(a, str)", "a b", {"a"}),
("a.location = b", "a is in b", {"a", "b"}),
("a.location = b", "'a' is in b", {"b"}),
("date.today()", "what is the date", set()),
("a.location", "where is a", {"a"})
])
def test_i_can_get_variables_from_python_node_when_long_name(self, expression, name, expected):
ret_val = self.get_concept_part(expression)
context = self.get_context()
assert DefConceptEvaluator.get_variables(context, ret_val, name.split()) == expected
def test_i_can_get_variables_when_keywords(self):
sheerka, context = self.init_concepts()
def_concept = self.get_def_concept("condition pre").value.value
name_to_use = DefConceptEvaluator.get_name_to_use(def_concept)
concept_part = self.get_concept_part("pre")
assert DefConceptEvaluator.get_variables(context, concept_part, name_to_use) == {"pre"}
def test_i_cannot_get_variables_from_python_node_when_name_has_only_one_token(self):
ret_val = self.get_concept_part("isinstance(a, str)")
context = self.get_context()
assert DefConceptEvaluator.get_variables(context, ret_val, ["a"]) == set()
def test_i_can_get_variables_from_definition(self):
parsing_expression = Sequence(ConceptExpression('mult'),
ZeroOrMore(Sequence(StrMatch("+"), ConceptExpression("add"))))
ret_val = self.get_return_value("mult (('+'|'-') add)?", parsing_expression)
assert DefConceptEvaluator.get_variables(self.get_context(), ret_val, []) == {"add", "mult"}
def test_concept_that_references_itself_is_correctly_created(self):
context = self.get_context()
def_concept_as_return_value = self.get_def_concept("foo", body="foo")
@@ -247,18 +304,6 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert new_concept.values() == {}
assert new_concept.get_metadata().variables == []
def test_i_can_get_variable_when_rule_is_defined(self):
sheerka, context = self.init_test().unpack()
def_concept_parser = DefConceptParser()
parsed_ret_val = def_concept_parser.parse(context, ParserInput("def concept rule x as r:|x:"))
assert parsed_ret_val.status # sanity check
evaluated = DefConceptEvaluator().eval(context, parsed_ret_val)
assert evaluated.status
assert evaluated.body.body.key == "rule __var__0"
assert evaluated.body.body.get_metadata().variables == [("x", None)]
def test_i_can_recognize_variable_when_keyword_argument(self):
sheerka, context = self.init_test().unpack()
def_concept_parser = DefConceptParser()
@@ -309,7 +354,19 @@ class TestDefConceptEvaluator(TestUsingMemoryBasedSheerka):
assert created_concept.get_metadata().variables == [("x", None)]
assert created_concept._bnf == Sequence(StrMatch("hello"), VariableExpression("x"))
def test_i_can_eval_when_auto_eval_is_true(self):
sheerka, context = self.init_test().unpack()
def_ret_val = DefConceptParser().parse(context, ParserInput("def concept foo auto_eval True"))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)
assert evaluated.status
assert context.sheerka.isinstance(evaluated.body, BuiltinConcepts.NEW_CONCEPT)
created_concept = evaluated.body.body
assert sheerka.get_property(created_concept, BuiltinConcepts.ISA) == {sheerka.new(BuiltinConcepts.AUTO_EVAL)}
def test_i_cannot_eval_bnf_concept_with_unknown_variable(self):
# testing MandatoryVariable
context = self.get_context()
def_ret_val = DefConceptParser().parse(context, ParserInput("def concept name from bnf unknown foo"))
evaluated = DefConceptEvaluator().eval(context, def_ret_val)