|
|
@@ -499,14 +499,18 @@ class ForestToParseTree(ForestTransformer): |
|
|
|
resolve_ambiguity: If True, ambiguities will be resolved based on |
|
|
|
priorities. Otherwise, `_ambig` nodes will be in the resulting |
|
|
|
tree. |
|
|
|
use_cache: If True, the results of packed node transformations will be |
|
|
|
cached. |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__(self, tree_class=Tree, callbacks=dict(), prioritizer=ForestSumVisitor(), resolve_ambiguity=True): |
|
|
|
def __init__(self, tree_class=Tree, callbacks=dict(), prioritizer=ForestSumVisitor(), resolve_ambiguity=True, use_cache=True): |
|
|
|
super(ForestToParseTree, self).__init__() |
|
|
|
self.tree_class = tree_class |
|
|
|
self.callbacks = callbacks |
|
|
|
self.prioritizer = prioritizer |
|
|
|
self.resolve_ambiguity = resolve_ambiguity |
|
|
|
self._use_cache = use_cache |
|
|
|
self._cache = {} |
|
|
|
self._on_cycle_retreat = False |
|
|
|
self._cycle_node = None |
|
|
|
self._successful_visits = set() |
|
|
@@ -515,6 +519,7 @@ class ForestToParseTree(ForestTransformer): |
|
|
|
if self.prioritizer: |
|
|
|
self.prioritizer.visit(root) |
|
|
|
super(ForestToParseTree, self).visit(root) |
|
|
|
self._cache = {} |
|
|
|
|
|
|
|
def on_cycle(self, node, path): |
|
|
|
logger.debug("Cycle encountered in the SPPF at node: %s. " |
|
|
@@ -578,6 +583,8 @@ class ForestToParseTree(ForestTransformer): |
|
|
|
self._check_cycle(node) |
|
|
|
if self.resolve_ambiguity and id(node.parent) in self._successful_visits: |
|
|
|
raise Discard() |
|
|
|
if self._use_cache and id(node) in self._cache: |
|
|
|
return self._cache[id(node)] |
|
|
|
children = [] |
|
|
|
assert len(data) <= 2 |
|
|
|
data = PackedData(node, data) |
|
|
@@ -589,8 +596,8 @@ class ForestToParseTree(ForestTransformer): |
|
|
|
if data.right is not PackedData.NO_DATA: |
|
|
|
children.append(data.right) |
|
|
|
if node.parent.is_intermediate: |
|
|
|
return children |
|
|
|
return self._call_rule_func(node, children) |
|
|
|
return self._cache.setdefault(id(node), children) |
|
|
|
return self._cache.setdefault(id(node), self._call_rule_func(node, children)) |
|
|
|
|
|
|
|
def visit_symbol_node_in(self, node): |
|
|
|
super(ForestToParseTree, self).visit_symbol_node_in(node) |
|
|
@@ -602,7 +609,8 @@ class ForestToParseTree(ForestTransformer): |
|
|
|
self._on_cycle_retreat = False |
|
|
|
to_visit = super(ForestToParseTree, self).visit_packed_node_in(node) |
|
|
|
if not self.resolve_ambiguity or id(node.parent) not in self._successful_visits: |
|
|
|
return to_visit |
|
|
|
if not self._use_cache or id(node) not in self._cache: |
|
|
|
return to_visit |
|
|
|
|
|
|
|
def visit_packed_node_out(self, node): |
|
|
|
super(ForestToParseTree, self).visit_packed_node_out(node) |
|
|
@@ -647,10 +655,14 @@ class TreeForestTransformer(ForestToParseTree): |
|
|
|
nodes in the SPPF. |
|
|
|
:param resolve_ambiguity: If True, ambiguities will be resolved based on |
|
|
|
priorities. |
|
|
|
:param use_cache: If True, caches the results of some transformations, |
|
|
|
potentially improving performance when ``resolve_ambiguity==False``. |
|
|
|
Only use if you know what you are doing: i.e. All transformation |
|
|
|
functions are pure and referentially transparent. |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__(self, tree_class=Tree, prioritizer=ForestSumVisitor(), resolve_ambiguity=True): |
|
|
|
super(TreeForestTransformer, self).__init__(tree_class, dict(), prioritizer, resolve_ambiguity) |
|
|
|
def __init__(self, tree_class=Tree, prioritizer=ForestSumVisitor(), resolve_ambiguity=True, use_cache=False): |
|
|
|
super(TreeForestTransformer, self).__init__(tree_class, dict(), prioritizer, resolve_ambiguity, use_cache) |
|
|
|
|
|
|
|
def __default__(self, name, data): |
|
|
|
"""Default operation on tree (for override). |
|
|
|