First implementation of questions management

This commit is contained in:
2020-08-14 08:16:33 +02:00
parent e84b394da2
commit 351c16f946
47 changed files with 1582 additions and 400 deletions
+35 -3
View File
@@ -3,7 +3,7 @@ from dataclasses import dataclass
import pytest
from core.builtin_concepts import ParserResultConcept, BuiltinConcepts, ReturnValueConcept
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF
from core.concept import DEFINITION_TYPE_BNF, DEFINITION_TYPE_DEF, Concept, CV
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import Keywords, Tokenizer, LexerError
from parsers.BnfNodeParser import OrderedChoice, ConceptExpression, StrMatch
@@ -87,9 +87,9 @@ class PN:
class TestDefaultParser(TestUsingMemoryBasedSheerka):
def init_parser(self, *concepts):
sheerka, concept, *updated = self.init_concepts(*concepts, singleton=True)
sheerka, context, *updated = self.init_concepts(*concepts, singleton=True)
parser = DefaultParser()
return sheerka, concept, parser, *updated
return sheerka, context, parser, *updated
@pytest.mark.parametrize("text, expected", [
("def concept hello", get_def_concept(name="hello")),
@@ -313,6 +313,38 @@ def concept add one to a as
assert isinstance(res.value, ParserResultConcept)
assert node == expected
def test_i_can_parse_when_ambiguity_in_where_pre_clause(self):
sheerka, context, parser, *concepts = self.init_parser(
Concept("x is a y", pre="in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)"),
Concept("x is a y")
)
text = "def concept foo x y where x is a y"
res = parser.parse(context, ParserInput(text))
expected_body = self.pretval(CV(concepts[0], pre=True), source="x is a y", who="parsers.Default",
parser="parsers.ExactConcept")
expected = get_def_concept("foo x y", where=expected_body)
node = res.value.value
assert res.status
assert res.who == parser.name
assert res.value.source == text
assert isinstance(res.value, ParserResultConcept)
assert node == expected
text = "def concept foo x y pre x is a y"
res = parser.parse(context, ParserInput(text))
expected_body = self.pretval(CV(concepts[0], pre=True), source="x is a y", who="parsers.Default",
parser="parsers.ExactConcept")
expected = get_def_concept("foo x y", pre=expected_body)
node = res.value.value
assert res.status
assert res.who == parser.name
assert res.value.source == text
assert isinstance(res.value, ParserResultConcept)
assert node == expected
def test_i_can_detect_not_for_me(self):
text = "hello world"
sheerka, context, parser = self.init_parser()
+108 -1
View File
@@ -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
@@ -0,0 +1,69 @@
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from parsers.ShortTermMemoryParser import ShortTermMemoryParser
from tests.TestUsingMemoryBasedSheerka import TestUsingMemoryBasedSheerka
class TestShortTermMemoryParser(TestUsingMemoryBasedSheerka):
def init_parser(self):
sheerka, context = self.init_concepts()
parser = ShortTermMemoryParser()
return sheerka, context, parser
def test_i_cannot_parse_empty_string(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_get_concept_from_sheerka(self):
sheerka, context, parser = self.init_parser()
foo = Concept("foo")
sheerka.add_to_short_term_memory(None, "test", foo)
res = parser.parse(context, ParserInput("test"))
assert res.status
assert id(res.body) == id(foo)
def test_i_can_get_concept_from_the_context(self):
sheerka, context, parser = self.init_parser()
foo = Concept("foo")
sheerka.add_to_short_term_memory(context, "test", foo)
res = parser.parse(context, ParserInput("test"))
assert res.status
assert id(res.body) == id(foo)
def test_i_can_get_concept_from_parent_context(self):
sheerka, context, parser = self.init_parser()
foo = Concept("foo")
sheerka.add_to_short_term_memory(context, "test", foo)
with context.push(BuiltinConcepts.TESTING, None) as sub_context:
res = parser.parse(sub_context, ParserInput("test"))
assert res.status
assert id(res.body) == id(foo)
def test_i_cannot_get_concept_when_no_concept_in_memory(self):
sheerka, context, parser = self.init_parser()
res = parser.parse(context, ParserInput("test"))
assert not res.status
assert sheerka.isinstance(res.body, BuiltinConcepts.NOT_FOUND)
assert res.body.body == "test"
def test_parser_can_only_be_called_with_parser_input(self):
sheerka, context, parser = self.init_parser()
assert parser.parse(context, "not_a_parser_input") is None