def test_cases(self):
     for case in test_data.examples:
         g = f.parse_bnf(case)
         g = f.remove_left_recursion(g)
         for p in g.iter_productions():
             self.assertFalse(p.is_left_recursive(),
                              msg='{} is left-recursive'.format(p))
 def test_cases(self):
     try:
         for case in test_data.examples:
             g = f.parse_bnf(case)
             h = f.remove_left_recursion(g)
             i = f.remove_left_factoring(h)
             for x in i.nonterminals:
                 i.first(x)
     except Exception as e:
         self.fail(str(e))
Exemple #3
0
def do_the_whole_thing(grammar_text,
                       epsilon='ε',
                       eof='$',
                       output=None,
                       verbose=True):
    file = None
    if output:
        file = open(output, 'w')
        sys.stdout = file

    vprint = print if verbose else lambda *a, **key: None  # Only print if verbose is True

    vprint("Original:")
    g = parse_bnf(grammar_text, epsilon=epsilon, eof=eof)
    vprint(g)

    vprint("\nAfter removing left-recursion:")
    g = remove_left_recursion(g)
    vprint(g)

    vprint("\nAfter removing left-factoring:")
    g = remove_left_factoring(g)
    vprint(g)

    vprint()
    for nt in g.nonterminals:
        vprint('FIRST({}) = {}'.format(nt, g.first(nt)))

    vprint()
    follow = [(nt, g.follow(nt)) for nt in g.nonterminals]

    for nt, f in follow:
        vprint('FOLLOW({}) = {}'.format(nt, f))

    vprint()
    table, ambiguous = g.parsing_table()
    vprint("Parsing Table: ")
    if ambiguous:
        vprint(
            "El lenguaje de entrada no es LL(1) debido a que se encontraron ambigüedades."
        )

    vprint()
    pprint_table(g, table)

    if file:
        file.close()
Exemple #4
0
    def parsing_table(self, is_clean=True):
        """
        Compute LL(1) predictive parsing table
        :param is_clean: If False, will remove left factoring and left recursions.
        :return: parsing table
        """
        from parser.functions import remove_left_recursion, remove_left_factoring  # To avoid cyclic import

        equiv = self if is_clean else remove_left_recursion(remove_left_factoring(copy(self)))

        table = {}
        ambigous = False
        for r in equiv.iter_productions():
            terminals = equiv.first(r.body)
            for t in terminals:
                if not equiv.is_terminal(t):
                    continue
                if t == equiv.epsilon:
                    f = equiv.follow(r.head)
                    for ef in f:
                        if (table.get((r.head, ef))):
                            ls = []
                            ls.append(table[(r.head, ef)])
                            ls.append(r)
                            table[(r.head, ef)] = ls
                            ambigous = True
                        else:
                            table[(r.head, ef)] = r
                else:
                    if (table.get((r.head, t))):
                        ls = []
                        ls.append(table[(r.head, t)])
                        ls.append(r)
                        table[(r.head, t)] = ls
                        ambigous = True
                    else:
                        table[(r.head, t)] = r
        return (table, ambigous)
Exemple #5
0
def just_do_it(req):
    errors = []
    g = None
    grammar_not_recursive = None
    grammar_not_factor = None
    parsing_table = None

    try:
        g = parse_bnf(req.form['bnf'],
                      epsilon=req.form['epsilon'],
                      eof=req.form['eof'])
        grammar_not_recursive = remove_left_recursion(g)
        grammar_not_factor = remove_left_factoring(grammar_not_recursive)
        table, ambiguous = grammar_not_factor.parsing_table()

        if ambiguous:
            errors.append(
                'El lenguaje de entrada no es LL(1) debido a que se encontraron ambigüedades.'
            )

        parsing_table = {
            'table': table,
            'terminals': sorted(set(g.terminals) - {g.epsilon}) + [g.eof],
            'nonterminals': [nt for nt in grammar_not_factor.nonterminals]
        }

    except InvalidGrammar:
        errors.append(
            'Gramática inválida. Revise las especificaciones de BNF.')
    except InvalidProduction as e:
        errors.append('Produccion invalida: {}.'.format(e.production))

    return render_template('results.html',
                           grammar=g,
                           no_recursion=grammar_not_recursive,
                           no_factor=grammar_not_factor,
                           parsing_table=parsing_table,
                           errors=errors)
 def test_simple_book_example(self):
     solved = f.parse_bnf(test_data.solved_left_recursion)
     unsolved = f.parse_bnf(test_data.unsolved_left_recursion)
     g = f.remove_left_recursion(unsolved)
     self.assertEqual(solved, g)