Commit 94a4b568 authored by eckhart's avatar eckhart

refactoring of history recording finished

parent 2c132d71
......@@ -36,22 +36,13 @@ __all__ = ('trace_history', 'all_descendants', 'set_tracer',
'resume_notices_on')
def add_resume_notice(parser, rest: StringView, err_node: Node) -> None:
"""Adds a resume notice to the error node with information about
the reentry point and the parser."""
notice = Error('Resuming from {} with parser {} at point: {}'
.format(err_node.tag_name, parser.tag_name, repr(rest[:10])),
parser._grammar.document_length__ - len(rest), Error.RESUME_NOTICE)
parser._grammar.tree__.add_error(err_node, notice)
def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], StringView]:
grammar = self._grammar
location = grammar.document_length__ - text._len
if grammar.most_recent_error__:
# add resume notice
# add resume notice (mind that skip notices are added by
# `parse.MandatoryElementsParser.mandatory_violation()`
pe = grammar.most_recent_error__
grammar.most_recent_error__ = None
if grammar.resume_notices__:
......@@ -72,28 +63,17 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin
else (self.pname or self.tag_name)), location))
grammar.moving_forward__ = True
# if grammar.most_recent_error__:
# save_error = grammar.most_recent_error__
# grammar.most_recent_error__ = None
# else:
# save_error = None
try:
node, rest = self._parse(text)
except ParserError as pe:
grammar.call_stack__.pop()
if pe.first_throw:
# add error message to history
grammar.most_recent_error__ = pe
lc = line_col(grammar.document_lbreaks__, pe.error.pos)
nd = pe.node
grammar.history__.append(
HistoryRecord(grammar.call_stack__, nd, pe.rest[len(nd):], lc, [pe.error]))
# if self == grammar.start_parser__:
# lc = line_col(grammar.document_lbreaks__, pe.error.pos)
# # TODO: get the call stack from when the error occured, here
# nd = pe.node
# grammar.history__.append(
# HistoryRecord(grammar.call_stack__, nd, pe.rest[len(nd):], lc, [pe.error]))
raise pe
# Mind that memoized parser calls will not appear in the history record!
......@@ -101,6 +81,7 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin
if ((grammar.moving_forward__ or (node and not self.anonymous))
and (self.tag_name != WHITESPACE_PTYPE)):
# record history
# TODO: Make dropping insignificant whitespace from history configurable
delta = text._len - rest._len
nd = Node(node.tag_name, text[:delta]).with_pos(location) if node else None
......@@ -111,8 +92,6 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin
or record.call_stack != grammar.history__[-1].call_stack[:cs_len]):
grammar.history__.append(record)
# if save_error:
# grammar.most_recent_error__ = save_error
grammar.moving_forward__ = False
grammar.call_stack__.pop()
return node, rest
......
......@@ -31,13 +31,12 @@ from DHParser import grammar_provider, all_descendants, \
set_config_value, resume_notices_on, Error
def get_history(name) -> str:
def get_history(name, show: bool = False) -> str:
history_fname = os.path.join(log_dir() or '', name + "_full_parser.log.html")
# just for debugging:
import webbrowser, time
webbrowser.open(history_fname)
time.sleep(1)
# ------------------
if show:
import webbrowser, time
webbrowser.open(history_fname)
time.sleep(1)
with open(history_fname, 'r', encoding='utf-8') as f:
history_file = f.read()
return history_file
......@@ -187,8 +186,8 @@ class TestErrorReporting:
break
else:
assert False, "Missing Error!"
log_parsing_history(gr, 'trace_noskip')
get_history('trace_noskip')
# log_parsing_history(gr, 'trace_noskip')
# get_history('trace_noskip')
def test_trace_skip_clause(self):
lang = """
......@@ -205,8 +204,8 @@ class TestErrorReporting:
break
else:
assert False, "Missing Error!"
log_parsing_history(gr, 'trace_skip_clause')
get_history('trace_skip_clause')
# log_parsing_history(gr, 'trace_skip_clause')
# get_history('trace_skip_clause')
def test_trace_resume(self):
gr = self.gr; gr.resume_rules = dict()
......@@ -219,9 +218,38 @@ class TestErrorReporting:
assert cst.pick('alpha').content.startswith('ALPHA')
# because of resuming, there should be only one error message
assert len([err for err in cst.errors_sorted if err.code >= 1000]) == 1
log_parsing_history(gr, 'trace_skip_clause')
get_history('trace_skip_clause')
# log_parsing_history(gr, 'trace_resume')
# get_history('trace_resume')
def test_trace_resume_complex_case(self):
lang = r"""
@ comment = /(?:\/\/.*)|(?:\/\*(?:.|\n)*?\*\/)/ # Kommentare im C++-Stil
document = block_A block_B
@ block_A_resume = /(?=x)/
block_A = "a" §"b" "c"
block_B = "x" "y" "z"
"""
def mini_suite(grammar):
tree = grammar('abc/*x*/xyz')
assert not tree.errors
tree = grammar('abDxyz')
mandatory_cont = (Error.MANDATORY_CONTINUATION, Error.MANDATORY_CONTINUATION_AT_EOF)
assert len(tree.errors) > 1 and tree.errors[0].code in mandatory_cont
# log_parsing_history(grammar, 'trace_resume_complex_1')
# get_history('trace_resume_complex_1')
tree = grammar('abD/*x*/xyz')
assert len(tree.errors) > 1 and tree.errors[0].code in mandatory_cont
# log_parsing_history(grammar, 'trace_resume_complex_2')
# get_history('trace_resume_complex_2', show=True)
tree = grammar('aD /*x*/ c /* a */ /*x*/xyz')
assert len(tree.errors) > 1 and tree.errors[0].code in mandatory_cont
# log_parsing_history(grammar, 'trace_resume_complex_3')
# get_history('trace_resume_complex_3')
# test regex-defined resume rule
grammar = grammar_provider(lang)()
resume_notices_on(grammar)
mini_suite(grammar)
if __name__ == "__main__":
......
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