def test_book_example(self): """ S -> i E t S | i E t S e S | a E -> b """ solved = f.parse_bnf(test_data.solved_left_factoring) unsolved = f.parse_bnf(test_data.unsolved_left_factoring) g = f.remove_left_factoring(unsolved) self.assertEqual(solved, g)
def test_simple(self): a = Grammar(start='E') a.add_rule(Rule('E', ('E', '+', 'T'))) a.add_rule(Rule('E', ('T', ))) a.add_rule(Rule('T', ('T', '*', 'F'))) a.add_rule(Rule('T', ('F', ))) a.add_rule(Rule('F', ('(', 'E', ')'))) a.add_rule(Rule('F', ('id', ))) text = str(a) g = f.parse_bnf(text) self.assertEqual(a, g)
def test_book_example(self): g = f.parse_bnf(test_data.book_example) answers = { 'E': {'$', ')'}, 'E\'': {'$', ')'}, 'T': {'$', ')', '+'}, 'T\'': {'$', ')', '+'}, 'F': {'$', ')', '*', '+'} } for x, first in answers.items(): self.assertEqual(first, set(g.follow(x)))
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()
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_book_example(self): g = f.parse_bnf(test_data.unsolved_left_recursion) # Trust me, this is the answer answer = { ("T'", '+'): Rule("T'", ('ε', )), ('F', 'id'): Rule('F', ('id', )), ("E'", '+'): Rule("E'", ('+', 'T', "E'")), ('E', '('): Rule('E', ('T', "E'")), ('T', '('): Rule('T', ('F', "T'")), ("E'", '$'): Rule("E'", ('ε', )), ("T'", '*'): Rule("T'", ('*', 'F', "T'")), ("T'", ')'): Rule("T'", ('ε', )), ("T'", '$'): Rule("T'", ('ε', )), ("E'", ')'): Rule("E'", ('ε', )), ('T', 'id'): Rule('T', ('F', "T'")), ('E', 'id'): Rule('E', ('T', "E'")), ('F', '('): Rule('F', ('(', 'E', ')')) } table, amb = g.parsing_table(is_clean=False) self.assertFalse(amb) self.assertEqual(table, answer)
def test_check_left_factor(self): solved = f.parse_bnf(test_data.solved_left_factoring) unsolved = f.parse_bnf(test_data.unsolved_left_factoring) self.assertTrue(f.check_left_factors(unsolved)) self.assertFalse(f.check_left_factors(solved))
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)
def test_cases(self): for case in test_data.examples: g = f.parse_bnf(case) text = str(g) self.assertEqual(g, f.parse_bnf(text))
def test_invalid_production(self): text = "E -> E + T | E" # Production is the same as nonterminal with self.assertRaises(InvalidProduction): f.parse_bnf(text)
def test_invalid_grammar(self): text = "INVALID" with self.assertRaises(InvalidGrammar): f.parse_bnf(text)
def setUp(self): self.g = f.parse_bnf(test_data.exam_exercise)