def create_snippet(parent, children, choice, key): """ Given a parent NT and a list of child trees, create a new tree that acts as the parent of the given children. Generates this tree as a snippet and adds the new snippet to the trackers.snippets library. :param parent: A non-terminal root. :param children: A list of derivation tree instances. :param choice: The chosen production choice. :param key: A new key for the trackers.snippets dictionary. :return: Nothing. """ # Initialise new instance of the tree class to act as new snippet. new_tree = tree.Tree(parent, None) # Generate a codon to match the given production choice. new_tree.codon = generate_codon(parent, choice) # Save the snippet key of this tree. new_tree.snippet = key # Add the children to the new node for child in children: new_tree.children.append(child) # Set the parent of the child to the new node child.parent = new_tree # Add new snippet to snippets dictionary trackers.snippets[key] = new_tree
def check_reductions(alt_cs, pre, aft, idx, children): """ Given a list of the indexes of potential children, find snippets which match adjacent portions of the target string that can be used as these children. :param alt_cs: An ordered list of indexes of potential Terminals or Non Terminals to reduce_trees. :param pre: The start index of the overall snippet on the target string. :param aft: The end index of the overall snippet on the target string. :param children: A list of children to be reduced. :param idx: The index of the current child. :return: The same inputs, in the same order. """ if idx < len(alt_cs): # Take the next available unexpanded item from the # list. child_idx = alt_cs[idx] child = NTs[child_idx] # Increment counter. idx += 1 if pre is None: # Then we are starting with an NT which # directly follows the current NT. if child[1] == "T": # Then we can immediately check if this # reduction T is legally allowed # follow the current NT in the target # string. # Get output to check for match. check = child[0] # Get portion of target string to match. end_point = aft + len(check) target = params['TARGET'][ aft:end_point] if target == check: # The current terminal matches the same # location on the target string. # Generate fake key for snippets dict. key = str([aft, end_point]) # Increment aft phenotype counter. aft += len(check) # Create new tree from this terminal. T_tree = tree.Tree(check, None) # Add to children. children[child_idx] = [key, T_tree] if alt_cs: # Recurse to find the next piece of # the puzzle. check_reductions( alt_cs, pre, aft, idx, children) elif child[1] == "NT": # Check to see if there are any snippets # which can be reduced to the current # block. # Find all potential snippets which # match our criteria. matches = [ v for v in sorted_keys if v[0][0] == aft and v[1] == child[0] ] # Create a copy of this marker otherwise # each match will over-write it. aft_c = copy(aft) for match in matches: # Iterate over all potential matches. # Calculate length of match string. str_len = match[0] # Increment appropriate phenotype # counter. aft_c = aft + str_len[1] - str_len[ 0] # Add to children. children[child_idx] = [ match[2], trackers.snippets[match[2]] ] if alt_cs: # Recurse to find the next piece of # the puzzle. check_reductions( alt_cs, pre, aft_c, idx, children) elif aft is None: # Then we are starting with an NT which # directly precedes the current NT. if child[1] == "T": # Then we can immediately check if this # reduction T is legally allowed # follow the current NT in the target # string. # Get output to check for match. check = child[0] # Get portion of target string to match. start_point = pre - len(check) target = params['TARGET'][ start_point:pre] if target == check: # The current terminal matches the same # location on the target string. # Generate fake key for snippets dict. key = str([start_point, pre]) # Increment pre phenotype counter. pre -= len(check) # Create new tree from this terminal. T_tree = tree.Tree(check, None) # Add to children. children[child_idx] = [key, T_tree] if alt_cs: # Recurse to find the next piece of # the puzzle. check_reductions( alt_cs, pre, aft, idx, children) elif child[1] == "NT": # Check to see if there are any snippets # which can be reduced to the current # block. # Find all potential snippets which # match our criteria. matches = [ v for v in sorted_keys if v[0][1] == pre and v[1] == child[0] ] # Create a copy of this marker otherwise # each match will over-write it. pre_c = copy(pre) for match in matches: # Iterate over all potential matches. # Calculate length of match string. str_len = match[0] # Increment appropriate phenotype # counter. pre_c = pre - str_len[1] + str_len[ 0] # Add to children. children[child_idx] = [ match[2], trackers.snippets[match[2]] ] if alt_cs: # Recurse to find the next piece of # the puzzle. check_reductions( alt_cs, pre_c, aft, idx, children) else: # Our starting NT is somewhere in the middle # of the proposed reduction. if child[1] == "T": # Then we can immediately check if this # reduction T is legally allowed be # where it wants to be. # Get output to check for match. check = child[0] # Get portion of target string to match. if child_idx > loc: # This T comes after the original NT. start_point = aft end_point = start_point + len( check) else: # This T comes before the original NT. start_point = pre - len(check) end_point = pre target = params['TARGET'][ start_point:end_point] if target == check: # The current terminal matches the same # location on the target string. # Increment appropriate phenotype # counter. if child_idx > loc: # This T comes after the original # NT. aft += len(check) else: # This T comes before the original # NT. pre -= len(check) # Generate fake key for snippets dict. key = str([start_point, end_point]) # Create new tree from this terminal. T_tree = tree.Tree(check, None) # Add to children. children[child_idx] = [key, T_tree] if alt_cs: # Recurse to find the next piece of # the puzzle. check_reductions( alt_cs, pre, aft, idx, children) elif child[1] == "NT": # Check to see if there are any snippets # which can be reduced to the current # block. # Get portion of target string to match. if child_idx > loc: # This NT comes after the original NT. matches = [ v for v in sorted_keys if v[0][0] == aft and v[1] == child[0] ] else: # This NT comes before the original NT. matches = [ v for v in sorted_keys if v[0][1] == pre and v[1] == child[0] ] # Create copies of this markers otherwise # each match will over-write them. pre_c, aft_c = copy(pre), copy(aft) for match in matches: # Iterate over all potential matches. # Calculate length of match string. str_len = match[0] # Increment appropriate phenotype # counter. if child_idx > loc: # This NT comes after the original # NT. aft_c = aft + str_len[ 1] - str_len[0] else: # This NT comes before the original # NT. pre_c = pre - str_len[ 1] + str_len[0] # Add to children. children[child_idx] = [ match[2], trackers.snippets[match[2]] ] if alt_cs: # Recurse to find the next piece of # the puzzle. check_reductions( alt_cs, pre_c, aft_c, idx, children) elif all([i != [] for i in children]): # We have compiled a full set of potneital # children to reduce_trees. Generate a key and check # if it exists. generate_key_and_check(pre, aft, reduce, children)