예제 #1
0
    def test_generating_object(self):
        """ Test the finding of CFGObject """
        var_a = Variable("A")
        var_b = Variable("B")
        ter_a = Terminal("a")
        ter_b = Terminal("b")
        start = Variable("S")
        prod0 = Production(start, [var_a, var_b])
        prod1 = Production(start, [ter_a])
        prod2 = Production(var_a, [ter_b])
        cfg = CFG({var_a, var_b, start}, {ter_a, ter_b}, start,
                  {prod0, prod1, prod2})
        self.assertEqual(len(cfg.variables), 3)
        self.assertEqual(len(cfg.terminals), 2)
        self.assertEqual(len(cfg.productions), 3)
        self.assertEqual(cfg.get_generating_symbols(),
                         {var_a, ter_a, ter_b, start})

        prod3 = Production(var_b, [Epsilon()])

        cfg = CFG({var_a, var_b, start}, {ter_a, ter_b}, start,
                  {prod0, prod1, prod2, prod3})
        self.assertEqual(len(cfg.variables), 3)
        self.assertEqual(len(cfg.terminals), 2)
        self.assertEqual(len(cfg.productions), 4)
        self.assertEqual(cfg.get_generating_symbols(),
                         {var_a, var_b, ter_a, ter_b, start})
예제 #2
0
def part2():
    rules, words = open("in.txt").read().split("\n\n")

    rules = rules.replace("8: 42", "8: 42 | 42 8")
    rules = rules.replace("11: 42 31", "11: 42 31 | 42 11 31")

    variables = set()
    productions = set()
    terminals = set()
    for line in rules.split("\n"):
        left, right = line.split(":")
        left = Variable(left)
        variables.add(left)
        for expression in right.split("|"):
            if '"' in expression:  # Terminal expression
                expression = expression.strip('" ')
                right = [Terminal(expression)]
                terminals.add(Terminal(expression))
                productions.add(Production(left, right))
            else:
                right = [
                    Variable(token) for token in expression.strip().split()
                ]
                productions.add(Production(left, right))

    cfg = CFG(variables, terminals, Variable("0"), productions)
    count = sum(map(lambda x: 1 if cfg.contains(x) else 0, words.split("\n")))
    print(count)
예제 #3
0
 def test_get_first_set2(self):
     # Example from:
     # https://www.geeksforgeeks.org/first-set-in-syntax-analysis/
     text = """
         S -> A C B | C b b | B a
         A -> d a | B C
         B -> g | Є
         C -> h | Є
     """
     cfg = CFG.from_text(text)
     llone_parser = LLOneParser(cfg)
     first_set = llone_parser.get_first_set()
     self.assertEqual(first_set[Variable("S")],
                      {Terminal(x)
                       for x in {"d", "g", "h", "b", "a"}
                       }.union({Epsilon()}))
     self.assertEqual(first_set[Variable("A")],
                      {Terminal(x)
                       for x in {"d", "g", "h"}}.union({Epsilon()}))
     self.assertEqual(first_set[Variable("B")],
                      {Terminal(x)
                       for x in {"g"}}.union({Epsilon()}))
     self.assertEqual(first_set[Variable("C")],
                      {Terminal(x)
                       for x in {"h"}}.union({Epsilon()}))
예제 #4
0
 def test_generation_words(self):
     """ Tests the generation of word """
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     var_s = Variable("S")
     productions = {
         Production(var_s, [ter_a, var_s, ter_b]),
         Production(var_s, [])
     }
     cfg = CFG(productions=productions, start_symbol=var_s)
     words0 = list(cfg.get_words(max_length=0))
     self.assertIn([], words0)
     self.assertEqual(len(words0), 1)
     words1 = list(cfg.get_words(max_length=1))
     self.assertIn([], words1)
     self.assertEqual(len(words1), 1)
     words2 = list(cfg.get_words(max_length=2))
     self.assertIn([], words2)
     self.assertIn([ter_a, ter_b], words2)
     self.assertEqual(len(words2), 2)
     words3 = list(cfg.get_words(max_length=3))
     self.assertIn([], words3)
     self.assertIn([ter_a, ter_b], words3)
     self.assertEqual(len(words3), 2)
     words4 = list(cfg.get_words(max_length=4))
     self.assertIn([], words4)
     self.assertIn([ter_a, ter_a, ter_b, ter_b], words4)
     self.assertEqual(len(words4), 3)
예제 #5
0
def hellings(g: LabelGraph, gr: WeakCNF):
    result = LabelGraph(g.size)

    for variable in gr.variables:
        result.dict[variable] = Matrix.sparse(BOOL, g.size, g.size)

    for label in g.labels:
        result[Terminal(label)] = g[label].dup()
        for i, j, _ in zip(*result[Terminal(label)].select(lib.GxB_NONZERO).to_lists()):
            for production in gr.productions:
                if len(production.body) == 1 and production.body[0] == Terminal(label):
                    head = production.head
                    result.dict[head][i, j] = True

    if gr.generate_epsilon():
        for i in range(g.size):
            result.dict[gr.start_symbol][i, i] = True

    changing = True
    while changing:
        changing = False
        for p in gr.productions:
            if len(p.body) == 2:
                for i, k in zip(*result.dict[p.body[0]].select(lib.GxB_NONZERO).to_lists()[:2]):
                    for l, j in zip(*result.dict[p.body[1]].select(lib.GxB_NONZERO).to_lists()[:2]):
                        if k == l:
                            if (i, j) not in zip(*result.dict[p.head].select(lib.GxB_NONZERO).to_lists()[:2]):
                                changing = True
                                result.dict[p.head][i, j] = True

    return set(zip(*result.dict[gr.start_symbol].to_lists()[:2]))
예제 #6
0
    def test_intersection_dfa2(self):
        state0 = State(0)
        symb_a = Symbol("a")
        symb_b = Symbol("b")
        dfa = DeterministicFiniteAutomaton({state0}, {symb_a, symb_b},
                                           start_state=state0,
                                           final_states={state0})
        dfa.add_transition(state0, symb_a, state0)
        dfa.add_transition(state0, symb_b, state0)
        self.assertTrue(dfa.accepts([symb_a, symb_a, symb_b, symb_b]))

        ter_a = Terminal("a")
        ter_b = Terminal("b")
        var_s = Variable("S")
        var_s1 = Variable("S1")
        var_l = Variable("L")
        productions = {
            Production(var_s, [var_l, var_s1]),
            Production(var_l, [Epsilon()]),
            Production(var_s1, [ter_a, var_s1, ter_b]),
            Production(var_s1, [ter_b, var_s1, ter_a]),
            Production(var_s1, [])
        }
        cfg = CFG(productions=productions, start_symbol=var_s)
        self.assertTrue(cfg.contains([ter_a, ter_a, ter_b, ter_b]))
        self.assertFalse(cfg.contains([ter_a, ter_a, ter_b]))
        cfg_i = cfg.intersection(dfa)
        self.assertFalse(cfg_i.is_empty())
        self.assertTrue(cfg_i.contains([ter_a, ter_a, ter_b, ter_b]))
        self.assertTrue(cfg_i.contains([]))
예제 #7
0
    def _test_profiling_intersection(self):
        size = 50
        states = [State(i) for i in range(size * 2 + 1)]
        symb_a = Symbol("a")
        symb_b = Symbol("b")
        dfa = DeterministicFiniteAutomaton(states, {symb_a, symb_b},
                                           start_state=states[0],
                                           final_states={states[-1]})
        for i in range(size):
            dfa.add_transition(states[i], symb_a, states[i + 1])
        for i in range(size, size * 2):
            dfa.add_transition(states[i], symb_b, states[i + 1])

        ter_a = Terminal("a")
        ter_b = Terminal("b")
        var_s = Variable("S")
        var_s1 = Variable("S1")
        var_l = Variable("L")
        productions = [
            Production(var_s, [var_l, var_s1]),
            Production(var_l, [Epsilon()]),
            Production(var_s1, [ter_a, var_s1, ter_b]),
            Production(var_s1, [ter_b, var_s1, ter_a]),
            Production(var_s1, [])
        ]
        cfg = CFG(productions=productions, start_symbol=var_s)
        cfg_i = cfg.intersection(dfa)
        self.assertFalse(cfg_i.is_empty())
        self.assertTrue(cfg_i.contains([ter_a] * size + [ter_b] * size))
        self.assertFalse(cfg_i.contains([]))
예제 #8
0
def part2(file='input_test.txt'):
    rules, messages = get_input(file)

    # 8: 42 | 42 8
    # 11: 42 31 | 42 11 31
    rules['8'] = '42 | 42 8'
    rules['11'] = '42 31 | 42 11 31'

    rule_variables = set()
    rule_products = set()

    for rule in rules:
        subs = rules[rule].split(' | ')
        rule_variables.add(Variable(rule))
        for sub in subs:
            if sub == '"a"' or sub == '"b"':
                rule_products.add(
                    Production(Variable(rule),
                               [Terminal(sub.replace('"', ''))]))
            else:
                rule_products.add(
                    Production(Variable(rule),
                               [Variable(x) for x in sub.split(' ')]))

    cfg = CFG(rule_variables, {Terminal('a'), Terminal('b')}, Variable('0'),
              rule_products)
    count = 0

    for message in messages:
        if cfg.contains(message):
            count += 1

    print('Part 2: Solution {}'.format(count))
예제 #9
0
def cyk(config: Config) -> bool:
    word = config['word']
    query = config['pretty_cnf_query']
    if word == '':
        return query.generate_epsilon
    for char in word:
        if Terminal(char) not in query.terminals:
            return False
    len_word = len(word)
    dp: MyMatrix = MyMatrix({
        V: Matrix.sparse(types.BOOL, len_word, len_word)
        for V in query.variables
    })
    for i, char in enumerate(word):
        term = Terminal(char)
        for V in query.simple_antiproductions[term]:
            dp[i, i, V] = True
    for m in range(1, len_word):
        for i in range(len_word - m):
            j = i + m
            for A in query.variables:
                flag = False
                for B, C in query.complex_productions.get(A, set()):
                    for k in range(i, j):
                        if dp[i, k, B] and dp[k + 1, j, C]:
                            dp[i, j, A] = True
                            flag = True
                            break
                    if flag:
                        break
    return dp[0, len_word - 1, query.start_symbol]
예제 #10
0
 def test_get_llone_table(self):
     # Example from:
     # https://www.geeksforgeeks.org/construction-of-ll1-parsing-table/
     text = """
         E  -> T E’
         E’ -> + T E’ | Є
         T  -> F T’
         T’ -> * F T’ | Є
         F  -> ( E ) | id
     """
     cfg = CFG.from_text(text, start_symbol="E")
     llone_parser = LLOneParser(cfg)
     parsing_table = llone_parser.get_llone_parsing_table()
     self.assertEqual(
         len(
             parsing_table.get(Variable("E"),
                               dict()).get(Terminal("id"), [])), 1)
     self.assertEqual(
         len(
             parsing_table.get(Variable("E"),
                               dict()).get(Terminal("+"), [])), 0)
     self.assertEqual(
         len(
             parsing_table.get(Variable("T’"),
                               dict()).get(Terminal(")"), [])), 1)
     self.assertEqual(
         len(
             parsing_table.get(Variable("F"),
                               dict()).get(Terminal("("), [])), 1)
     self.assertEqual(
         len(
             parsing_table.get(Variable("F"),
                               dict()).get(Terminal("id"), [])), 1)
예제 #11
0
 def test_intersection(self):
     """ Tests the intersection with a regex """
     regex = Regex("a*b*")
     dfa = regex.to_epsilon_nfa()
     symb_a = Symbol("a")
     symb_b = Symbol("b")
     self.assertTrue(dfa.accepts([symb_a, symb_a, symb_b, symb_b]))
     self.assertFalse(dfa.accepts([symb_b, symb_b, symb_a]))
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     var_s = Variable("S")
     productions = {
         Production(var_s, [ter_a, var_s, ter_b]),
         Production(var_s, [ter_b, var_s, ter_a]),
         Production(var_s, [])
     }
     cfg = CFG(productions=productions, start_symbol=var_s)
     self.assertTrue(cfg.contains([ter_a, ter_a, ter_b, ter_b]))
     self.assertFalse(cfg.contains([ter_a, ter_a, ter_b]))
     cfg_i = cfg.intersection(regex)
     self.assertTrue(cfg_i.contains([ter_a, ter_a, ter_b, ter_b]))
     self.assertFalse(cfg_i.contains([ter_a, ter_a, ter_b]))
     self.assertTrue(cfg_i.contains([]))
     cfg_i = cfg.intersection(dfa)
     self.assertTrue(cfg_i.contains([ter_a, ter_a, ter_b, ter_b]))
     self.assertFalse(cfg_i.contains([ter_a, ter_a, ter_b]))
     self.assertTrue(cfg_i.contains([]))
예제 #12
0
 def test_pda_conversion(self):
     """ Tests conversions from a PDA """
     state_p = State("p")
     state_q = State("q")
     state_a = Symbol("a")
     state_b = Symbol("b")
     state_c = Symbol("c")
     terminal_a = Terminal("a")
     terminal_b = Terminal("b")
     terminal_c = Terminal("c")
     stack_symbol_a = StackSymbol("a")
     stack_symbol_b = StackSymbol("b")
     stack_symbol_c = StackSymbol("c")
     stack_symbol_x0 = StackSymbol("X0")
     pda = PDA(states={state_p, state_q},
               input_symbols={state_a, state_b, state_c},
               stack_alphabet={
                   stack_symbol_a, stack_symbol_b, stack_symbol_c,
                   stack_symbol_x0
               },
               start_state=state_p,
               start_stack_symbol=stack_symbol_x0,
               final_states={state_q})
     pda.add_transition(state_p, Epsilon(), stack_symbol_x0, state_q, [])
     pda.add_transition(
         state_p, Epsilon(), stack_symbol_x0, state_p,
         [stack_symbol_a, stack_symbol_b, stack_symbol_c, stack_symbol_x0])
     pda.add_transition(state_p, state_a, stack_symbol_a, state_p, [])
     pda.add_transition(state_p, state_b, stack_symbol_b, state_p, [])
     pda.add_transition(state_p, state_c, stack_symbol_c, state_p, [])
     cfg = pda.to_empty_stack().to_cfg()
     self.assertTrue(cfg.contains([]))
     self.assertTrue(cfg.contains([terminal_a, terminal_b, terminal_c]))
     self.assertFalse(cfg.contains([terminal_c, terminal_b, terminal_a]))
예제 #13
0
 def test_derivation_does_not_exist(self):
     var_s = Variable("S")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     cfg = CFG(productions=[], start_symbol=var_s)
     with self.assertRaises(DerivationDoesNotExist):
         parse_tree = cfg.get_cnf_parse_tree([ter_a, ter_b])
         parse_tree.get_rightmost_derivation()
    def cyk(self, words, tokens=dict()):
        word_size = sum([
            1 if word in tokens.keys() else len(word)
            for word in words.split()
        ])

        if word_size == 0:
            return self.eps

        cfg = self.cnf
        productions = cfg.productions

        cyk_table = [[set() for _ in range(word_size)]
                     for _ in range(word_size)]

        shift = 0
        for word in words.split():
            if word in tokens.keys():
                for production in productions:
                    if len(production.body) == 1 \
                    and production.body[0] == Terminal(tokens[word]):
                        cyk_table[shift][shift].add(production.head)
                shift += 1
            else:
                for index, letter in enumerate(word):
                    for production in productions:
                        if len(production.body) == 1 \
                        and production.body[0] == Terminal(letter):
                            cyk_table[shift + index][shift + index].add(
                                production.head)
                shift += len(word)

        productions_len_2 = [
            prod for prod in productions if len(prod.body) == 2
        ]

        for level in range(1, word_size):
            for production_index in range(word_size - level):
                row = production_index
                column = level + production_index

                for col_new in range(row, column):
                    row_new = col_new + 1

                    body_left = cyk_table[row][col_new]
                    body_right = cyk_table[row_new][column]

                    for production in productions_len_2:
                        if production.body[0] in body_left \
                           and production.body[1] in body_right:
                            cyk_table[row][column].add(production.head)

        start_symbol_table = cyk_table[0][word_size - 1]

        if len(start_symbol_table) != 0:
            return cfg.start_symbol in start_symbol_table

        return False
예제 #15
0
 def cfg_obj_to_pretty(cfg_obj: Union[Variable, Terminal]):
     if isinstance(cfg_obj, Variable):
         return Variable(cfg_obj.value[2:])
     elif isinstance(cfg_obj, Terminal):
         if cfg_obj.value == 't_newline':
             return Terminal('\n')
         if cfg_obj.value == 't_escape':
             return Terminal('\\')
         return Terminal(cls._from_pretty_term(cfg_obj.value))
예제 #16
0
파일: solver.py 프로젝트: Aunsiels/dangie
 def process_l(self, word, query, non_terminal):
     parse_tree = ParseTree(Variable(non_terminal))
     parse_tree.sons.append(ParseTree(Terminal(non_terminal[1:])))
     parse_tree.sons.append(
         self.construct_parse_tree(
             word[1:-1], query,
             "B" + utils.get_inverse_relation(non_terminal[1:])))
     parse_tree.sons.append(
         ParseTree(Terminal(utils.get_inverse_relation(non_terminal[1:]))))
     return parse_tree
예제 #17
0
def get_lex(word):
    lexems = []

    for lex in word.split():
        if lex in KEYWORDS:
            lexems.append(Terminal(lex))
        else:
            # Encountered string or int
            lexems.extend([Terminal(sym) for sym in lex])
    return lexems
예제 #18
0
 def test_emptiness(self):
     """ Tests the emptiness of a CFG """
     # pylint: disable=too-many-locals
     var_s = Variable("S")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     prod0 = Production(var_s, [ter_a, var_s, ter_b])
     prod1 = Production(var_s, [])
     cfg = CFG({var_s}, {ter_a, ter_b}, var_s, {prod0, prod1})
     self.assertFalse(cfg.is_empty())
예제 #19
0
 def test_get_follow_set(self):
     # Example from:
     # https://www.geeksforgeeks.org/follow-set-in-syntax-analysis/
     text = """
         E  -> T E’
         E’ -> + T E’ | Є
         T  -> F T’
         T’ -> * F T’ | Є
         F  -> ( E ) | id
     """
     cfg = CFG.from_text(text, start_symbol="E")
     llone_parser = LLOneParser(cfg)
     follow_set = llone_parser.get_follow_set()
     self.assertEqual(follow_set[Variable("E")], {"$", Terminal(")")})
     self.assertEqual(follow_set[Variable("E’")], {"$", Terminal(")")})
     self.assertEqual(
         follow_set[Variable("T")],
         {"$", Terminal("+"), Terminal(")")})
     self.assertEqual(
         follow_set[Variable("T’")],
         {"$", Terminal("+"), Terminal(")")})
     self.assertEqual(
         follow_set[Variable("F")],
         {"$", Terminal("+"),
          Terminal("*"), Terminal(")")})
