Loading DHParser/log.py +3 −3 Original line number Diff line number Diff line Loading @@ -372,8 +372,8 @@ def log_ST(syntax_tree, log_file_name): """ if is_logging(): path = os.path.join(log_dir(), log_file_name) if os.path.exists(path): print('WARNING: Log-file "%s" already exists and will be overwritten!' % path) # if os.path.exists(path): # print('WARNING: Log-file "%s" already exists and will be overwritten!' % path) with open(path, "w", encoding="utf-8") as f: f.write(syntax_tree.as_sxpr()) Loading Loading @@ -401,7 +401,7 @@ def log_parsing_history(grammar, log_file_name: str = '', html: bool = True) -> path = os.path.join(log_dir(), log_name + "_parser.log" + htm) if os.path.exists(path): os.remove(path) print('WARNING: Log-file "%s" already existed and was deleted.' % path) # print('WARNING: Log-file "%s" already existed and was deleted.' % path) if history: with open(path, "w", encoding="utf-8") as f: if html: Loading DHParser/parse.py +40 −26 Original line number Diff line number Diff line Loading @@ -106,9 +106,10 @@ class ParserError(Exception): different kind of error like `UnknownParserError`, is when a `Series`- detects a missing mandatory element. """ def __init__(self, node: Node, rest: StringView, first_throw: bool): def __init__(self, node: Node, rest: StringView, error: Optional[Error], first_throw: bool): self.node = node # type: Node self.rest = rest # type: StringView self.error = error # type: Optional[Error] self.first_throw = first_throw # type: bool def __str__(self): Loading Loading @@ -263,6 +264,15 @@ class Parser: the business intelligence that is common to all parsers. The actual parsing is done in the overridden method `_parse()`. """ def get_error_node_id(error_node: Node, root_node: RootNode) -> int: if error_node: error_node_id = id(error_node) while error_node_id not in grammar.tree__.error_nodes and error_node.children: error_node = error_node.result[-1] error_node_id = id(error_node) else: error_node_id = 0 grammar = self._grammar location = grammar.document_length__ - len(text) Loading Loading @@ -291,15 +301,16 @@ class Parser: (':RegExp', ':Token', ':DropToken') else self.tag_name) grammar.moving_forward__ = True error = None try: # PARSER CALL: run _parse() method node, rest = self._parse(text) except ParserError as error: except ParserError as pe: # does this play well with variable setting? add rollback clause here? tests needed... gap = len(text) - len(error.rest) gap = len(text) - len(pe.rest) rules = grammar.resume_rules__.get(self.pname, []) rest = error.rest[len(error.node):] rest = pe.rest[len(pe.node):] i = reentry_point(rest, rules) if i >= 0 or self == grammar.start_parser__: # apply reentry-rule or catch error at root-parser Loading @@ -307,26 +318,28 @@ class Parser: i = 1 nd = Node(ZOMBIE_TAG, rest[:i]).with_pos(location) rest = rest[i:] assert error.node.children or (not error.node.result) if error.first_throw: node = error.node assert pe.node.children or (not pe.node.result) if pe.first_throw: node = pe.node node.result = node.children + (nd,) else: # TODO: ggf. Fehlermeldung, die sagt, wo es weitergeht anfügen # TODO: ggf. Fehlermeldung, die sagt, wo es weitergeht, anfügen; # dürfte allerdings erst an den nächsten(!) Knoten angehängt werden (wie?) node = Node(self.tag_name, (Node(ZOMBIE_TAG, text[:gap]).with_pos(location), error.node, nd)) elif error.first_throw: raise ParserError(error.node, error.rest, first_throw=False) pe.node, nd)) elif pe.first_throw: raise ParserError(pe.node, pe.rest, pe.error, first_throw=False) else: result = (Node(ZOMBIE_TAG, text[:gap]).with_pos(location), error.node) if gap \ else error.node # type: ResultType result = (Node(ZOMBIE_TAG, text[:gap]).with_pos(location), pe.node) if gap \ else pe.node # type: ResultType if grammar.tree__.errors[-1].code == Error.MANDATORY_CONTINUATION_AT_EOF: # EXPERIMENTAL!! node = error.node node = pe.node else: raise ParserError(Node(self.tag_name, result).with_pos(location), text, first_throw=False) text, pe.error, first_throw=False) error = pe.error # needed for history tracking if left_recursion_depth__: self.recursion_counter[location] -= 1 Loading @@ -343,6 +356,7 @@ class Parser: "Refactor grammar to avoid slow parsing.", node.pos if node else location, Error.LEFT_RECURSION_WARNING)) error_id = id(node) grammar.last_recursion_location__ = location # don't overwrite any positive match (i.e. node not None) in the cache # and don't add empty entries for parsers returning from left recursive calls! Loading Loading @@ -372,12 +386,12 @@ class Parser: record = HistoryRecord(grammar.call_stack__, node, text, grammar.line_col__(text)) grammar.history__.append(record) elif node: nid = id(node) # type: int if nid in grammar.tree__.error_nodes: elif error: # error_nid = id(node) # type: int # if error_nid in grammar.tree__.error_nodes: record = HistoryRecord(grammar.call_stack__, node, text, grammar.line_col__(text), grammar.tree__.error_nodes[nid]) [error]) grammar.history__.append(record) grammar.moving_forward__ = False grammar.call_stack__.pop() Loading Loading @@ -1763,7 +1777,7 @@ class Series(NaryParser): ret_node = self._return_values(results) # type: Node if error: raise ParserError(ret_node.with_pos(self.grammar.document_length__ - len(text)), text, first_throw=True) text, error, first_throw=True) return ret_node, text_ def __repr__(self): Loading Loading @@ -1980,7 +1994,7 @@ class AllOf(NaryParser): nd = self._return_values(results) # type: Node if error: raise ParserError(nd.with_pos(self.grammar.document_length__ - len(text)), text, first_throw=True) text, error, first_throw=True) return nd, text_ def __repr__(self): Loading DHParser/scripts/dhparser.py +4 −2 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ import os import sys scriptdir = os.path.dirname(os.path.abspath(__file__)) i = scriptdir.find('DHParser') i, k = scriptdir.find('DHParser-submodule'), len('DHParser-submodule') if i < 0: i, k = scriptdir.find('DHParser'), len('DHParser') if i >= 0: dhparserdir = scriptdir[:i + 8] dhparserdir = scriptdir[:i + k] sys.path.append(dhparserdir) else: dhparserdir = '' Loading DHParser/syntaxtree.py +1 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil S-Expression-output. """ __slots__ = '_result', 'children', '_pos', 'tag_name', '_xml_attr', '_id' __slots__ = '_result', 'children', '_pos', 'tag_name', '_xml_attr' def __init__(self, tag_name: str, result: ResultType, leafhint: bool = False) -> None: """ Loading test/test_parse.py +2 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ from DHParser.stringview import StringView class TestParserError: def test_parser_error_str(self): pe = ParserError(Node('TAG', 'test').with_pos(0), StringView('Beispiel'), True) pe = ParserError(Node('TAG', 'test').with_pos(0), StringView('Beispiel'), None, True) assert str(pe).find('Beispiel') >= 0 and str(pe).find('TAG') >= 0 Loading Loading @@ -779,7 +779,7 @@ class TestReentryAfterError: class TestConfiguredErrorMessages: def test_(self): def test_configured_error_message(self): lang = """ document = series | /.*/ @series_error = "a badly configured error message {5}" Loading DHParser/server.py +4 −4 File changed.Contains only whitespace changes. Show changes Loading
DHParser/log.py +3 −3 Original line number Diff line number Diff line Loading @@ -372,8 +372,8 @@ def log_ST(syntax_tree, log_file_name): """ if is_logging(): path = os.path.join(log_dir(), log_file_name) if os.path.exists(path): print('WARNING: Log-file "%s" already exists and will be overwritten!' % path) # if os.path.exists(path): # print('WARNING: Log-file "%s" already exists and will be overwritten!' % path) with open(path, "w", encoding="utf-8") as f: f.write(syntax_tree.as_sxpr()) Loading Loading @@ -401,7 +401,7 @@ def log_parsing_history(grammar, log_file_name: str = '', html: bool = True) -> path = os.path.join(log_dir(), log_name + "_parser.log" + htm) if os.path.exists(path): os.remove(path) print('WARNING: Log-file "%s" already existed and was deleted.' % path) # print('WARNING: Log-file "%s" already existed and was deleted.' % path) if history: with open(path, "w", encoding="utf-8") as f: if html: Loading
DHParser/parse.py +40 −26 Original line number Diff line number Diff line Loading @@ -106,9 +106,10 @@ class ParserError(Exception): different kind of error like `UnknownParserError`, is when a `Series`- detects a missing mandatory element. """ def __init__(self, node: Node, rest: StringView, first_throw: bool): def __init__(self, node: Node, rest: StringView, error: Optional[Error], first_throw: bool): self.node = node # type: Node self.rest = rest # type: StringView self.error = error # type: Optional[Error] self.first_throw = first_throw # type: bool def __str__(self): Loading Loading @@ -263,6 +264,15 @@ class Parser: the business intelligence that is common to all parsers. The actual parsing is done in the overridden method `_parse()`. """ def get_error_node_id(error_node: Node, root_node: RootNode) -> int: if error_node: error_node_id = id(error_node) while error_node_id not in grammar.tree__.error_nodes and error_node.children: error_node = error_node.result[-1] error_node_id = id(error_node) else: error_node_id = 0 grammar = self._grammar location = grammar.document_length__ - len(text) Loading Loading @@ -291,15 +301,16 @@ class Parser: (':RegExp', ':Token', ':DropToken') else self.tag_name) grammar.moving_forward__ = True error = None try: # PARSER CALL: run _parse() method node, rest = self._parse(text) except ParserError as error: except ParserError as pe: # does this play well with variable setting? add rollback clause here? tests needed... gap = len(text) - len(error.rest) gap = len(text) - len(pe.rest) rules = grammar.resume_rules__.get(self.pname, []) rest = error.rest[len(error.node):] rest = pe.rest[len(pe.node):] i = reentry_point(rest, rules) if i >= 0 or self == grammar.start_parser__: # apply reentry-rule or catch error at root-parser Loading @@ -307,26 +318,28 @@ class Parser: i = 1 nd = Node(ZOMBIE_TAG, rest[:i]).with_pos(location) rest = rest[i:] assert error.node.children or (not error.node.result) if error.first_throw: node = error.node assert pe.node.children or (not pe.node.result) if pe.first_throw: node = pe.node node.result = node.children + (nd,) else: # TODO: ggf. Fehlermeldung, die sagt, wo es weitergeht anfügen # TODO: ggf. Fehlermeldung, die sagt, wo es weitergeht, anfügen; # dürfte allerdings erst an den nächsten(!) Knoten angehängt werden (wie?) node = Node(self.tag_name, (Node(ZOMBIE_TAG, text[:gap]).with_pos(location), error.node, nd)) elif error.first_throw: raise ParserError(error.node, error.rest, first_throw=False) pe.node, nd)) elif pe.first_throw: raise ParserError(pe.node, pe.rest, pe.error, first_throw=False) else: result = (Node(ZOMBIE_TAG, text[:gap]).with_pos(location), error.node) if gap \ else error.node # type: ResultType result = (Node(ZOMBIE_TAG, text[:gap]).with_pos(location), pe.node) if gap \ else pe.node # type: ResultType if grammar.tree__.errors[-1].code == Error.MANDATORY_CONTINUATION_AT_EOF: # EXPERIMENTAL!! node = error.node node = pe.node else: raise ParserError(Node(self.tag_name, result).with_pos(location), text, first_throw=False) text, pe.error, first_throw=False) error = pe.error # needed for history tracking if left_recursion_depth__: self.recursion_counter[location] -= 1 Loading @@ -343,6 +356,7 @@ class Parser: "Refactor grammar to avoid slow parsing.", node.pos if node else location, Error.LEFT_RECURSION_WARNING)) error_id = id(node) grammar.last_recursion_location__ = location # don't overwrite any positive match (i.e. node not None) in the cache # and don't add empty entries for parsers returning from left recursive calls! Loading Loading @@ -372,12 +386,12 @@ class Parser: record = HistoryRecord(grammar.call_stack__, node, text, grammar.line_col__(text)) grammar.history__.append(record) elif node: nid = id(node) # type: int if nid in grammar.tree__.error_nodes: elif error: # error_nid = id(node) # type: int # if error_nid in grammar.tree__.error_nodes: record = HistoryRecord(grammar.call_stack__, node, text, grammar.line_col__(text), grammar.tree__.error_nodes[nid]) [error]) grammar.history__.append(record) grammar.moving_forward__ = False grammar.call_stack__.pop() Loading Loading @@ -1763,7 +1777,7 @@ class Series(NaryParser): ret_node = self._return_values(results) # type: Node if error: raise ParserError(ret_node.with_pos(self.grammar.document_length__ - len(text)), text, first_throw=True) text, error, first_throw=True) return ret_node, text_ def __repr__(self): Loading Loading @@ -1980,7 +1994,7 @@ class AllOf(NaryParser): nd = self._return_values(results) # type: Node if error: raise ParserError(nd.with_pos(self.grammar.document_length__ - len(text)), text, first_throw=True) text, error, first_throw=True) return nd, text_ def __repr__(self): Loading
DHParser/scripts/dhparser.py +4 −2 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ import os import sys scriptdir = os.path.dirname(os.path.abspath(__file__)) i = scriptdir.find('DHParser') i, k = scriptdir.find('DHParser-submodule'), len('DHParser-submodule') if i < 0: i, k = scriptdir.find('DHParser'), len('DHParser') if i >= 0: dhparserdir = scriptdir[:i + 8] dhparserdir = scriptdir[:i + k] sys.path.append(dhparserdir) else: dhparserdir = '' Loading
DHParser/syntaxtree.py +1 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ class Node: # (collections.abc.Sized): Base class omitted for cython-compatibil S-Expression-output. """ __slots__ = '_result', 'children', '_pos', 'tag_name', '_xml_attr', '_id' __slots__ = '_result', 'children', '_pos', 'tag_name', '_xml_attr' def __init__(self, tag_name: str, result: ResultType, leafhint: bool = False) -> None: """ Loading
test/test_parse.py +2 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ from DHParser.stringview import StringView class TestParserError: def test_parser_error_str(self): pe = ParserError(Node('TAG', 'test').with_pos(0), StringView('Beispiel'), True) pe = ParserError(Node('TAG', 'test').with_pos(0), StringView('Beispiel'), None, True) assert str(pe).find('Beispiel') >= 0 and str(pe).find('TAG') >= 0 Loading Loading @@ -779,7 +779,7 @@ class TestReentryAfterError: class TestConfiguredErrorMessages: def test_(self): def test_configured_error_message(self): lang = """ document = series | /.*/ @series_error = "a badly configured error message {5}" Loading