|
@@ -121,16 +121,6 @@ class ChildFilterLALR_NoPlaceholders(ChildFilter): |
|
|
def _should_expand(sym): |
|
|
def _should_expand(sym): |
|
|
return not sym.is_term and sym.name.startswith('_') |
|
|
return not sym.is_term and sym.name.startswith('_') |
|
|
|
|
|
|
|
|
class AmbiguousExpander: |
|
|
|
|
|
"""Deal with the case where we're expanding children ('_rule') into a parent but the children |
|
|
|
|
|
are ambiguous. i.e. (parent->_ambig->_expand_this_rule). In this case, make the parent itself |
|
|
|
|
|
ambiguous with as many copies as their are ambiguous children, and then copy the ambiguous children |
|
|
|
|
|
into the right parents in the right places, essentially shifting the ambiguiuty up the tree.""" |
|
|
|
|
|
def __init__(self, to_expand, tree_class, node_builder): |
|
|
|
|
|
self.node_builder = node_builder |
|
|
|
|
|
self.tree_class = tree_class |
|
|
|
|
|
self.to_expand = to_expand |
|
|
|
|
|
|
|
|
|
|
|
def maybe_create_child_filter(expansion, keep_all_tokens, ambiguous, _empty_indices): |
|
|
def maybe_create_child_filter(expansion, keep_all_tokens, ambiguous, _empty_indices): |
|
|
# Prepare empty_indices as: How many Nones to insert at each index? |
|
|
# Prepare empty_indices as: How many Nones to insert at each index? |
|
|
if _empty_indices: |
|
|
if _empty_indices: |
|
@@ -158,15 +148,38 @@ def maybe_create_child_filter(expansion, keep_all_tokens, ambiguous, _empty_indi |
|
|
# LALR without placeholders |
|
|
# LALR without placeholders |
|
|
return partial(ChildFilterLALR_NoPlaceholders, [(i, x) for i,x,_ in to_include]) |
|
|
return partial(ChildFilterLALR_NoPlaceholders, [(i, x) for i,x,_ in to_include]) |
|
|
|
|
|
|
|
|
|
|
|
class AmbiguousExpander: |
|
|
|
|
|
"""Deal with the case where we're expanding children ('_rule') into a parent but the children |
|
|
|
|
|
are ambiguous. i.e. (parent->_ambig->_expand_this_rule). In this case, make the parent itself |
|
|
|
|
|
ambiguous with as many copies as their are ambiguous children, and then copy the ambiguous children |
|
|
|
|
|
into the right parents in the right places, essentially shifting the ambiguiuty up the tree.""" |
|
|
|
|
|
def __init__(self, to_expand, tree_class, node_builder): |
|
|
|
|
|
self.node_builder = node_builder |
|
|
|
|
|
self.tree_class = tree_class |
|
|
|
|
|
self.to_expand = to_expand |
|
|
|
|
|
|
|
|
def __call__(self, children): |
|
|
def __call__(self, children): |
|
|
def _is_ambig_tree(child): |
|
|
def _is_ambig_tree(child): |
|
|
return hasattr(child, 'data') and child.data == '_ambig' |
|
|
return hasattr(child, 'data') and child.data == '_ambig' |
|
|
|
|
|
|
|
|
ambiguous = [i for i in self.to_expand if _is_ambig_tree(children[i])] |
|
|
|
|
|
if ambiguous: |
|
|
|
|
|
expand = [iter(child.children) if i in ambiguous else repeat(child) for i, child in enumerate(children)] |
|
|
|
|
|
return self.tree_class('_ambig', [self.node_builder(list(f[0])) for f in product(zip(*expand))]) |
|
|
|
|
|
return self.node_builder(children) |
|
|
|
|
|
|
|
|
#### When we're repeatedly expanding ambiguities we can end up with nested ambiguities. |
|
|
|
|
|
# All children of an _ambig node should be a derivation of that ambig node, hence |
|
|
|
|
|
# it is safe to assume that if we see an _ambig node nested within an ambig node |
|
|
|
|
|
# it is safe to simply expand it into the parent _ambig node as an alternative derivation. |
|
|
|
|
|
ambiguous = [] |
|
|
|
|
|
for i, child in enumerate(children): |
|
|
|
|
|
if _is_ambig_tree(child): |
|
|
|
|
|
if i in self.to_expand: |
|
|
|
|
|
ambiguous.append(i) |
|
|
|
|
|
|
|
|
|
|
|
to_expand = [j for j, grandchild in enumerate(child.children) if _is_ambig_tree(grandchild)] |
|
|
|
|
|
child.expand_kids_by_index(*to_expand) |
|
|
|
|
|
|
|
|
|
|
|
if not ambiguous: |
|
|
|
|
|
return self.node_builder(children) |
|
|
|
|
|
|
|
|
|
|
|
expand = [ iter(child.children) if i in ambiguous else repeat(child) for i, child in enumerate(children) ] |
|
|
|
|
|
return self.tree_class('_ambig', [self.node_builder(list(f[0])) for f in product(zip(*expand))]) |
|
|
|
|
|
|
|
|
def maybe_create_ambiguous_expander(tree_class, expansion, keep_all_tokens): |
|
|
def maybe_create_ambiguous_expander(tree_class, expansion, keep_all_tokens): |
|
|
to_expand = [i for i, sym in enumerate(expansion) |
|
|
to_expand = [i for i, sym in enumerate(expansion) |
|
|