Commit 163b9340 authored by eckhart's avatar eckhart
Browse files

parse.py: subtle errors in Grammar-initialization corrected

parent 01393c6f
......@@ -1048,22 +1048,22 @@ class EBNFCompiler(Compiler):
definitions.append(pp_rules(self.ERR_MSGS_KEYWORD, error_messages))
for symbol in self.directives.error.keys():
if symbol not in self.consumed_custom_errors:
try:
def_node = self.rules[symbol][0]
self.tree.new_error(
def_node, 'Customized error message for symbol "{}" will never be used, '
'because the mandatory marker "§" appears nowhere in its definiendum!'
.format(symbol), Error.UNUSED_ERROR_HANDLING_WARNING)
except KeyError:
def match_function(nd: Node) -> bool:
return bool(nd.children) and nd.children[0].content.startswith(symbol + '_')
dir_node = self.tree.pick(match_function)
if dir_node:
directive = dir_node.children[0].content
self.tree.new_error(
dir_node, 'Directive "{}" relates to undefined symbol "{}"!'
.format(directive, directive.split('_')[0]))
if symbol in self.rules and symbol not in self.consumed_custom_errors:
# try:
def_node = self.rules[symbol][0]
self.tree.new_error(
def_node, 'Customized error message for symbol "{}" will never be used, '
'because the mandatory marker "§" appears nowhere in its definiendum!'
.format(symbol), Error.UNUSED_ERROR_HANDLING_WARNING)
# except KeyError:
# def match_function(nd: Node) -> bool:
# return bool(nd.children) and nd.children[0].content.startswith(symbol + '_')
# dir_node = self.tree.pick(match_function)
# if dir_node:
# directive = dir_node.children[0].content
# self.tree.new_error(
# dir_node, 'Directive "{}" relates to undefined symbol "{}"!'
# .format(directive, directive.split('_')[0]))
# prepare parser class header and docstring and
# add EBNF grammar to the doc string of the parser class
......
......@@ -1068,7 +1068,10 @@ class Grammar:
else:
parser.pname = entry
parser.anonymous = anonymous
cls.parser_initialization__[0] = "done"
if cls != Grammar:
cls.parser_initialization__ = ["done"] # (over-)write subclass-variable
# cls.parser_initialization__[0] = "done"
pass
def __init__(self, root: Parser = None) -> None:
......@@ -1107,6 +1110,8 @@ class Grammar:
self.static_analysis_pending__ = [True] # type: List[bool]
self.static_analysis_errors__ = [] # type: List[AnalysisError]
else:
assert self.__class__ == Grammar or self.__class__.root__ != PARSER_PLACEHOLDER, \
"Please add `root__` field to definition of class " + self.__class__.__name__
self.root_parser__ = copy.deepcopy(self.__class__.root__)
self.static_analysis_pending__ = self.__class__.static_analysis_pending__
self.static_analysis_errors__ = self.__class__.static_analysis_errors__
......
......@@ -94,6 +94,16 @@ class TestParserClass:
s3 = ", ".join(l)
assert s1 == s2 == s3
def test_symbol(self):
class MyGrammar(Grammar):
wrong = Token('wrong')
word = OneOrMore(wrong) + Whitespace(r'\s*') + OneOrMore(RegExp(r'\w+'))
root__ = word
gr = MyGrammar()
regex = gr['word'].parsers[-1].parser
result = gr.associated_symbol(regex).symbol
# assert result == 'word', result
class TestInfiLoopsAndRecursion:
def test_direct_left_recursion1(self):
......@@ -282,7 +292,7 @@ class TestRegex:
assert node.tag_name == "regex"
assert str(node) == 'abc+def'
def text_ignore_case(self):
def test_ignore_case(self):
mlregex = r"""
@ ignorecase = True
regex = /alpha/
......@@ -292,9 +302,8 @@ class TestRegex:
assert result
assert not messages
parser = compile_python_object(DHPARSER_IMPORTS + result, r'\w+Grammar$')()
node, rest = parser.regex('Alpha')
node, rest = parser.regex(StringView('Alpha'))
assert node
assert not node.error_flag
assert rest == ''
assert node.tag_name == "regex"
assert str(node) == 'Alpha'
......@@ -308,9 +317,8 @@ class TestRegex:
assert result
assert not messages
parser = compile_python_object(DHPARSER_IMPORTS + result, r'\w+Grammar$')()
node, rest = parser.regex('Alpha')
assert node.error_flag
node, rest = parser.regex(StringView('Alpha'))
assert node is None
def test_token(self):
tokenlang = r"""
......@@ -573,7 +581,6 @@ class TestErrorRecovery:
assert len(st.errors) == 2 and any(err.code == Error.RESUME_NOTICE for err in st.errors)
assert 'Skipping' in str(st.errors_sorted[1])
def test_Interleave_skip(self):
lang = """
document = allof | /.*/
......@@ -1040,7 +1047,6 @@ class TestReentryAfterError:
grammar = grammar_provider(lang)()
mini_suite(grammar)
def test_unambiguous_error_location(self):
lang = r"""
@ drop = whitespace, token # drop tokens and whitespace early
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment