Exemplo n.º 1
0
 def generate_splitting(self, counter, first_nt, also):
     """generate_splitting
     Generate the splitting for the branches
     :param counter: The first index to use to generate rules
     :param first_nt: the first non terminal of the tree (the head)
     """
     rules = []
     initial_counter = counter
     if len(self.others) == 0:
         rules.append(DuplicationRule("C", "T", first_nt))
     elif len(self.others) == 1:
         rules.append(DuplicationRule("C", "CD" + str(counter), first_nt))
     else:
         rules.append(
             DuplicationRule("C", "CD" + str(counter),
                             "K" + str(counter + 1)))
         counter += 1
         for i in range(len(self.others) - 2):
             rules.append(
                 DuplicationRule("K" + str(counter), "CD" + str(counter),
                                 "K" + str(counter + 1)))
             counter += 1
         rules.append(
             DuplicationRule("K" + str(counter), "CD" + str(counter),
                             first_nt))
         # Stacking
         for i in range(len(self.others)):
             temp = stack(["end"] + self.others[i].part0 + also, counter,
                          "CD" + str(initial_counter + i), "C")
             counter = temp[1]
             rules = rules + temp[0]
     return (rules, counter)
Exemplo n.º 2
0
 def consume_tree(self, first: str, last: str,
                  counter: int) -> Tuple[List[ReducedRule], int]:
     """consume_tree
     In the creation of rules in the grammar, consumes symbols
     :param first: The first symbol in the grammar to use
     :param last: The last symbol in the grammar to use
     :param counter: A counter to prevent duplication of non-terminals
     :type first: str
     :type last: str
     :type counter: int
     :return: A couple which contains first the rules generated and then\
                 the next counter to use
     :rtype: A couple of a list of Reduced rules and an int
     """
     rules = []
     if not self.head.is_str():
         # It means we have a function...
         return utils.unstack(self.head.get_function().part0, [], counter,
                              first, last)
     elif self.head.get_str() == ".":
         # When concatenation
         temp_nt = [first]
         # Creates intermediate non-terminals
         for _ in range(len(self.sons)):
             temp_nt.append("C" + str(counter))
             counter += 1
         # Consume each son separately and join them with the intermediate
         # non-terminals
         for i in range(len(self.sons)):
             temp = self.sons[i].consume_tree(temp_nt[i], temp_nt[i + 1],
                                              counter)
             rules += temp[0]
             counter = temp[1]
         # link last intermediate to the last non-symbol
         rules.append(DuplicationRule(temp_nt[-1], "T", last))
         return (rules, counter)
     elif self.head.get_str() == "|":
         # Or node
         # Each son is consumed separately and they all have the same first
         # and last non-terminals
         for son in self.sons:
             temp = son.consume_tree(first, last, counter)
             rules += temp[0]
             counter = temp[1]
         return (rules, counter)
     elif self.head.get_str() == "*":
         # Kleene star
         # We make the first symbol go directly to the last one, to simulate
         # the empty case
         rules.append(DuplicationRule(first, "T", last))
         # Normally just one
         for son in self.sons:
             # We should end where we begin
             temp = son.consume_tree(last, last, counter)
             rules += temp[0]
             counter = temp[1]
         return (rules, counter)
     return (rules, counter)
Exemplo n.º 3
0
 def generate_general_reduced_rules(self, counter, i, j):
     """generate_general_reduced_rules
     Generate a middle rule, starting at ci and ending at cj
     :param counter: The counter to avoid collision
     :param i: index of the first relation
     :param j: index of the last relation
     """
     rules = []
     rules.append(
         DuplicationRule("C", "A" + str(counter), "D" + str(counter)))
     temp_counter = counter
     temp = stack(["end"] + self.part1[:i], counter + 1, "A" + str(counter),
                  "C")
     counter = temp[1]
     rules = rules + temp[0]
     temp = unstack(self.part0[i:j + 1], self.part0, temp_counter,
                    "D" + str(temp_counter),
                    "Cback" + str(temp_counter + self.n_relations() + 1))
     counter = temp[1]
     rules = rules + temp[0]
     counter = max(counter, temp_counter)
     counter += 1
     temp = stack(self.part1[j + 1:], counter,
                  "Cback" + str(temp_counter + self.n_relations() + 1), "C")
     counter = temp[1]
     rules = rules + temp[0]
     return (rules, counter)