예제 #20
0
    def test_intersection_regex(self):
        """ Tests the intersection with a regex """
        # pylint: disable=too-many-locals
        state_p = State("p")
        state_q = State("q")
        state_r = State("r")
        state_i = Symbol("i")
        state_e = Symbol("e")
        state_z = StackSymbol("Z")
        state_x0 = StackSymbol("X0")
        pda = PDA(states={state_p, state_q, state_r},
                  input_symbols={state_i, state_e},
                  stack_alphabet={state_z, state_x0},
                  start_state=state_p,
                  start_stack_symbol=state_x0,
                  final_states={state_r})
        pda.add_transition(state_p, Epsilon(), state_x0, state_q,
                           [state_z, state_x0])
        pda.add_transition(state_q, state_i, state_z, state_q,
                           [state_z, state_z])
        pda.add_transition(state_q, state_e, state_z, state_q, [])
        pda.add_transition(state_q, Epsilon(), state_x0, state_r, [])

        state_s = finite_automaton.State("s")
        state_t = finite_automaton.State("t")
        i_dfa = finite_automaton.Symbol("i")
        e_dfa = finite_automaton.Symbol("e")
        dfa = finite_automaton.DeterministicFiniteAutomaton(
            states={state_s, state_t},
            input_symbols={i_dfa, e_dfa},
            start_state=state_s,
            final_states={state_s, state_t})
        dfa.add_transition(state_s, i_dfa, state_s)
        dfa.add_transition(state_s, e_dfa, state_t)
        dfa.add_transition(state_t, e_dfa, state_t)

        new_pda = pda.intersection(dfa)
        pda_es = new_pda.to_empty_stack()
        cfg = pda_es.to_cfg()
        self.assertEqual(new_pda.get_number_transitions(), 6)
        self.assertEqual(len(new_pda.states), 5)
        self.assertEqual(len(new_pda.final_states), 2)
        self.assertEqual(len(new_pda.input_symbols), 2)
        self.assertEqual(len(new_pda.stack_symbols), 2)

        i_cfg = Terminal("i")
        e_cfg = Terminal("e")

        self.assertTrue(cfg.contains([i_cfg, i_cfg, e_cfg, e_cfg, e_cfg]))

        new_pda = pda.intersection(
            finite_automaton.DeterministicFiniteAutomaton())
        self.assertEqual(new_pda.get_number_transitions(), 0)
예제 #21
0
 def test_intersection_empty(self):
     regex = Regex("")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     var_s = Variable("S")
     productions = {
         Production(var_s, [ter_a, var_s, ter_b]),
         Production(var_s, [ter_b, var_s, ter_a]),
         Production(var_s, [])
     }
     cfg = CFG(productions=productions, start_symbol=var_s)
     cfg_i = cfg & regex
     self.assertFalse(cfg_i)
예제 #22
0
 def test_reverse(self):
     """ Test the reversal of a CFG """
     var_s = Variable("S")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     prod0 = Production(var_s, [ter_a, var_s, ter_b])
     prod1 = Production(var_s, [])
     cfg = CFG({var_s}, {ter_a, ter_b}, var_s, {prod0, prod1})
     new_cfg = cfg.reverse()
     self.assertEqual(len(new_cfg.variables), 1)
     self.assertEqual(len(new_cfg.terminals), 2)
     self.assertEqual(len(new_cfg.productions), 2)
     self.assertFalse(new_cfg.is_empty())
     self.assertTrue(new_cfg.contains([ter_b, ter_b, ter_a, ter_a]))
예제 #23
0
 def test_union(self):
     """ Tests the union of two cfg """
     var_s = Variable("S")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     prod0 = Production(var_s, [ter_a, var_s, ter_b])
     prod1 = Production(var_s, [])
     cfg = CFG({var_s}, {ter_a, ter_b}, var_s, {prod0, prod1})
     new_cfg = cfg.union(cfg)
     self.assertEqual(len(new_cfg.variables), 3)
     self.assertEqual(len(new_cfg.terminals), 2)
     self.assertEqual(len(new_cfg.productions), 6)
     self.assertFalse(new_cfg.is_empty())
     self.assertTrue(new_cfg.contains([ter_a, ter_a, ter_b, ter_b]))
예제 #24
0
 def _test_profiling_conversions():
     """ Tests multiple conversions """
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     ter_c = Terminal("c")
     var_s = Variable("S")
     productions = {
         Production(var_s, [ter_a, var_s, ter_b]),
         Production(var_s, [ter_c])
     }
     cfg = CFG(productions=productions, start_symbol=var_s)
     cfg = cfg.to_pda().to_final_state().to_empty_stack().to_cfg()
     cfg = cfg.to_pda().to_final_state().to_empty_stack().to_cfg()
     cfg.to_pda().to_final_state().to_empty_stack().to_cfg()
