|
|
@@ -195,6 +195,86 @@ def maybe_create_ambiguous_expander(tree_class, expansion, keep_all_tokens): |
|
|
|
if to_expand: |
|
|
|
return partial(AmbiguousExpander, to_expand, tree_class) |
|
|
|
|
|
|
|
class AmbiguousIntermediateExpander: |
|
|
|
""" |
|
|
|
Propagate ambiguous intermediate nodes and their derivations up to the |
|
|
|
current rule. |
|
|
|
|
|
|
|
In general, converts |
|
|
|
|
|
|
|
rule |
|
|
|
_iambig |
|
|
|
_inter |
|
|
|
someChildren1 |
|
|
|
... |
|
|
|
_inter |
|
|
|
someChildren2 |
|
|
|
... |
|
|
|
someChildren3 |
|
|
|
... |
|
|
|
|
|
|
|
to |
|
|
|
|
|
|
|
_ambig |
|
|
|
rule |
|
|
|
someChildren1 |
|
|
|
... |
|
|
|
someChildren3 |
|
|
|
... |
|
|
|
rule |
|
|
|
someChildren2 |
|
|
|
... |
|
|
|
someChildren3 |
|
|
|
... |
|
|
|
rule |
|
|
|
childrenFromNestedIambigs |
|
|
|
... |
|
|
|
someChildren3 |
|
|
|
... |
|
|
|
... |
|
|
|
|
|
|
|
propagating up any nested '_iambig' nodes along the way. |
|
|
|
""" |
|
|
|
|
|
|
|
def __init__(self, tree_class, node_builder): |
|
|
|
self.node_builder = node_builder |
|
|
|
self.tree_class = tree_class |
|
|
|
|
|
|
|
def __call__(self, children): |
|
|
|
def _is_iambig_tree(child): |
|
|
|
return hasattr(child, 'data') and child.data == '_iambig' |
|
|
|
|
|
|
|
def _collapse_iambig(children): |
|
|
|
""" |
|
|
|
Recursively flatten the derivations of the parent of an '_iambig' |
|
|
|
node. Returns a list of '_inter' nodes guaranteed not |
|
|
|
to contain any nested '_iambig' nodes, or None if children does |
|
|
|
not contain an '_iambig' node. |
|
|
|
""" |
|
|
|
|
|
|
|
# Due to the structure of the SPPF, |
|
|
|
# an '_iambig' node can only appear as the first child |
|
|
|
if children and _is_iambig_tree(children[0]): |
|
|
|
iambig_node = children[0] |
|
|
|
result = [] |
|
|
|
for grandchild in iambig_node.children: |
|
|
|
collapsed = _collapse_iambig(grandchild.children) |
|
|
|
if collapsed: |
|
|
|
for child in collapsed: |
|
|
|
child.children += children[1:] |
|
|
|
result += collapsed |
|
|
|
else: |
|
|
|
new_tree = self.tree_class('_inter', grandchild.children + children[1:]) |
|
|
|
result.append(new_tree) |
|
|
|
return result |
|
|
|
|
|
|
|
collapsed = _collapse_iambig(children) |
|
|
|
if collapsed: |
|
|
|
processed_nodes = [self.node_builder(c.children) for c in collapsed] |
|
|
|
return self.tree_class('_ambig', processed_nodes) |
|
|
|
|
|
|
|
return self.node_builder(children) |
|
|
|
|
|
|
|
def ptb_inline_args(func): |
|
|
|
@wraps(func) |
|
|
|
def f(children): |
|
|
@@ -239,6 +319,7 @@ class ParseTreeBuilder: |
|
|
|
maybe_create_child_filter(rule.expansion, keep_all_tokens, self.ambiguous, options.empty_indices if self.maybe_placeholders else None), |
|
|
|
self.propagate_positions and PropagatePositions, |
|
|
|
self.ambiguous and maybe_create_ambiguous_expander(self.tree_class, rule.expansion, keep_all_tokens), |
|
|
|
self.ambiguous and partial(AmbiguousIntermediateExpander, self.tree_class) |
|
|
|
])) |
|
|
|
|
|
|
|
yield rule, wrapper_chain |
|
|
|