Exemplo n.º 4
0
def stack(s_relations, counter, start, end):
    """stack
    Stack the given relations on the stack using reduced rules.
    :param s_relations: The relations to stack
    :param counter: The counter to avoid collisions
    :param start: The starting non-terminal
    :param end: The ending non-terminal
    """
    rules = []
    if len(s_relations) == 0:
        rules.append(DuplicationRule(start,
                                     "T",
                                     end))
    elif len(s_relations) == 1:
        rules.append(ProductionRule(start,
                                    end,
                                    s_relations[0]))
    else:
        rules.append(ProductionRule(start,
                                    "A" + str(counter),
                                    s_relations[0]))
    for x in range(1, len(s_relations) - 1):
        rules.append(ProductionRule("A" + str(counter),
                                    "A" + str(counter + 1),
                                    s_relations[x]))
        counter += 1
    if len(s_relations) > 1:
        rules.append(ProductionRule("A" + str(counter),
                                    end,
                                    s_relations[-1]))
    counter += 1
    return (rules, counter)
Exemplo n.º 5
0
def get_ISWC_grammar(relations, query):
    rules = []
    rules.append(EndRule("T", "epsilon"))
    rules.append(ProductionRule("S", "Finit", "end"))
    rules.append(ProductionRule("Finit", "F", query))
    for relation in relations:
        rules.append(DuplicationRule("F", relation, "F" + relation))
        rules.append(EndRule(relation, relation))
        rules.append(ProductionRule("F" + relation, "F", relation))
        rules.append(ConsommationRule(relation, "B", "Btemp" + relation))
        rules.append(DuplicationRule("Btemp" + relation,
                                     "Lleft" + relation,
                                     "B"))
        rules.append(DuplicationRule("Lleft", "L" + relation, relation))
        rules.append(ProductionRule("L" + relation, "L", relation))
        rules.append(ConsommationRule(relation, "L", "Ltemp" + relation))
        rules.append(DuplicationRule("Ltemp" + relation,
                                     "Lleft" + relation,
                                     "Lright" + relation))
        rules.append(DuplicationRule("Lleft" + relation,
                                     inverse(relation),
                                     "L"))
        rules.append(DuplicationRule("Lright" + relation,
                                     relation,
                                     "L" + relation))
    rules.append(EndRule("L", "epsilon"))
    rules.append(ConsommationRule("end", "B", "T"))
    rules.append(DuplicationRule("F", "B", "T"))
    rules = Rules(rules)
    return IndexedGrammar(rules)
Exemplo n.º 6
0
def unstack(u_relations, all_relations, counter, start, end):
    """unstack
    Unstack the given relation from the stack by using reduced forms
    :param u_relations: The relations to unstack
    :param all_relations: All the relations used
    :param counter: Counter to avoid collision
    :param start: the starting non-terminal
    :param end: the ending non-terminal
    """
    rules = []
    if len(u_relations) != 0:
        rules.append(DuplicationRule(start,
                                     "T",
                                     "C" + str(counter)))
    else:
        rules.append(DuplicationRule(start,
                                     "T",
                                     end))
    temp_counter = counter
    if len(u_relations) > 1:
        rules.append(ConsommationRule(u_relations[0],
                                      "C" + str(counter),
                                      "C" + str(counter + 1)))
        counter += 1
    elif len(u_relations) == 1:
        rules.append(ConsommationRule(u_relations[0],
                                      "C" + str(counter),
                                      end))
    for x in range(1, len(u_relations) - 1):
        rules.append(ConsommationRule(u_relations[x],
                                      "C" + str(counter),
                                      "C" + str(counter + 1)))
        counter += 1
    if len(u_relations) > 1:
        rules.append(ConsommationRule(u_relations[-1],
                                      "C" + str(counter),
                                      end))
    for x in range(len(all_relations)):
        temp_counter += 1
    counter = max(temp_counter, counter)
    counter += 1
    return (rules, counter)
Exemplo n.º 7
0
def get_translated_rule(rule, translator):
    if rule.isDuplication():
        return DuplicationRule(translator[rule.getLeftTerm()],
                               translator[rule.getRightTerms()[0]],
                               translator[rule.getRightTerms()[1]])
    if rule.isEndRule():
        return EndRule(translator[rule.getLeftTerm()],
                       rule.getRightTerm())
    if rule.isProduction():
        return ProductionRule(translator[rule.getLeftTerm()],
                              translator[rule.getRightTerm()],
                              rule.getProduction())
    if rule.isConsommation():
        return ConsommationRule(rule.getF(),
                                translator[rule.getLeftTerm()],
                                translator[rule.getRight()])