예제 #25
0
 def test_to_pda(self):
     """ Tests the conversion to PDA """
     var_e = Variable("E")
     var_i = Variable("I")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     ter_0 = Terminal("0")
     ter_1 = Terminal("1")
     ter_par_open = Terminal("(")
     ter_par_close = Terminal(")")
     ter_mult = Terminal("*")
     ter_plus = Terminal("+")
     productions = {
         Production(var_e, [var_i]),
         Production(var_e, [var_e, ter_plus, var_e]),
         Production(var_e, [var_e, ter_mult, var_e]),
         Production(var_e, [ter_par_open, var_e, ter_par_close]),
         Production(var_i, [ter_a]),
         Production(var_i, [ter_b]),
         Production(var_i, [var_i, ter_a]),
         Production(var_i, [var_i, ter_b]),
         Production(var_i, [var_i, ter_0]),
         Production(var_i, [var_i, ter_1]),
         Production(var_i, [var_i, Epsilon()])
     }
     cfg = CFG({var_e, var_i}, {
         ter_a, ter_b, ter_0, ter_1, ter_par_open, ter_par_close, ter_mult,
         ter_plus
     }, var_e, productions)
     pda = cfg.to_pda()
     self.assertEqual(len(pda.states), 1)
     self.assertEqual(len(pda.final_states), 0)
     self.assertEqual(len(pda.input_symbols), 8)
     self.assertEqual(len(pda.stack_symbols), 10)
     self.assertEqual(pda.get_number_transitions(), 19)
예제 #26
0
 def test_substitution(self):
     """ Tests substitutions in a CFG """
     var_s = Variable("S")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     prod0 = Production(var_s, [ter_a, var_s, ter_b])
     prod1 = Production(var_s, [])
     cfg = CFG({var_s}, {ter_a, ter_b}, var_s, {prod0, prod1})
     new_cfg = cfg.substitute({ter_a: cfg})
     self.assertEqual(len(new_cfg.variables), 2)
     self.assertEqual(len(new_cfg.terminals), 2)
     self.assertEqual(len(new_cfg.productions), 4)
     self.assertFalse(new_cfg.is_empty())
     self.assertTrue(
         new_cfg.contains([ter_a, ter_b, ter_a, ter_b, ter_b, ter_b]))
예제 #27
0
 def test_nullable_object(self):
     """ Tests the finding of nullable objects """
     var_a = Variable("A")
     var_b = Variable("B")
     ter_a = Terminal("a")
     ter_b = Terminal("b")
     start = Variable("S")
     prod0 = Production(start, [var_a, var_b])
     prod1 = Production(var_a, [ter_a, var_a, var_a])
     prod2 = Production(var_a, [Epsilon()])
     prod3 = Production(var_b, [ter_b, var_b, var_b])
     prod4 = Production(var_b, [Epsilon()])
     cfg = CFG({var_a, var_b, start}, {ter_a, ter_b}, start,
               {prod0, prod1, prod2, prod3, prod4})
     self.assertEqual(cfg.get_nullable_symbols(), {var_a, var_b, start})
예제 #28
0
    def from_grammar_file(path, python_regex=False, nonterms_upper=True):
        with open(path, 'r') as g:
            productions = set()

            first_line = g.readline()
            rule = first_line.strip().split(' ', 1)
            start_symbol = Variable(rule[0])
            if any(symb in rule[1] for symb in '?+*|') and len(rule[1]) > 1:
                body = rule[1].replace('?', f'| eps')
                productions |= GrammarAlgos.prod_from_regex(
                    start_symbol, body, python_regex, nonterms_upper)
            else:
                body = []
                for s in rule[1].split(' '):
                    if s == 'eps':
                        e = Epsilon()
                        body.append(e)
                    elif s.isupper():
                        v = Variable(s)
                        body.append(v)
                    else:
                        t = Terminal(s)
                        body.append(t)
                productions.add(Production(start_symbol, body))

            for line in g.readlines():
                rule = line.strip().split(' ', 1)
                var = Variable(rule[0])
                if any(symb in rule[1]
                       for symb in '?+*|') and len(rule[1]) > 1:
                    body = rule[1].replace('?', f'| eps')
                    productions |= GrammarAlgos.prod_from_regex(
                        var, body, python_regex, nonterms_upper)
                else:
                    body = []
                    for s in rule[1].split(' '):
                        if s == 'eps':
                            e = Epsilon()
                            body.append(e)
                        elif s.isupper():
                            v = Variable(s)
                            body.append(v)
                        else:
                            t = Terminal(s)
                            body.append(t)
                    productions.add(Production(var, body))

            return CFG(start_symbol=start_symbol, productions=productions)
