We can now use concept sets in BNF definitions

This commit is contained in:
2020-01-19 21:48:43 +01:00
parent a7b239c167
commit 821614a6c4
16 changed files with 643 additions and 93 deletions
+72 -6
View File
@@ -1,5 +1,6 @@
import pytest
from core.builtin_concepts import BuiltinConcepts
from core.concept import Concept
from core.sheerka import Sheerka, ExecutionContext
from core.tokenizer import Tokenizer, TokenKind, LexerError
@@ -17,6 +18,11 @@ def get_context():
return ExecutionContext("sheerka", Event(), sheerka)
class ClassWithName():
def __init__(self, name):
self.name = name
@pytest.mark.parametrize("expression, expected", [
("'str'", StrMatch("str")),
("1", StrMatch("1")),
@@ -41,12 +47,6 @@ def get_context():
("(1|*) +", Sequence(OrderedChoice(StrMatch("1"), StrMatch("*")), StrMatch("+"))),
("1, :&", Sequence(StrMatch("1"), StrMatch(","), StrMatch(":"), StrMatch("&"))),
("(1 )", StrMatch("1")),
("foo", ConceptExpression("foo")),
("foo*", ZeroOrMore(ConceptExpression("foo"))),
("foo 'and' bar+", Sequence(ConceptExpression("foo"), StrMatch("and"), OneOrMore(ConceptExpression("bar")))),
("foo | bar?", OrderedChoice(ConceptExpression("foo"), Optional(ConceptExpression("bar")))),
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), ConceptExpression("var"))),
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), ConceptExpression("var"))),
("'str'=var", StrMatch("str", rule_name="var")),
("'foo'?=var", Optional(StrMatch("foo"), rule_name="var")),
("('foo'?)=var", Optional(StrMatch("foo"), rule_name="var")),
@@ -75,6 +75,47 @@ def test_i_can_parse_regex(expression, expected):
assert res.value.source == expression
@pytest.mark.parametrize("expression, expected", [
("foo", Concept("foo").init_key()),
("foo*", ZeroOrMore(Concept("foo").init_key())),
("foo 'and' bar+", Sequence(Concept("foo").init_key(), StrMatch("and"), OneOrMore(Concept("bar").init_key()))),
("foo | bar?", OrderedChoice(Concept("foo").init_key(), Optional(Concept("bar").init_key()))),
("'str' = var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
("'str''='var", Sequence(StrMatch("str"), StrMatch("="), Concept("var").init_key())),
])
def test_i_can_parse_regex_with_concept(expression, expected):
foo = Concept("foo")
bar = Concept("bar")
var = Concept("var")
context = get_context()
for c in (foo, bar, var):
context.sheerka.add_in_cache(c)
parser = BnfParser()
res = parser.parse(context, Tokenizer(expression))
assert not parser.has_error
assert res.status
assert res.value.value == expected
assert res.value.source == expression
def test_i_can_parse_regex_with_concept_when_the_concept_is_still_under_definition():
expression = "foo"
expected = ConceptExpression("foo")
context = get_context()
context.obj = ClassWithName("foo")
parser = BnfParser()
res = parser.parse(context, Tokenizer(expression))
assert not parser.has_error
assert res.status
assert res.value.value == expected
assert res.value.source == expression
@pytest.mark.parametrize("expression, error", [
("1 ", UnexpectedEndOfFileError()),
("1|", UnexpectedEndOfFileError()),
@@ -117,3 +158,28 @@ def test_i_can_use_the_result_of_regex_parsing_to_parse_a_text():
res = concept_parser.parse(context, "twenty")
assert res.status
assert res.value.body == [cnode("foo", 0, 0, "twenty")]
def test_i_cannot_parse_when_too_many_concepts():
foo1 = Concept(name="foo", body="1")
foo2 = Concept(name="foo", body="2")
context = get_context()
context.sheerka.cache_by_key["foo"] = [foo1, foo2]
regex_parser = BnfParser()
res = regex_parser.parse(context, "foo")
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.CANNOT_RESOLVE_CONCEPT)
assert res.value.body == ('key', 'foo')
def test_i_cannot_parse_when_unknown_concept():
context = get_context()
regex_parser = BnfParser()
res = regex_parser.parse(get_context(), "foo")
assert not res.status
assert context.sheerka.isinstance(res.value, BuiltinConcepts.UNKNOWN_CONCEPT)
assert res.value.body == ('key', 'foo')