Exemplo n.º 8
0
 def generate_reduced_rules(
         self,
         counter: int,
         empty: bool = False) -> Tuple[List[ReducedRule], int]:
     """generate_reduced_rules
     Generates a set of reduced rules
     :param counter: A counter to prevent duplication of non-terminals
     :param empty: Whether to use the empty rule or not
     :type counter: int
     :type empty: bool
     :return: A tuple with rules and the new counter
     :rtype: Tuple[List[ReducedRule], int]
     """
     rules = []
     # We will cut the function into 3 parts and use these parts to generate
     # the rules of the grammar
     cuts = self.get_cuts()
     for cut in cuts:
         cuts2 = RegexTree(Node(cut[0])).get_cuts()
         for cut2 in cuts2:
             if empty and cut2[0] != "":
                 continue
             if not empty and cut2[1] == "":
                 continue
             # We split the rule into the three parts we are considering
             c_left = "Cleft" + str(counter)
             c_right = "Cright" + str(counter)
             c_inter = "Cinter" + str(counter)
             rules.append(DuplicationRule("C", c_left, c_right))
             res = RegexTree(Node(cut2[0])).push_tree(c_left,
                                                      "C",
                                                      counter,
                                                      end=True)
             rules += res[0]
             counter = res[1]
             res = RegexTree(Node(cut2[1])).consume_tree(
                 c_right, c_inter, counter)
             rules += res[0]
             counter = res[1]
             res = RegexTree(Node(cut[1])).push_tree(c_inter,
                                                     "C",
                                                     counter,
                                                     end=False)
             rules += res[0]
             counter = res[1]
     return (rules, counter)
Exemplo n.º 9
0
 def generate_right_reduced_rules(self, counter):
     """generate_right_reduced_rules
     Generates the reduced right rules as describe in the paper.
     :param counter: counter used to be sure we do not duplicate
     non-terminals. So, it MUST be update after the function.
     :return A couple (rules, counter) containing the generated rules and the
     new counter value
     """
     rules = []
     for i in range(1, self.n_relations()):
         rules.append(
             DuplicationRule("C", "A" + str(counter), "D" + str(counter)))
         temp_counter = counter
         temp = stack(["end"] + self.part1[:i], counter, "A" + str(counter),
                      "C")
         counter = temp[1]
         rules = rules + temp[0]
         temp = unstack(self.part0[i:self.n_relations()], self.part0,
                        temp_counter, "D" + str(temp_counter), "C")
         counter = temp[1]
         rules = rules + temp[0]
         counter = max(counter, temp_counter)
         counter += 1
     return (rules, counter)
Exemplo n.º 10
0
 def __get_initial_palindrom_rules(self, query):
     initial_rules = []
     self.init_counter = -1
     initial_rules.append(ProductionRule("S", "Cinitquery", "end"))
     initial_rules.append(ProductionRule("Cinitquery", "Cforward", "query"))
     for j in range(len(query)):
         self.init_counter += 1
         initial_rules.append(
             ConsommationRule("query", "Cforward",
                              "Cinit" + str(self.init_counter)))
         for i in range(len(query[j]) - 1):
             initial_rules.append(
                 ProductionRule("Cinit" + str(self.init_counter),
                                "Cinit" + str(self.init_counter + 1),
                                query[j][len(query[j]) - i - 1]))
             self.init_counter += 1
         initial_rules.append(
             ProductionRule("Cinit" + str(self.init_counter), "Cforward",
                            query[j][0]))
     initial_rules.append(ConsommationRule("end", "Cbackward", "T"))
     initial_rules.append(ConsommationRule("end", "Cend", "T"))
     initial_rules.append(DuplicationRule("Cforward", "Cbackward", "T"))
     initial_rules.append(EndRule("T", "epsilon"))
     return initial_rules
