First implementation of questions management
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user