Commit 44c61528 authored by di68kap's avatar di68kap

- removed MetaParser._keep_node(). This kind of optimization is now done...

- removed MetaParser._keep_node(). This kind of optimization is now done inplace which is considerably faster
parent 3d95076e
......@@ -1348,6 +1348,17 @@ class DropWhitespace(Whitespace):
class MetaParser(Parser):
"""Class Meta-Parser contains functions for the optimization of
retrun values of parsers that call other parsers (i.e descendants
of classes UnaryParser and NaryParser).
The optimization consists in flattening the tree by eliminating
anonymous nodes. This is the same as what the function
DHParser.transform.flatten() does, only at an earlier stage.
The reasoning is that the earlier the tree is reduced, the less work
reamins to do at all the later processing stages.
"""
def _return_value(self, node: Optional[Node]) -> Node:
"""
Generates a return node if a single node has been returned from
......@@ -1401,16 +1412,6 @@ class MetaParser(Parser):
return EMPTY_NODE # avoid creation of a node object for anonymous empty nodes
return Node(self.tag_name, results) # unoptimized code
def _keep_node(self, node):
"""
Returns True, if a node returned by a descendant parser should be kept.
False, if it should be sorted out. A node is kept, if it is empty and
neither the parser of the descendant parser is a named parser.
"""
if self.grammar.flatten_tree__:
return node._result or node.tag_name[0:1] != ':'
return node != EMPTY_NODE # EMPTY_NODE will always be sorted out...
class UnaryParser(MetaParser):
"""
......@@ -1548,7 +1549,7 @@ class ZeroOrMore(Option):
node, text = self.parser(text)
if not node:
break
if self._keep_node(node):
if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,)
if len(text) == n:
break # avoid infinite loop
......@@ -1599,7 +1600,7 @@ class OneOrMore(UnaryParser):
if not node:
break
match_flag = True
if self._keep_node(node):
if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,)
if len(text_) == n:
break # avoid infinite loop
......@@ -1758,7 +1759,7 @@ class Series(NaryParser):
else:
results += (node,)
break
if self._keep_node(node): # optimization
if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,)
# assert len(results) <= len(self.parsers) \
# or len(self.parsers) >= len([p for p in results if p.tag_name != ZOMBIE_TAG])
......@@ -1960,7 +1961,7 @@ class AllOf(NaryParser):
for i, parser in enumerate(parsers):
node, text__ = parser(text_)
if node:
if self._keep_node(node):
if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,)
text_ = text__
del parsers[i]
......@@ -2027,7 +2028,7 @@ class SomeOf(NaryParser):
for i, parser in enumerate(parsers):
node, text__ = parser(text_)
if node:
if self._keep_node(node):
if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,)
text_ = text__
del parsers[i]
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -59,7 +59,8 @@ class ArithmeticGrammar(Grammar):
r"""Parser for an Arithmetic source file.
"""
expression = Forward()
source_hash__ = "a8142ddc723ae56bbdf6c898efc7af45"
factor = Forward()
source_hash__ = "6bca790f81db2b6dda4c92abdbe06d90"
static_analysis_pending__ = [True]
parser_initialization__ = ["upon instantiation"]
resume_rules__ = {}
......@@ -73,12 +74,12 @@ class ArithmeticGrammar(Grammar):
NEGATIVE = RegExp('[-]')
POSITIVE = RegExp('[+]')
DIV = Series(Token("/"), dwsp__)
MUL = Series(Token("*"), dwsp__)
MUL = Alternative(Series(DropToken("*"), dwsp__), Lookahead(factor))
MINUS = Series(Token("-"), dwsp__)
PLUS = Series(Token("+"), dwsp__)
group = Series(Series(DropToken("("), dwsp__), expression, Series(DropToken(")"), dwsp__))
sign = Alternative(POSITIVE, NEGATIVE)
factor = Series(Option(sign), Alternative(NUMBER, VARIABLE, group))
factor.set(Series(Option(sign), Alternative(NUMBER, VARIABLE, group)))
term = Series(factor, ZeroOrMore(Series(Alternative(DIV, MUL), factor)))
expression.set(Series(term, ZeroOrMore(Series(Alternative(PLUS, MINUS), term))))
root__ = expression
......@@ -101,7 +102,7 @@ def get_grammar() -> ArithmeticGrammar:
#
#######################################################################
def group_no_asterix_mul(context: List[Node]):
def group_no_asterix_mul(context):
pass
# TODO: Find an algorithm, here
......
......@@ -897,7 +897,7 @@ class TestMetaParser:
"""
gr = grammar_provider(minilang)()
cst = gr("2x")
assert bool(cst.pick('MUL'))
assert bool(cst.pick('MUL')), "Named empty nodes should not be dropped!!!"
if __name__ == "__main__":
from DHParser.testing import runner
......
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