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): ...@@ -1348,6 +1348,17 @@ class DropWhitespace(Whitespace):
class MetaParser(Parser): 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: def _return_value(self, node: Optional[Node]) -> Node:
""" """
Generates a return node if a single node has been returned from Generates a return node if a single node has been returned from
...@@ -1401,16 +1412,6 @@ class MetaParser(Parser): ...@@ -1401,16 +1412,6 @@ class MetaParser(Parser):
return EMPTY_NODE # avoid creation of a node object for anonymous empty nodes return EMPTY_NODE # avoid creation of a node object for anonymous empty nodes
return Node(self.tag_name, results) # unoptimized code 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): class UnaryParser(MetaParser):
""" """
...@@ -1548,7 +1549,7 @@ class ZeroOrMore(Option): ...@@ -1548,7 +1549,7 @@ class ZeroOrMore(Option):
node, text = self.parser(text) node, text = self.parser(text)
if not node: if not node:
break break
if self._keep_node(node): if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,) results += (node,)
if len(text) == n: if len(text) == n:
break # avoid infinite loop break # avoid infinite loop
...@@ -1599,7 +1600,7 @@ class OneOrMore(UnaryParser): ...@@ -1599,7 +1600,7 @@ class OneOrMore(UnaryParser):
if not node: if not node:
break break
match_flag = True match_flag = True
if self._keep_node(node): if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,) results += (node,)
if len(text_) == n: if len(text_) == n:
break # avoid infinite loop break # avoid infinite loop
...@@ -1758,7 +1759,7 @@ class Series(NaryParser): ...@@ -1758,7 +1759,7 @@ class Series(NaryParser):
else: else:
results += (node,) results += (node,)
break break
if self._keep_node(node): # optimization if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,) results += (node,)
# assert len(results) <= len(self.parsers) \ # assert len(results) <= len(self.parsers) \
# or len(self.parsers) >= len([p for p in results if p.tag_name != ZOMBIE_TAG]) # or len(self.parsers) >= len([p for p in results if p.tag_name != ZOMBIE_TAG])
...@@ -1960,7 +1961,7 @@ class AllOf(NaryParser): ...@@ -1960,7 +1961,7 @@ class AllOf(NaryParser):
for i, parser in enumerate(parsers): for i, parser in enumerate(parsers):
node, text__ = parser(text_) node, text__ = parser(text_)
if node: if node:
if self._keep_node(node): if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,) results += (node,)
text_ = text__ text_ = text__
del parsers[i] del parsers[i]
...@@ -2027,7 +2028,7 @@ class SomeOf(NaryParser): ...@@ -2027,7 +2028,7 @@ class SomeOf(NaryParser):
for i, parser in enumerate(parsers): for i, parser in enumerate(parsers):
node, text__ = parser(text_) node, text__ = parser(text_)
if node: if node:
if self._keep_node(node): if node._result or node.tag_name[0:1] != ':': # drop anonymous empty nodes
results += (node,) results += (node,)
text_ = text__ text_ = text__
del parsers[i] 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): ...@@ -59,7 +59,8 @@ class ArithmeticGrammar(Grammar):
r"""Parser for an Arithmetic source file. r"""Parser for an Arithmetic source file.
""" """
expression = Forward() expression = Forward()
source_hash__ = "a8142ddc723ae56bbdf6c898efc7af45" factor = Forward()
source_hash__ = "6bca790f81db2b6dda4c92abdbe06d90"
static_analysis_pending__ = [True] static_analysis_pending__ = [True]
parser_initialization__ = ["upon instantiation"] parser_initialization__ = ["upon instantiation"]
resume_rules__ = {} resume_rules__ = {}
...@@ -73,12 +74,12 @@ class ArithmeticGrammar(Grammar): ...@@ -73,12 +74,12 @@ class ArithmeticGrammar(Grammar):
NEGATIVE = RegExp('[-]') NEGATIVE = RegExp('[-]')
POSITIVE = RegExp('[+]') POSITIVE = RegExp('[+]')
DIV = Series(Token("/"), dwsp__) DIV = Series(Token("/"), dwsp__)
MUL = Series(Token("*"), dwsp__) MUL = Alternative(Series(DropToken("*"), dwsp__), Lookahead(factor))
MINUS = Series(Token("-"), dwsp__) MINUS = Series(Token("-"), dwsp__)
PLUS = Series(Token("+"), dwsp__) PLUS = Series(Token("+"), dwsp__)
group = Series(Series(DropToken("("), dwsp__), expression, Series(DropToken(")"), dwsp__)) group = Series(Series(DropToken("("), dwsp__), expression, Series(DropToken(")"), dwsp__))
sign = Alternative(POSITIVE, NEGATIVE) 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))) term = Series(factor, ZeroOrMore(Series(Alternative(DIV, MUL), factor)))
expression.set(Series(term, ZeroOrMore(Series(Alternative(PLUS, MINUS), term)))) expression.set(Series(term, ZeroOrMore(Series(Alternative(PLUS, MINUS), term))))
root__ = expression root__ = expression
...@@ -101,7 +102,7 @@ def get_grammar() -> ArithmeticGrammar: ...@@ -101,7 +102,7 @@ def get_grammar() -> ArithmeticGrammar:
# #
####################################################################### #######################################################################
def group_no_asterix_mul(context: List[Node]): def group_no_asterix_mul(context):
pass pass
# TODO: Find an algorithm, here # TODO: Find an algorithm, here
......
...@@ -897,7 +897,7 @@ class TestMetaParser: ...@@ -897,7 +897,7 @@ class TestMetaParser:
""" """
gr = grammar_provider(minilang)() gr = grammar_provider(minilang)()
cst = gr("2x") cst = gr("2x")
assert bool(cst.pick('MUL')) assert bool(cst.pick('MUL')), "Named empty nodes should not be dropped!!!"
if __name__ == "__main__": if __name__ == "__main__":
from DHParser.testing import runner 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