예제 #29
0
    def test_example62(self):
        """ Example from the book """
        state0 = State("q0")
        state1 = State("q1")
        state2 = State("q2")
        s_zero = Symbol("0")
        s_one = Symbol("1")
        ss_zero = StackSymbol("0")
        ss_one = StackSymbol("1")
        ss_z0 = StackSymbol("Z0")
        pda = PDA(states={state0, state1, state2},
                  input_symbols={s_zero, s_one},
                  stack_alphabet={ss_zero, ss_one, ss_z0},
                  start_state=state0,
                  start_stack_symbol=ss_z0,
                  final_states={state2})
        self.assertEqual(len(pda.states), 3)
        self.assertEqual(len(pda.input_symbols), 2)
        self.assertEqual(len(pda.stack_symbols), 3)
        self.assertEqual(pda.get_number_transitions(), 0)

        pda.add_transition(state0, s_zero, ss_z0, state0, [ss_zero, ss_z0])
        pda.add_transition(state0, s_one, ss_z0, state0, [ss_one, ss_z0])

        pda.add_transition(state0, s_zero, ss_zero, state0, [ss_zero, ss_zero])
        pda.add_transition(state0, s_one, ss_one, state0, [ss_zero, ss_one])
        pda.add_transition(state0, s_one, ss_zero, state0, [ss_one, ss_zero])
        pda.add_transition(state0, s_one, ss_one, state0, [ss_one, ss_one])

        pda.add_transition(state0, Epsilon(), ss_z0, state1, [ss_z0])
        pda.add_transition(state0, Epsilon(), ss_zero, state1, [ss_zero])
        pda.add_transition(state0, Epsilon(), ss_one, state1, [ss_one])

        pda.add_transition(state1, s_zero, ss_zero, state1, [])
        pda.add_transition(state1, s_one, ss_one, state1, [])

        pda.add_transition(state1, Epsilon(), ss_z0, state2, [ss_z0])

        self.assertEqual(pda.get_number_transitions(), 12)

        t_zero = Terminal("0")
        t_one = Terminal("1")
        cfg = pda.to_empty_stack().to_cfg()
        self.assertTrue(cfg.contains([]))
        self.assertTrue(cfg.contains([t_zero, t_zero]))
        self.assertTrue(cfg.contains([t_zero, t_one, t_one, t_zero]))
        self.assertFalse(cfg.contains([t_zero]))
        self.assertFalse(cfg.contains([t_zero, t_one, t_zero]))
예제 #30
0
    def __init__(self, rules: Iterable[str], patch: bool = False):
        start_var: Variable
        vars: set[Variable] = set()
        terminals: Set[Terminal] = set()
        productions: Set[Production] = set()

        for rule in rules:
            i, r = rule.split(": ")
            var = Variable(i)
            if i == "0":
                start_var = var
            if r[0] == '"':
                ter = Terminal(r[1])
                terminals.add(ter)
                productions.add(Production(var, [ter]))
                continue
            if patch:
                if i == "8":
                    r = "42 | 42 8"
                if i == "11":
                    r = "42 31 | 42 11 31"
            rr = r.split(" | ")
            for r in rr:
                productions.add(
                    Production(var, [Variable(x) for x in r.split(" ")]))

        self.CFG = CFG(vars, terminals, start_var, productions)