def test_elim_null_prod(self): for x, y in zip(cases.elim_null_test_cases, cases.elim_null_test_cases_targets): x = gm.parse(x) y = gm.parse(y) ng = elim_null(x) self.assertEqual(ng, y)
def test_elim_unit_prod(self): for x, y in zip(cases.elim_unit_test_cases, cases.elim_unit_test_cases_targets): x = gm.parse(x) y = gm.parse(y) ng = elim_unit(x) ng = remove_same_rules(ng, False, False) self.assertEqual(ng, y)
def test_elim_left_recursion(self): for x, y in zip(cases.elim_lr_test_cases, cases.elim_lr_test_cases_targets): x, f = x x = gm.parse(x) if f: x = gm.reverse_grammar(x) y = gm.parse(y) ng = elim_lr(x) self.assertEqual(ng, y)
def test_follow_set(self): for x, y in zip(cases.first_follow_set_test_cases, cases.follow_set_test_cases_targets): x = gm.parse(x) fs = first_sets(x) start = list(x.keys())[0] fls = follow_sets(start, x, fs) self.assertEqual(fls, y)
def test_first_set(self): for x, y in zip(cases.first_follow_set_test_cases, cases.first_set_test_cases_targets): x = gm.parse(x) fs = first_sets(x) self.assertEqual(fs, y)
def test_is_nullable(self): for x, y in zip(cases.is_nullable_test_cases, cases.is_nullable_test_cases_targets): x = gm.parse(x) self.assertEqual(is_nullable("S", x), y)
def test_parse_grammar(self): for x, y in zip(cases.parser_test_cases, cases.parser_test_cases_targets): self.assertEqual(gm.parse(x), y)
def main(): args = docopt(__doc__) # check if file exits if not os.path.exists(args["FILE"]): print(cf.red("{} doesn't exist\n".format(args["FILE"]))) exit(1) # create the output file of = args["-o"] open(of, "w").close() f = open(args["FILE"]) grammar = f.read() f.close() # clear console clear() # print banner print(cf.yellow_bold(BANNER)) print(cf.bold_white("Input Grammar:\n")) pgrammar = gm.parse(grammar) orignal = pgrammar gm.pprint(pgrammar) print() write_to_output(of, "Input Grammar", gm.str_pgrammar(pgrammar)) choices = [ "Remove Null Productions", "Remove Unit Productions", "Remove Left Recursion", "First Sets", "Follow Sets", "Parsing Table", ] misc_choices = [ "Restore Original Grammar", "Print Current Grammar", "Clear", "Exit", ] question = { "type": "list", "name": "ops", "message": "Which operation would you like to perform?", "choices": choices + [Separator()] + misc_choices, } reuse_confirm = { "type": "confirm", "name": "last_grammar", "message": "Use this grammar output for subsequent operations?", "default": True, } reverse_confirm = { "type": "confirm", "name": "reverse_grammar", "message": "Reverse Non-Terminal ordering?", "default": True, } start_input = { "type": "input", "name": "start_sym", "message": "Enter Start Symbol:", } # will contain the last output output = None # if last output was a grammar (as opposed to follow sets) output_grammar = False while True: answer = prompt(question) choice = answer["ops"] if choice == misc_choices[0]: pgrammar = orignal print(cf.white_bold("\nRestored\n")) gm.pprint(pgrammar) print() write_to_output(of, choice, gm.str_pgrammar(pgrammar)) continue elif choice == misc_choices[1]: print() gm.pprint(pgrammar) print() continue elif choice == misc_choices[2]: clear() continue if choice == misc_choices[3]: print(cf.cyan("Bye!")) print("Remember! Logs are saved in", of) print() break # -------- if choice == choices[0]: output = elim_null(pgrammar) elif choice == choices[1]: output = elim_unit(pgrammar) output = remove_same_rules(output, False, False) elif choice == choices[2]: continuel = False for rule in pgrammar.values(): if "eps" in rule: print( cf.red( "\nGrammar contains null productions. This operation can't" " be performed\n")) continuel = True break if continuel: continue answer = prompt(reverse_confirm) reverse = answer["reverse_grammar"] if reverse: print( "\nReversing the order of non-terminals for Left Recursion Removal." ) ng = gm.reverse_grammar(pgrammar) else: ng = pgrammar ng = elim_lr(ng) if reverse: ng = gm.reverse_grammar(ng) output = ng elif choice == choices[3]: fs = first_sets(pgrammar) output = fs elif choice == choices[4]: start_input["validate"] = lambda x: x in pgrammar.keys() answer = prompt(start_input) fs = first_sets(pgrammar) fls = follow_sets(answer["start_sym"], pgrammar, fs) output = fls elif choice == choices[5]: start_input["validate"] = lambda x: x in pgrammar.keys() answer = prompt(start_input) fs = first_sets(pgrammar) fls = follow_sets(answer["start_sym"], pgrammar, fs) output = parsing_table(pgrammar, fs, fls) if choice != choices[5]: # flag to check if the last operation output a pgrammar # only the first 3 operations output a grammar output_grammar = choices.index(choice) in range(3) # print output print(cf.bold_green("\n=>\n")) (gm.pprint if output_grammar else gm.set_print)(output) # log to the output file write_to_output( of, choice, (gm.str_pgrammar if output_grammar else gm.str_set)(output), ) print() # ask to use grammar from last operation if output_grammar: answer = prompt(reuse_confirm) if answer["last_grammar"]: pgrammar = output else: # print parsing table print("\n" + output + "\n") write_to_output( of, choice, output, )