Skip to content

Commit

Permalink
Address review comment: Make '%declare rule' fail in post-processing …
Browse files Browse the repository at this point in the history
…with a nice message.
  • Loading branch information
RossPatterson committed Feb 10, 2024
1 parent e9c026e commit 9bf7ddf
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 4 deletions.
8 changes: 8 additions & 0 deletions lark/lark_validator_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ def validate(cls, tree: Tree):
visitor.visit(tree)
return tree

def declare(self, tree: Tree):
for child in tree.children:
assert child.data == "name"
assert len(child.children) == 1
assert isinstance(child.children[0], Token)
if child.children[0].type != "TOKEN":
raise GrammarError("Expecting terminal name")

def ignore(self, tree: Tree):
# Reject everything except 'literal' and 'name' > 'TOKEN'.
assert len(tree.children) > 0 # The grammar should pass us some things to ignore.
Expand Down
7 changes: 4 additions & 3 deletions lark/load_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,13 +1272,14 @@ def load_grammar(self, grammar_text: str, grammar_name: str="<?>", mangle: Optio
self._ignore(*stmt.children)
elif stmt.data == 'declare':
for symbol in stmt.children:
assert isinstance(symbol, Symbol), symbol
is_term = isinstance(symbol, Terminal)
if isinstance(symbol, NonTerminal):
raise GrammarError("Expecting terminal name")
assert isinstance(symbol, Terminal), symbol
if mangle is None:
name = symbol.name
else:
name = mangle(symbol.name)
self._define(name, is_term, None)
self._define(name, True, None)
elif stmt.data == 'import':
pass
else:
Expand Down
35 changes: 34 additions & 1 deletion tests/test_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from lark import Lark, Token, Tree, ParseError, UnexpectedInput
from lark.load_grammar import GrammarError, GRAMMAR_ERRORS, find_grammar_errors, list_grammar_imports
from lark.load_grammar import FromPackageLoader
from lark.lark_validator_visitor import LarkValidatorVisitor


class TestGrammar(TestCase):
Expand Down Expand Up @@ -295,9 +296,41 @@ def test_line_breaks(self):
""")
p.parse('ab')

def test_declare_rule_lg(self):
g = """
%declare a
start: b
b: "c"
"""
self.assertRaisesRegex(GrammarError, "Expecting terminal name", Lark, g)

def test_declare_rule_ll(self):
g = """
%declare a
start: b
b: "c"
"""
l = Lark.open_from_package("lark", "grammars/lark.lark")
t = l.parse(g)
self.assertRaisesRegex(GrammarError, "Expecting terminal name", LarkValidatorVisitor.validate, t)

def test_declare_token_lg(self):
g = """
%declare A
start: b
b: "c"
"""
Lark(g)


def test_declare_token_ll(self):
g = """
%declare A
start: b
b: "c"
"""
l = Lark.open_from_package("lark", "grammars/lark.lark")
t = l.parse(g)
LarkValidatorVisitor.validate(t)


if __name__ == '__main__':
Expand Down

0 comments on commit 9bf7ddf

Please sign in to comment.