05.11., 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 241311a8 authored by di68kap's avatar di68kap

- more preliminary work for variable curated error messages

parent 6815e2b6
......@@ -834,30 +834,24 @@ class EBNFCompiler(Compiler):
check_argnum(2)
symbol = key[:-6]
error_msgs = self.directives['error'].get(symbol, [])
if symbol in self.rules:
self.tree.new_error(node, 'Custom error message for symbol "%s"' % symbol
+ 'must be defined before the symbol!')
parameter_error = 'Directive "%s" requires message string or a a pair '\
'(regular expression or search string, message string) as argument!'
# if symbol in self.rules:
# self.tree.new_error(node, 'Custom error message for symbol "%s"' % symbol
# + 'must be defined before the symbol!')
if node.children[1 if len(node.children) == 2 else 2].parser.name != 'literal':
self.tree.new_error(
node, 'Directive "%s" requires message string or a a pair ' % key +
'(regular expression or search string, message string) as argument!')
if len(node.children) == 2:
if node.children[1].parser.name != 'literal':
self.tree.new_error(node, parameter_error)
else:
error_msgs.append(('', unrepr(node.children[1].content)))
if len(node.children) == 3:
if (node.children[1].parser.name not in ('literal', 'regexp')
or node.children[2].parser.name != 'literal'):
self.tree.new_error(node, parameter_error)
else:
error_msgs.append((self._gen_search_rule(node.children[1]),
unrepr(node.children[2].content)))
error_msgs.append(('', unrepr(node.children[1].content)))
elif len(node.children) == 3:
rule = self._gen_search_rule(node.children[1])
error_msgs.append((rule if rule else unrepr(node.children[1].content),
unrepr(node.children[2].content)))
else:
self.tree.new_error(node, 'Directive "%s" allows at most two parameters' % key)
self.directives['error'][symbol] = error_msgs
elif key.endswith('_resume'):
# if not all(child.parser.name in ('literal', 'regexp') for child in node.children[1:]):
# self.tree.new_error(node, 'Directive "%s" accepts only regular expressions or '
# 'plain strings as arguments, but no symbols without '
# 'quotation marks!' % key)
symbol = key[:-7]
if symbol in self.directives['resume']:
self.tree.new_error(node, 'Reentry conditions for "%s" have already been defined'
......@@ -866,12 +860,7 @@ class EBNFCompiler(Compiler):
reentry_conditions = [] # type: List[Union[unrepr, str]]
for child in node.children[1:]:
rule = self._gen_search_rule(child)
if rule:
reentry_conditions.append(rule)
else: # child.parser.name == 'symbol'
if child.content not in self.symbols:
self.symbols[child.content] = node
reentry_conditions.append(unrepr(child.content.strip()))
reentry_conditions.append(rule if rule else unrepr(child.content.strip()))
self.directives['resume'][symbol] = reentry_conditions
else:
......@@ -932,6 +921,7 @@ class EBNFCompiler(Compiler):
current_symbol = next(reversed(self.rules.keys()))
msgs = self.directives['error'].get(current_symbol, [])
if msgs:
# use class field instead or direct representation of error messages!
custom_args.append('err_msgs=' + str(msgs))
compiled = self.non_terminal(node, 'Series', custom_args)
node.result = saved_result
......
......@@ -1423,7 +1423,7 @@ class Series(NaryOperator):
found = text_[:10].replace('\n', '\\n ')
for search, message in self.err_msgs:
rxs = not isinstance(search, str)
if rxs and search.match(text_) or not rxs and text_.startswith(search):
if rxs and text_.match(search) or not rxs and text_.startswith(search):
msg = message.format(parser.repr, found)
break
else:
......
......@@ -183,8 +183,17 @@ class unrepr:
>>> unrepr("re.compile(r'abc+')")
re.compile(r'abc+')
"""
def __init__(self, s):
self.s = s
def __init__(self, s: str):
self.s = s # type: str
def __eq__(self, other: Union['unrepr', str]):
if isinstance(other, unrepr):
return self.s == other.s
elif isinstance(other, str):
return self.s == other
else:
raise TypeError('unrepr objects can only be compared with '
'other unrepr objects or strings!')
def __str__(self):
return self.s
......
......@@ -453,18 +453,18 @@ class TestCuratedErrors:
Cureted Errors replace existing errors with alternative
error codes and messages that are more helptful to the user.
"""
def test_user_error_declaration(self):
lang = """
document = series | /.*/
series = "X" | head §"C" "D"
head = "A" "B"
@series_error = "a user defined error message"
"""
try:
parser = grammar_provider(lang)()
assert False, "Error definition after symbol definition should fail!"
except CompilationError as e:
pass
# def test_user_error_declaration(self):
# lang = """
# document = series | /.*/
# series = "X" | head §"C" "D"
# head = "A" "B"
# @series_error = "a user defined error message"
# """
# try:
# parser = grammar_provider(lang)()
# assert False, "Error definition after symbol definition should fail!"
# except CompilationError as e:
# pass
def test_curated_mandatory_continuation(self):
lang = """
......
Markdown is supported
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