Loading DHParser/error.py +8 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,14 @@ class Error: @property def severity(self): """Returns a string representation of the error level, e.g. "warning".""" return "Warning" if is_warning(self.code) else "Error" if self.code < Error.WARNING: return "Notice" elif self.code < Error.ERROR: return "Warning" elif self.code < Error.FATAL: return "Error" else: return "Fatal" def visualize(self, document: str) -> str: """Shows the line of the document and the position where the error Loading DHParser/log.py +11 −3 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ __all__ = ('start_logging', 'clear_logs', 'NONE_TAG', 'NONE_NODE', 'freeze_callstack', 'HistoryRecord', 'log_ST', 'log_parsing_history') Loading Loading @@ -246,6 +247,11 @@ NONE_TAG = ":None" NONE_NODE = FrozenNode(NONE_TAG, '') def freeze_callstack(call_stack: List[Tuple[str, int]]) -> Tuple[Tuple[str, int], ...]: """Returns a frozen copy of the call stack.""" return tuple((tn, pos) for tn, pos in call_stack if tn != ":Forward") class HistoryRecord: """ Stores debugging information about one completed step in the Loading Loading @@ -292,15 +298,17 @@ class HistoryRecord: '</style>\n</head>\n<body>\n') HTML_LEAD_OUT = '\n</body>\n</html>\n' def __init__(self, call_stack: List[Tuple[str, int]], def __init__(self, call_stack: Union[List[Tuple[str, int]], Tuple[Tuple[str, int], ...]], node: Optional[Node], text: StringView, line_col: Tuple[int, int], errors: List[Error] = []) -> None: # copy call stack, dropping uninformative Forward-Parsers # self.call_stack = call_stack # type: Tuple[Tuple[str, int],...] self.call_stack = tuple((tn, pos) for tn, pos in call_stack if tn != ":Forward") # type: Tuple[Tuple[str, int],...] if isinstance(call_stack, tuple): self.call_stack = call_stack # type: Tuple[Tuple[str, int],...] else: self.call_stack = freeze_callstack(call_stack) self.node = NONE_NODE if node is None else node # type: Node self.text = text # type: StringView self.line_col = line_col # type: Tuple[int, int] Loading DHParser/parse.py +5 −4 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ __all__ = ('ParserError', 'Option', 'ZeroOrMore', 'OneOrMore', 'MandatoryNary', 'Series', 'Alternative', 'AllOf', Loading Loading @@ -1835,7 +1836,7 @@ MessagesType = List[Tuple[Union[str, Any], str]] NO_MANDATORY = 1000 class MandatoryElementsParser(NaryParser): class MandatoryNary(NaryParser): r""" Attributes: mandatory: Number of the element starting at which the element Loading @@ -1856,7 +1857,7 @@ class MandatoryElementsParser(NaryParser): mandatory: int = NO_MANDATORY, err_msgs: MessagesType = [], skip: ResumeList = []) -> None: super(MandatoryElementsParser, self).__init__(*parsers) super(MandatoryNary, self).__init__(*parsers) length = len(self.parsers) if mandatory < 0: mandatory += length Loading Loading @@ -1947,7 +1948,7 @@ class MandatoryElementsParser(NaryParser): return error, err_node, text_[i:] class Series(MandatoryElementsParser): class Series(MandatoryNary): r""" Matches if each of a series of parsers matches exactly in the order of the series. Loading Loading @@ -2119,7 +2120,7 @@ class Alternative(NaryParser): return self class AllOf(MandatoryElementsParser): class AllOf(MandatoryNary): """ Matches if all elements of a list of parsers match. Each parser must match exactly once. Other than in a sequence, the order in which Loading DHParser/trace.py +21 −24 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ from typing import Tuple, Optional, List, Iterable, Union from DHParser.error import Error, line_col from DHParser.stringview import StringView from DHParser.syntaxtree import Node, REGEXP_PTYPE, TOKEN_PTYPE, WHITESPACE_PTYPE, ZOMBIE_TAG from DHParser.log import HistoryRecord from DHParser.log import freeze_callstack, HistoryRecord from DHParser.parse import Grammar, Parser, ParserError, ParseFunc __all__ = ('trace_history', 'all_descendants', 'set_tracer', Loading @@ -52,10 +52,6 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin if not nd.children and nd.tag_name != ZOMBIE_TAG) text_ = pe.rest[l:] lc = line_col(grammar.document_lbreaks__, pe.error.pos) # grammar.history__.append( # HistoryRecord(grammar.call_stack__, pe.node, text_, lc, [pe.error])) if grammar.resume_notices__: target = text if len(target) >= 10: target = target[:7] + '...' Loading @@ -70,12 +66,11 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin notice = Error('Skipping within parser {} to point {}' .format(grammar.call_stack__[-1][0], repr(target)), self._grammar.document_length__ - len(text_), Error.RESUME_NOTICE) if grammar.resume_notices__: grammar.tree__.add_error(pe.node, notice) errors.append(notice) grammar.history__.append(HistoryRecord( grammar.call_stack__, pe.node, text_, lc, errors)) getattr(pe, 'frozen_callstack', grammar.call_stack__), pe.node, text_, lc, errors)) grammar.call_stack__.append( ((self.repr if self.tag_name in (REGEXP_PTYPE, TOKEN_PTYPE) Loading @@ -85,8 +80,8 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin try: node, rest = self._parse(text) # <===== call to the actual parser! except ParserError as pe: grammar.call_stack__.pop() if pe.first_throw: pe.frozen_callstack = freeze_callstack(grammar.call_stack__) grammar.most_recent_error__ = pe if self == grammar.start_parser__: fe = grammar.most_recent_error__ Loading @@ -95,6 +90,7 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin nd = fe.node grammar.history__.append( HistoryRecord(grammar.call_stack__, nd, fe.rest[len(nd):], lc, [fe.error])) grammar.call_stack__.pop() raise pe # Mind that memoized parser calls will not appear in the history record! Loading @@ -110,7 +106,8 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin record = HistoryRecord(grammar.call_stack__, nd, rest, lc, []) cs_len = len(record.call_stack) if (not grammar.history__ or lc != grammar.history__[-1].line_col or record.call_stack != grammar.history__[-1].call_stack[:cs_len]): or record.call_stack != grammar.history__[-1].call_stack[:cs_len] or self == grammar.start_parser__): grammar.history__.append(record) grammar.moving_forward__ = False Loading Loading
DHParser/error.py +8 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,14 @@ class Error: @property def severity(self): """Returns a string representation of the error level, e.g. "warning".""" return "Warning" if is_warning(self.code) else "Error" if self.code < Error.WARNING: return "Notice" elif self.code < Error.ERROR: return "Warning" elif self.code < Error.FATAL: return "Error" else: return "Fatal" def visualize(self, document: str) -> str: """Shows the line of the document and the position where the error Loading
DHParser/log.py +11 −3 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ __all__ = ('start_logging', 'clear_logs', 'NONE_TAG', 'NONE_NODE', 'freeze_callstack', 'HistoryRecord', 'log_ST', 'log_parsing_history') Loading Loading @@ -246,6 +247,11 @@ NONE_TAG = ":None" NONE_NODE = FrozenNode(NONE_TAG, '') def freeze_callstack(call_stack: List[Tuple[str, int]]) -> Tuple[Tuple[str, int], ...]: """Returns a frozen copy of the call stack.""" return tuple((tn, pos) for tn, pos in call_stack if tn != ":Forward") class HistoryRecord: """ Stores debugging information about one completed step in the Loading Loading @@ -292,15 +298,17 @@ class HistoryRecord: '</style>\n</head>\n<body>\n') HTML_LEAD_OUT = '\n</body>\n</html>\n' def __init__(self, call_stack: List[Tuple[str, int]], def __init__(self, call_stack: Union[List[Tuple[str, int]], Tuple[Tuple[str, int], ...]], node: Optional[Node], text: StringView, line_col: Tuple[int, int], errors: List[Error] = []) -> None: # copy call stack, dropping uninformative Forward-Parsers # self.call_stack = call_stack # type: Tuple[Tuple[str, int],...] self.call_stack = tuple((tn, pos) for tn, pos in call_stack if tn != ":Forward") # type: Tuple[Tuple[str, int],...] if isinstance(call_stack, tuple): self.call_stack = call_stack # type: Tuple[Tuple[str, int],...] else: self.call_stack = freeze_callstack(call_stack) self.node = NONE_NODE if node is None else node # type: Node self.text = text # type: StringView self.line_col = line_col # type: Tuple[int, int] Loading
DHParser/parse.py +5 −4 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ __all__ = ('ParserError', 'Option', 'ZeroOrMore', 'OneOrMore', 'MandatoryNary', 'Series', 'Alternative', 'AllOf', Loading Loading @@ -1835,7 +1836,7 @@ MessagesType = List[Tuple[Union[str, Any], str]] NO_MANDATORY = 1000 class MandatoryElementsParser(NaryParser): class MandatoryNary(NaryParser): r""" Attributes: mandatory: Number of the element starting at which the element Loading @@ -1856,7 +1857,7 @@ class MandatoryElementsParser(NaryParser): mandatory: int = NO_MANDATORY, err_msgs: MessagesType = [], skip: ResumeList = []) -> None: super(MandatoryElementsParser, self).__init__(*parsers) super(MandatoryNary, self).__init__(*parsers) length = len(self.parsers) if mandatory < 0: mandatory += length Loading Loading @@ -1947,7 +1948,7 @@ class MandatoryElementsParser(NaryParser): return error, err_node, text_[i:] class Series(MandatoryElementsParser): class Series(MandatoryNary): r""" Matches if each of a series of parsers matches exactly in the order of the series. Loading Loading @@ -2119,7 +2120,7 @@ class Alternative(NaryParser): return self class AllOf(MandatoryElementsParser): class AllOf(MandatoryNary): """ Matches if all elements of a list of parsers match. Each parser must match exactly once. Other than in a sequence, the order in which Loading
DHParser/trace.py +21 −24 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ from typing import Tuple, Optional, List, Iterable, Union from DHParser.error import Error, line_col from DHParser.stringview import StringView from DHParser.syntaxtree import Node, REGEXP_PTYPE, TOKEN_PTYPE, WHITESPACE_PTYPE, ZOMBIE_TAG from DHParser.log import HistoryRecord from DHParser.log import freeze_callstack, HistoryRecord from DHParser.parse import Grammar, Parser, ParserError, ParseFunc __all__ = ('trace_history', 'all_descendants', 'set_tracer', Loading @@ -52,10 +52,6 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin if not nd.children and nd.tag_name != ZOMBIE_TAG) text_ = pe.rest[l:] lc = line_col(grammar.document_lbreaks__, pe.error.pos) # grammar.history__.append( # HistoryRecord(grammar.call_stack__, pe.node, text_, lc, [pe.error])) if grammar.resume_notices__: target = text if len(target) >= 10: target = target[:7] + '...' Loading @@ -70,12 +66,11 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin notice = Error('Skipping within parser {} to point {}' .format(grammar.call_stack__[-1][0], repr(target)), self._grammar.document_length__ - len(text_), Error.RESUME_NOTICE) if grammar.resume_notices__: grammar.tree__.add_error(pe.node, notice) errors.append(notice) grammar.history__.append(HistoryRecord( grammar.call_stack__, pe.node, text_, lc, errors)) getattr(pe, 'frozen_callstack', grammar.call_stack__), pe.node, text_, lc, errors)) grammar.call_stack__.append( ((self.repr if self.tag_name in (REGEXP_PTYPE, TOKEN_PTYPE) Loading @@ -85,8 +80,8 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin try: node, rest = self._parse(text) # <===== call to the actual parser! except ParserError as pe: grammar.call_stack__.pop() if pe.first_throw: pe.frozen_callstack = freeze_callstack(grammar.call_stack__) grammar.most_recent_error__ = pe if self == grammar.start_parser__: fe = grammar.most_recent_error__ Loading @@ -95,6 +90,7 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin nd = fe.node grammar.history__.append( HistoryRecord(grammar.call_stack__, nd, fe.rest[len(nd):], lc, [fe.error])) grammar.call_stack__.pop() raise pe # Mind that memoized parser calls will not appear in the history record! Loading @@ -110,7 +106,8 @@ def trace_history(self: Parser, text: StringView) -> Tuple[Optional[Node], Strin record = HistoryRecord(grammar.call_stack__, nd, rest, lc, []) cs_len = len(record.call_stack) if (not grammar.history__ or lc != grammar.history__[-1].line_col or record.call_stack != grammar.history__[-1].call_stack[:cs_len]): or record.call_stack != grammar.history__[-1].call_stack[:cs_len] or self == grammar.start_parser__): grammar.history__.append(record) grammar.moving_forward__ = False Loading