Commit fde7e064 authored by eckhart's avatar eckhart

- some refinements

parent f6c14f6c
This diff is collapsed.
...@@ -166,7 +166,7 @@ def add_parser_guard(parser_func): ...@@ -166,7 +166,7 @@ def add_parser_guard(parser_func):
except RecursionError: except RecursionError:
node = Node(None, str(text[:min(10, max(1, text.find("\n")))]) + " ...") node = Node(None, str(text[:min(10, max(1, text.find("\n")))]) + " ...")
node._pos = location node._pos = location
grammar.tree__.add_error(node, "maximum recursion depth of parser reached; " grammar.tree__.new_error(node, "maximum recursion depth of parser reached; "
"potentially due to too many errors!") "potentially due to too many errors!")
rest = EMPTY_STRING_VIEW rest = EMPTY_STRING_VIEW
...@@ -728,7 +728,7 @@ class Grammar: ...@@ -728,7 +728,7 @@ class Grammar:
result, _ = parser(rest) result, _ = parser(rest)
if result is None: if result is None:
result = Node(None, '').init_pos(0) result = Node(None, '').init_pos(0)
self.tree__.add_error(result, self.tree__.new_error(result,
'Parser "%s" did not match empty document.' % str(parser)) 'Parser "%s" did not match empty document.' % str(parser))
while rest and len(stitches) < MAX_DROPOUTS: while rest and len(stitches) < MAX_DROPOUTS:
result, rest = parser(rest) result, rest = parser(rest)
...@@ -749,7 +749,7 @@ class Grammar: ...@@ -749,7 +749,7 @@ class Grammar:
if len(stitches) < MAX_DROPOUTS if len(stitches) < MAX_DROPOUTS
else " too often! Terminating parser.") else " too often! Terminating parser.")
stitches.append(Node(None, skip).init_pos(tail_pos(stitches))) stitches.append(Node(None, skip).init_pos(tail_pos(stitches)))
self.tree__.add_error(stitches[-1], error_msg) self.tree__.new_error(stitches[-1], error_msg)
if self.history_tracking__: if self.history_tracking__:
# # some parsers may have matched and left history records with nodes != None. # # some parsers may have matched and left history records with nodes != None.
# # Because these are not connected to the stitched root node, their pos- # # Because these are not connected to the stitched root node, their pos-
...@@ -775,10 +775,10 @@ class Grammar: ...@@ -775,10 +775,10 @@ class Grammar:
# of the error will be the end of the text. Otherwise, the error # of the error will be the end of the text. Otherwise, the error
# message above ("...after end of parsing") would appear illogical. # message above ("...after end of parsing") would appear illogical.
error_node = Node(ZOMBIE_PARSER, '').init_pos(tail_pos(result.children)) error_node = Node(ZOMBIE_PARSER, '').init_pos(tail_pos(result.children))
self.tree__.add_error(error_node, error_str) self.tree__.new_error(error_node, error_str)
result.result = result.children + (error_node,) result.result = result.children + (error_node,)
else: else:
self.tree__.add_error(result, error_str) self.tree__.new_error(result, error_str)
# result.pos = 0 # calculate all positions # result.pos = 0 # calculate all positions
# result.collect_errors(self.document__) # result.collect_errors(self.document__)
self.tree__.swallow(result) self.tree__.swallow(result)
...@@ -862,19 +862,19 @@ class PreprocessorToken(Parser): ...@@ -862,19 +862,19 @@ class PreprocessorToken(Parser):
end = text.find(END_TOKEN, 1) end = text.find(END_TOKEN, 1)
if end < 0: if end < 0:
node = Node(self, '') node = Node(self, '')
self.grammar.tree__.add_error(node, self.grammar.tree__.new_error(node,
'END_TOKEN delimiter missing from preprocessor token. ' 'END_TOKEN delimiter missing from preprocessor token. '
'(Most likely due to a preprocessor bug!)') # type: Node '(Most likely due to a preprocessor bug!)') # type: Node
return node, text[1:] return node, text[1:]
elif end == 0: elif end == 0:
node = Node(self, '') node = Node(self, '')
self.grammar.tree__.add_error(node, self.grammar.tree__.new_error(node,
'Preprocessor-token cannot have zero length. ' 'Preprocessor-token cannot have zero length. '
'(Most likely due to a preprocessor bug!)') '(Most likely due to a preprocessor bug!)')
return node, text[2:] return node, text[2:]
elif text.find(BEGIN_TOKEN, 1, end) >= 0: elif text.find(BEGIN_TOKEN, 1, end) >= 0:
node = Node(self, text[len(self.name) + 1:end]) node = Node(self, text[len(self.name) + 1:end])
self.grammar.tree__.add_error(node, self.grammar.tree__.new_error(node,
'Preprocessor-tokens must not be nested or contain ' 'Preprocessor-tokens must not be nested or contain '
'BEGIN_TOKEN delimiter as part of their argument. ' 'BEGIN_TOKEN delimiter as part of their argument. '
'(Most likely due to a preprocessor bug!)') '(Most likely due to a preprocessor bug!)')
...@@ -1257,13 +1257,13 @@ class ZeroOrMore(Option): ...@@ -1257,13 +1257,13 @@ class ZeroOrMore(Option):
if not node: if not node:
break break
if len(text) == n: if len(text) == n:
err_msg = dsl_error_msg(self, 'Infinite Loop encountered.') node.errors.append(Error("Infinite loop!", Error.MESSAGE, node=node))
node.errors.append(Error(err_msg, Error.MESSAGE, node=node)) infinite_loop_error = Error(dsl_error_msg(self, 'Infinite Loop encountered.'),
infinite_loop_error = Error(err_msg, node=node) node=node)
results += (node,) results += (node,)
node = Node(self, results) node = Node(self, results)
if infinite_loop_error: if infinite_loop_error:
self.grammar.tree__.add_error_obj(node, infinite_loop_error) self.grammar.tree__.add_error(node, infinite_loop_error)
return node, text return node, text
def __repr__(self): def __repr__(self):
...@@ -1307,15 +1307,15 @@ class OneOrMore(UnaryOperator): ...@@ -1307,15 +1307,15 @@ class OneOrMore(UnaryOperator):
if not node: if not node:
break break
if len(text_) == n: if len(text_) == n:
err_msg = dsl_error_msg(self, 'Infinite Loop encountered.') node.errors.append(Error("Infinite loop!", Error.MESSAGE, node=node))
node.errors.append(Error(err_msg, Error.MESSAGE, node=node)) infinite_loop_error = Error(dsl_error_msg(self, 'Infinite Loop encountered.'),
infinite_loop_error = Error(err_msg, node=node) node=node)
results += (node,) results += (node,)
if results == (): if results == ():
return None, text return None, text
node = Node(self, results) node = Node(self, results)
if infinite_loop_error: if infinite_loop_error:
self.grammar.tree__.add_error_obj(node, infinite_loop_error) self.grammar.tree__.add_error(node, infinite_loop_error)
return node, text_ return node, text_
def __repr__(self): def __repr__(self):
...@@ -1387,7 +1387,7 @@ class Series(NaryOperator): ...@@ -1387,7 +1387,7 @@ class Series(NaryOperator):
assert len(results) <= len(self.parsers) assert len(results) <= len(self.parsers)
node = Node(self, results) node = Node(self, results)
if mandatory_violation: if mandatory_violation:
self.grammar.tree__.add_error_obj(node, mandatory_violation) self.grammar.tree__.add_error(node, mandatory_violation)
return node, text_ return node, text_
def __repr__(self): def __repr__(self):
...@@ -1648,7 +1648,7 @@ def Required(parser: Parser) -> Parser: ...@@ -1648,7 +1648,7 @@ def Required(parser: Parser) -> Parser:
# i = max(1, text.index(m.regs[1][0])) if m else 1 # i = max(1, text.index(m.regs[1][0])) if m else 1
# node = Node(self, text[:i]) # node = Node(self, text[:i])
# text_ = text[i:] # text_ = text[i:]
# self.grammar.tree__.add_error(node, # self.grammar.tree__.new_error(node,
# '%s expected; "%s" found!' % (str(self.parser), # '%s expected; "%s" found!' % (str(self.parser),
# text[:10]), code=Error.MANDATORY_CONTINUATION) # text[:10]), code=Error.MANDATORY_CONTINUATION)
# return node, text_ # return node, text_
...@@ -1824,7 +1824,7 @@ class Retrieve(Parser): ...@@ -1824,7 +1824,7 @@ class Retrieve(Parser):
value = self.filter(stack) value = self.filter(stack)
except (KeyError, IndexError): except (KeyError, IndexError):
node = Node(self, '') node = Node(self, '')
self.grammar.tree__.add_error( self.grammar.tree__.new_error(
node, dsl_error_msg(self, "'%s' undefined or exhausted." % self.symbol.name)) node, dsl_error_msg(self, "'%s' undefined or exhausted." % self.symbol.name))
return node, text return node, text
if text.startswith(value): if text.startswith(value):
......
...@@ -717,26 +717,28 @@ class RootNode(Node): ...@@ -717,26 +717,28 @@ class RootNode(Node):
self._content = node._content self._content = node._content
return self return self
def add_error_obj(self, node: Node, error: Error) -> 'RootNode': def add_error(self, node: Node, error: Error) -> 'RootNode':
"""Adds an Error object to the tree, locating it at a specific node."""
self.all_errors.append(error) self.all_errors.append(error)
self.error_flag = max(self.error_flag, error.code) self.error_flag = max(self.error_flag, error.code)
node.errors.append(error) node.errors.append(error)
self.err_nodes_keep.append(node) self.err_nodes_keep.append(node)
return self return self
def add_error(self, def new_error(self,
node: Node, node: Node,
message: str, message: str,
code: int = Error.ERROR) -> 'RootNode': code: int = Error.ERROR) -> 'RootNode':
""" """
Adds an error to this tree. Adds an error to this tree, locating it at a specific node.
Parameters: Parameters:
pos(int): The position of the error in the source text pos(int): The position of the error in the source text
message(str): A string with the error message.abs message(str): A string with the error message.abs
code(int): An error code to identify the kind of error code(int): An error code to identify the kind of error
""" """
error = Error(message, code, node=node) error = Error(message, code, node=node)
self.add_error_obj(node, error) self.add_error(node, error)
return self
def collect_errors(self) -> List[Error]: def collect_errors(self) -> List[Error]:
...@@ -748,7 +750,7 @@ class RootNode(Node): ...@@ -748,7 +750,7 @@ class RootNode(Node):
self.all_errors.sort(key=lambda e: e.pos) self.all_errors.sort(key=lambda e: e.pos)
for node in self.err_nodes_keep: # redundant: consider removing Error.Error._node_keep for node in self.err_nodes_keep: # redundant: consider removing Error.Error._node_keep
for error in node.errors: for error in node.errors:
# assert error._pos < 0 or node.pos <= error._pos <= node.len assert error._pos < 0 or node.pos <= error._pos <= node.pos + len(node)
error._pos = node.pos error._pos = node.pos
self.err_nodes_keep = [] self.err_nodes_keep = []
errors = self.all_errors errors = self.all_errors
......
...@@ -355,7 +355,7 @@ def grammar_unit(test_unit, parser_factory, transformer_factory, report=True, ve ...@@ -355,7 +355,7 @@ def grammar_unit(test_unit, parser_factory, transformer_factory, report=True, ve
cst = parser(test_code, parser_name) cst = parser(test_code, parser_name)
except UnknownParserError as upe: except UnknownParserError as upe:
node = Node(ZOMBIE_PARSER, "").init_pos(0) node = Node(ZOMBIE_PARSER, "").init_pos(0)
cst = RootNode().swallow(node).add_error(node, str(upe)) cst = RootNode(node).new_error(node, str(upe))
if not is_error(cst.error_flag): if not is_error(cst.error_flag):
errata.append('Fail test "%s" for parser "%s" yields match instead of ' errata.append('Fail test "%s" for parser "%s" yields match instead of '
'expected failure!' % (test_name, parser_name)) 'expected failure!' % (test_name, parser_name))
......
...@@ -888,7 +888,7 @@ assert_has_children = error_on(lambda nd: nd.children, 'Element "%s" has no chil ...@@ -888,7 +888,7 @@ assert_has_children = error_on(lambda nd: nd.children, 'Element "%s" has no chil
def assert_content(context: List[Node], regexp: str): def assert_content(context: List[Node], regexp: str):
node = context[-1] node = context[-1]
if not has_content(context, regexp): if not has_content(context, regexp):
context[0].add_error(node, 'Element "%s" violates %s on %s' % context[0].new_error(node, 'Element "%s" violates %s on %s' %
(node.parser.name, str(regexp), node.content)) (node.parser.name, str(regexp), node.content))
...@@ -897,7 +897,7 @@ def require(context: List[Node], child_tags: AbstractSet[str]): ...@@ -897,7 +897,7 @@ def require(context: List[Node], child_tags: AbstractSet[str]):
node = context[-1] node = context[-1]
for child in node.children: for child in node.children:
if child.tag_name not in child_tags: if child.tag_name not in child_tags:
context[0].add_error(node, 'Element "%s" is not allowed inside "%s".' % context[0].new_error(node, 'Element "%s" is not allowed inside "%s".' %
(child.parser.name, node.parser.name)) (child.parser.name, node.parser.name))
...@@ -906,6 +906,6 @@ def forbid(context: List[Node], child_tags: AbstractSet[str]): ...@@ -906,6 +906,6 @@ def forbid(context: List[Node], child_tags: AbstractSet[str]):
node = context[-1] node = context[-1]
for child in node.children: for child in node.children:
if child.tag_name in child_tags: if child.tag_name in child_tags:
context[0].add_error(node, 'Element "%s" cannot be nested inside "%s".' % context[0].new_error(node, 'Element "%s" cannot be nested inside "%s".' %
(child.parser.name, node.parser.name)) (child.parser.name, node.parser.name))
...@@ -526,7 +526,7 @@ S-Expression-output.</p> ...@@ -526,7 +526,7 @@ S-Expression-output.</p>
<dl class="method"> <dl class="method">
<dt id="syntaxtree.Node.add_error"> <dt id="syntaxtree.Node.add_error">
<code class="descname">add_error</code><span class="sig-paren">(</span><em>message: str</em>, <em>code: int = 1000</em><span class="sig-paren">)</span> &#x2192; syntaxtree.Node<a class="reference internal" href="_modules/syntaxtree.html#Node.add_error"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#syntaxtree.Node.add_error" title="Permalink to this definition"></a></dt> <code class="descname">add_error</code><span class="sig-paren">(</span><em>message: str</em>, <em>code: int = 1000</em><span class="sig-paren">)</span> &#x2192; syntaxtree.Node<a class="reference internal" href="_modules/syntaxtree.html#Node.new_error"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#syntaxtree.Node.new_error" title="Permalink to this definition"></a></dt>
<dd><p>Adds an error to this Node. <dd><p>Adds an error to this Node.
:param message: A string with the error message.abs :param message: A string with the error message.abs
:type message: str :type message: str
......
...@@ -633,7 +633,7 @@ ...@@ -633,7 +633,7 @@
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_errors</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_errors</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<div class="viewcode-block" id="Node.add_error"><a class="viewcode-back" href="../ModuleReference.html#syntaxtree.Node.add_error">[docs]</a> <span class="k">def</span> <span class="nf">add_error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <div class="viewcode-block" id="Node.add_error"><a class="viewcode-back" href="../ModuleReference.html#syntaxtree.Node.new_error">[docs]</a> <span class="k">def</span> <span class="nf">new_error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>
<span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
<span class="n">code</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">Error</span><span class="o">.</span><span class="n">ERROR</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s1">&#39;Node&#39;</span><span class="p">:</span> <span class="n">code</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">Error</span><span class="o">.</span><span class="n">ERROR</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s1">&#39;Node&#39;</span><span class="p">:</span>
<span class="sd">&quot;&quot;&quot;</span> <span class="sd">&quot;&quot;&quot;</span>
......
...@@ -199,7 +199,7 @@ ...@@ -199,7 +199,7 @@
<h2 id="A">A</h2> <h2 id="A">A</h2>
<table style="width: 100%" class="indextable genindextable"><tr> <table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul> <td style="width: 33%; vertical-align: top;"><ul>
<li><a href="ModuleReference.html#syntaxtree.Node.add_error">add_error() (Node method)</a> <li><a href="ModuleReference.html#syntaxtree.Node.add_error">new_error() (Node method)</a>
</li> </li>
<li><a href="ModuleReference.html#error.adjust_error_locations">adjust_error_locations() (in module error)</a> <li><a href="ModuleReference.html#error.adjust_error_locations">adjust_error_locations() (in module error)</a>
</li> </li>
......
...@@ -690,7 +690,7 @@ class LaTeXCompiler(Compiler): ...@@ -690,7 +690,7 @@ class LaTeXCompiler(Compiler):
if 'language' in node.attributes: if 'language' in node.attributes:
self.metadata['language'] = it self.metadata['language'] = it
else: else:
self.tree.add_error(node, 'Only one document language supported. ' self.tree.new_error(node, 'Only one document language supported. '
'Using %s, ignoring %s.' 'Using %s, ignoring %s.'
% (self.metadata['language'], it), Error.WARNING) % (self.metadata['language'], it), Error.WARNING)
if node['text'] in self.KNOWN_DOCUMENT_CLASSES: if node['text'] in self.KNOWN_DOCUMENT_CLASSES:
......
...@@ -30,8 +30,8 @@ from DHParser import parse_sxpr, Compiler ...@@ -30,8 +30,8 @@ from DHParser import parse_sxpr, Compiler
# B = next(tree.select(lambda node: str(node) == "1")) # B = next(tree.select(lambda node: str(node) == "1"))
# D = next(tree.select(lambda node: node.parser.name == "D")) # D = next(tree.select(lambda node: node.parser.name == "D"))
# F = next(tree.select(lambda node: str(node) == "3")) # F = next(tree.select(lambda node: str(node) == "3"))
# B.add_error("Error in child node") # B.new_error("Error in child node")
# F.add_error("Error in child's child node") # F.new_error("Error in child's child node")
# Compiler.propagate_error_flags(tree, lazy=True) # Compiler.propagate_error_flags(tree, lazy=True)
# assert A.error_flag # assert A.error_flag
# assert not D.error_flag # assert not D.error_flag
......
...@@ -133,8 +133,8 @@ class TestRootNode: ...@@ -133,8 +133,8 @@ class TestRootNode:
tree = parse_sxpr('(A (B D) (C E))') tree = parse_sxpr('(A (B D) (C E))')
tree.init_pos(0) tree.init_pos(0)
root = RootNode() root = RootNode()
root.add_error(tree.children[1], "error C") root.new_error(tree.children[1], "error C")
root.add_error(tree.children[0], "error B") root.new_error(tree.children[0], "error B")
root.swallow(tree) root.swallow(tree)
assert root.error_flag assert root.error_flag
errors = root.collect_errors() errors = root.collect_errors()
...@@ -152,7 +152,7 @@ class TestRootNode: ...@@ -152,7 +152,7 @@ class TestRootNode:
# def find_h(context): # def find_h(context):
# node = context[-1] # node = context[-1]
# if node.result == "h": # if node.result == "h":
# node.add_error("an error deep inside the syntax tree") # node.new_error("an error deep inside the syntax tree")
# #
# assert not tree.error_flag # assert not tree.error_flag
# traverse(tree, {"*": find_h}) # traverse(tree, {"*": find_h})
...@@ -164,8 +164,8 @@ class TestRootNode: ...@@ -164,8 +164,8 @@ class TestRootNode:
# B = next(tree.select(lambda node: str(node) == "1")) # B = next(tree.select(lambda node: str(node) == "1"))
# D = next(tree.select(lambda node: node.parser.name == "D")) # D = next(tree.select(lambda node: node.parser.name == "D"))
# F = next(tree.select(lambda node: str(node) == "3")) # F = next(tree.select(lambda node: str(node) == "3"))
# B.add_error("Error in child node") # B.new_error("Error in child node")
# F.add_error("Error in child's child node") # F.new_error("Error in child's child node")
# tree.error_flag = Error.ERROR # tree.error_flag = Error.ERROR
# errors = tree.collect_errors() # errors = tree.collect_errors()
# assert len(errors) == 2, str(errors) # assert len(errors) == 2, str(errors)
......
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