Skip to content

Instantly share code, notes, and snippets.

@acdimalev
Last active September 15, 2019 21:49
Show Gist options
  • Save acdimalev/b44c919dc508a78fffe70e52c72d3b66 to your computer and use it in GitHub Desktop.
Save acdimalev/b44c919dc508a78fffe70e52c72d3b66 to your computer and use it in GitHub Desktop.

Adding a "grammar" context to all parsers.

Option 1 ("grammar omnipresence"):

  • Adding a grammar parameter to the parse and generate functions of every parser.
  • Updating every parse and generate call to pass a grammar parameter

Option 2:

  • Adding a map function to every parser.
# generate a token grammar
good_grammar = Grammar({})
# define an exception to raise when encountering some other grammar
class BadGrammarException(Exception):
pass
# define a combinatorial parser that validates the grammar parameter
class GoodGrammarParser(Parser):
def __init__(self, child):
self.child = child
def __repr__(self):
return "GoodGrammarParser({!r})".format(self.child)
def __str__(self):
return str(self.child)
def parse(self, document, grammar):
if good_grammar != grammar:
raise BadGrammarException
return self.child.parse(document, grammar)
def generate(self, entropy, grammar):
if good_grammar != grammar:
raise BadGrammarException
return self.child.generate(entropy, grammar)
# define a composable strategy for the validation parser
def good_grammar_parsers(children):
return builds(GoodGrammarParser, children)
# compose with combinatorial and primitive parsers
# compare with the definition of `parsers` strategy
def parsers_and_good_grammar_parsers():
self = deferred(lambda: parsers_and_good_grammar_parsers())
return one_of(
primitive_parsers(),
combinatorial_parsers(self),
good_grammar_parsers(self),
)
# attempted filter for identifying parsers that have good grammar parsers
def has_good_grammar_parser(entropy, parser):
try:
parser.generate(entropy, None)
return False
except BadGrammarException:
return True
class TestParsers(TestCase):
@given(
entropys(),
parsers_and_good_grammar_parsers(),
)
def test_parsers_retain_grammar(self, entropy, parser):
assume(has_good_grammar_parser(entropy, parser))
assume(parsers_are_good(entropy, [parser]))
for _ in range(iterations):
try:
parser.parse(parser.generate(entropy, good_grammar), good_grammar)
except GenerationException:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment