| @@ -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) | ||||