Пример #1
0
def _duplicate_context(grammar, orig_grammar, symbol, expansion, depth, seen):
    for i in range(len(grammar[symbol])):
        if expansion is None or grammar[symbol][i] == expansion:
            new_expansion = ""
            for (s, c) in expansion_to_children(grammar[symbol][i]):
                if s in seen:  # Duplicated already
                    new_expansion += seen[s]
                elif c == [] or depth == 0:  # Terminal symbol or end of recursion
                    new_expansion += s
                else:  # Nonterminal symbol - duplicate
                    # Add new symbol with copy of rule
                    new_s = new_symbol(grammar, s)
                    grammar[new_s] = copy.deepcopy(orig_grammar[s])

                    # Duplicate its expansions recursively
                    # {**seen, **{s: new_s}} is seen + {s: new_s}
                    _duplicate_context(grammar,
                                       orig_grammar,
                                       new_s,
                                       expansion=None,
                                       depth=depth - 1,
                                       seen={
                                           **seen,
                                           **{
                                               s: new_s
                                           }
                                       })
                    new_expansion += new_s

            grammar[symbol][i] = new_expansion
Пример #2
0
    def alternate_reductions(self, tree, symbol, depth=-1):
        reductions = []

        expansions = self.grammar.get(symbol, [])
        expansions.sort(
            key=lambda expansion: len(
                expansion_to_children(expansion)))

        for expansion in expansions:
            expansion_children = expansion_to_children(expansion)

            match = True
            new_children_reductions = []
            for (alt_symbol, _) in expansion_children:
                child_reductions = self.subtrees_with_symbol(
                    tree, alt_symbol, depth=depth)
                if len(child_reductions) == 0:
                    match = False   # Child not found; cannot apply rule
                    break

                new_children_reductions.append(child_reductions)

            if not match:
                continue  # Try next alternative

            # Use the first suitable combination
            for new_children in possible_combinations(new_children_reductions):
                new_tree = (symbol, new_children)
                if number_of_nodes(new_tree) < number_of_nodes(tree):
                    reductions.append(new_tree)
                    if not self.try_all_combinations:
                        break

        # Sort by number of nodes
        reductions.sort(key=number_of_nodes)

        return reductions
Пример #3
0
    def derivation_reductions(self, tree):
        (symbol, children) = tree
        if len(children) == 0:
            return []  # Terminal symbol

        print("Trying alternative expansions for " + symbol)

        # Possible expansions for this symbol
        expansions = self.grammar[symbol]
        print("Expansions: " + repr(expansions))

        alternatives = \
            [expansion_to_children(expansion) for expansion in expansions]

        reductions = []
        for alternative in alternatives:

            if len(alternative) > len(children):
                continue  # New alternative has more children

            match = True
            new_children_reductions = []
            # print("Trying alternative expansion " + queue_to_string(alternative))
            for alt_child in alternative:
                (alt_symbol, _) = alt_child
                child_reductions = subtrees_with_symbol(alt_symbol, tree)
                if len(child_reductions) == 0:
                    # Child not found; cannot apply rule
                    match = False
                    break

                # print("Found alternatives " + queue_to_string(child_reductions))
                new_children_reductions.append(child_reductions)

            if not match:
                continue  # Try next alternative

            # Go through the possible combinations
            for new_children in possible_combinations(new_children_reductions):
                new_tree = (symbol, new_children)

                if number_of_nodes(new_tree) >= number_of_nodes(tree):
                    continue  # No reduction

                reductions.append(new_tree)

        # Apply this recursively
        if children is not None:
            for i in range(0, len(children)):
                child = children[i]
                child_reductions = self.derivation_reductions(child)
                for reduced_child in child_reductions:
                    new_children = (children[:i] + [reduced_child] +
                                    children[i + 1:])
                    reductions.append((symbol, new_children))

        # Filter duplicates
        unique_reductions = []
        for r in reductions:
            if r not in unique_reductions:
                unique_reductions.append(r)
        reductions = unique_reductions

        if len(reductions) > 0:
            # We have a new expansion
            print("Can reduce " + symbol + " " + all_terminals(tree) +
                  " to reduced subtrees " + queue_to_string(reductions))

        return reductions