Exemplo n.º 11
0
 def push_tree(self,
               first: str,
               last: str,
               counter: int,
               end: bool = False) -> Tuple[List[ReducedRule], int]:
     """push_tree
     Push the regex on the stack of the grammar.
     :param first: The firts non-terminal to use
     :param last: The last non-terminal to use
     :param counter: A counter to prevent duplication of non-terminals
     :param end: Whether an end symbol should be added to the stack
     :type first: str
     :type last: str
     :type counter: int
     :type end: boolean
     :return: A couple which contains first the rules generated and then\
                 the next counter to use
     :rtype: A couple of a list of Reduced rules and an int
     """
     rules = []
     # We begin by pushing the end symbol if necessary
     if end:
         rules.append(ProductionRule(first, "Ce" + str(counter), "end"))
         first = "Ce" + str(counter)
     if not self.head.is_str():
         # i.e. we have a function
         res = utils.stack(self.head.get_function().part1, counter, first,
                           last)
         rules += res[0]
         counter = res[1]
         return (rules, counter)
     elif self.head.get_str() == ".":
         # Concatenation
         # Creates intermediate non-terminals
         temp_nt = [first]
         for _ in range(len(self.sons)):
             temp_nt.append("C" + str(counter))
             counter += 1
         # Consume each son separately and join them with the intermediate
         # non-terminals
         for i in range(len(self.sons)):
             temp = self.sons[i].push_tree(temp_nt[i], temp_nt[i + 1],
                                           counter)
             rules += temp[0]
             counter = temp[1]
         # link last intermediate to the last non-symbol
         rules.append(DuplicationRule(temp_nt[-1], "T", last))
         return (rules, counter)
     elif self.head.get_str() == "|":
         # Or node
         # Each son is pushed separately and they all have the same first
         # and last non-terminals
         for son in self.sons:
             temp = son.push_tree(first, last, counter)
             rules += temp[0]
             counter = temp[1]
         return (rules, counter)
     elif self.head.get_str() == "*":
         # Kleene star
         # We make the first symbol go directly to the last one, to simulate
         # the empty case
         rules.append(DuplicationRule(first, "T", last))
         # Normally just one
         for son in self.sons:
             # We should end where we begin
             temp = son.push_tree(last, last, counter)
             rules += temp[0]
             counter = temp[1]
         return (rules, counter)
     return (rules, counter)
Exemplo n.º 12
0
 def intersect_indexed_grammar(self, indexed_grammar):
     rules = indexed_grammar.rules
     new_rules = []
     terminals = rules.getTerminals()
     new_rules.append(EndRule("T", "epsilon"))
     consommations = rules.getConsommationRules()
     for f in consommations:
         for consommation in consommations[f]:
             for r in self.Q:
                 for s in self.Q:
                     new_rules.append(
                         ConsommationRule(
                             consommation.getF(),
                             str((r, consommation.getLeftTerm(), s)),
                             str((r, consommation.getRight(), s))))
     for rule in rules.getRules():
         if rule.isDuplication():
             for p in self.Q:
                 for q in self.Q:
                     for r in self.Q:
                         new_rules.append(
                             DuplicationRule(
                                 str((p, rule.getLeftTerm(), q)),
                                 str((p, rule.getRightTerms()[0], r)),
                                 str((r, rule.getRightTerms()[1], q))))
         elif rule.isProduction():
             for p in self.Q:
                 for q in self.Q:
                     new_rules.append(
                         ProductionRule(str((p, rule.getLeftTerm(), q)),
                                        str((p, rule.getRightTerm(), q)),
                                        str(rule.getProduction())))
         elif rule.isEndRule():
             for p in self.Q:
                 for q in self.Q:
                     new_rules.append(
                         DuplicationRule(str((p, rule.getLeftTerm(), q)),
                                         str((p, rule.getRightTerm(), q)),
                                         "T"))
     for a in terminals:
         for p in self.Q:
             for q in self.Q:
                 for r in self.Q:
                     new_rules.append(
                         DuplicationRule(str((p, a, q)),
                                         str((p, "epsilon", r)),
                                         str((r, a, q))))
                     new_rules.append(
                         DuplicationRule(str((p, a, q)), str((p, a, r)),
                                         str((r, "epsilon", q))))
     for p in self.Q:
         for q in self.Q:
             for r in self.Q:
                 new_rules.append(
                     DuplicationRule(str((p, "epsilon", q)),
                                     str((p, "epsilon", r)),
                                     str((r, "epsilon", q))))
     for key in self.delta:
         p = key[0]
         a = key[1]
         q = self.delta[key][0]
         x = self.delta[key][1]
         new_rules.append(EndRule(str((p, a, q)), x))
     for p in self.Q:
         new_rules.append(EndRule(str((p, "epsilon", p)), "epsilon"))
     for p in self.F:
         new_rules.append(DuplicationRule("S", str((self.q0, "S", p)), "T"))
     rules = Rules(new_rules)
     return IndexedGrammar(rules)