def delete_nonderivable_nonterminals(grammar): new_grammar = Grammar() new_grammar.axiom = grammar.axiom new_grammar.terminals = grammar.terminals unwatched = list([new_grammar.axiom]) watched = set() while unwatched: nonterminal = unwatched[0] unwatched = unwatched.remove(nonterminal) or [] watched.add(nonterminal) rules = find_rules_for_nonterminal(grammar.rules, nonterminal) for rule in rules: for symbol in rule.right_side: if isinstance(symbol, Nonterminal): if symbol not in watched and symbol not in unwatched: unwatched.append(symbol) new_grammar.nonterminals = watched new_rules = [] for rule in grammar.rules: if rule.left_side[0] in watched: new_rules.append(rule) new_grammar.rules = new_rules return new_grammar
def convert_grammar(grammar, disappearing_nonterminals): print "algorithm 1" new_grammar = Grammar() # build new nonterminals set new_grammar.nonterminals = build_new_nonterminals_set( grammar, disappearing_nonterminals) # find new axiom if grammar.axiom in disappearing_nonterminals: # language has empty chain new_grammar.axiom = Nonterminal(grammar.axiom.name, False) new_grammar.nonterminals.add(new_grammar.axiom) new_grammar.nonterminals.remove(grammar.axiom) else: new_grammar.axiom = grammar.axiom # build new rules new_grammar.rules = build_new_rules( grammar, disappearing_nonterminals, new_grammar.nonterminals) # copy terminals new_grammar.terminals = set(grammar.terminals) return new_grammar
def delete_useless_nonterminals(grammar): new_rules = list(grammar.rules) new_nonterminals = set(grammar.nonterminals) while True: useless_nonterminals = find_useless_nonterminals(new_rules) if not useless_nonterminals: break new_rules = delete_useless_nonterminals_from_rules(new_rules, useless_nonterminals) new_rules = delete_useless_nonterminals_rules(new_rules, useless_nonterminals) new_nonterminals.difference_update(useless_nonterminals) new_grammar = Grammar() new_grammar.axiom = grammar.axiom new_grammar.terminals = set(grammar.terminals) new_grammar.nonterminals = new_nonterminals new_grammar.rules = new_rules return new_grammar
def convert_to_greibach(grammar): print "algorithm 3" converted_grammar = delete_empty_rules(grammar) print "converted grammar:" print converted_grammar new_grammar = Grammar() new_grammar.axiom = converted_grammar.axiom new_grammar.terminals = set(converted_grammar.terminals) sorted_nonterminals = sort_nonterminals( converted_grammar.nonterminals, converted_grammar.rules) print "sorted nonterminals:", [str(s) for s in sorted_nonterminals] new_grammar.nonterminals = set(sorted_nonterminals) # rebuild rules nonterminal = sorted_nonterminals[-1] new_rules = find_rules_for_nonterminal(converted_grammar.rules, nonterminal) for idx in range(len(sorted_nonterminals) - 2, -1, -1): nonterminal = sorted_nonterminals[idx] rules = find_rules_for_nonterminal(converted_grammar.rules, nonterminal) for rule in rules: if isinstance(rule.right_side[0], Nonterminal): new_rules.extend(replace_rule(new_rules, rule)) else: new_rules.append(rule) # add rules for terminals for terminal in converted_grammar.terminals: new_nonterminal = Nonterminal("X{%s}" % str(terminal)) new_grammar.nonterminals.add(new_nonterminal) new_rules.append(Rule([new_nonterminal], [terminal])) # replace nonleft terminal to new nonterminals for rule in new_rules: rule =replace_nonleft_terminal_to_nonterminal(rule, terminal, new_nonterminal) new_grammar.rules = new_rules print "grammar:", new_grammar return delete_nonderivable_nonterminals(new_grammar)
def build_new_grammar(grammar): new_grammar = Grammar() new_grammar.terminals = set(grammar.terminals) new_grammar.axiom = ComplexNonterminal( [grammar.axiom], grammar.axiom.is_nullable) new_rules = [] unwatched, watched = [new_grammar.axiom], set() while unwatched: complex_nonterminal = unwatched[0] unwatched.remove(complex_nonterminal) watched.add(complex_nonterminal) if complex_nonterminal.starts_with_nonterminal(): new_rules.extend(build_rules_starts_with_nonterminal( grammar.rules, complex_nonterminal, watched, unwatched)) elif complex_nonterminal.starts_with_terminal(): new_rules.extend(build_rules_starts_with_terminal( grammar.rules, complex_nonterminal, watched, unwatched)) new_grammar.rules = new_rules new_grammar.nonterminals = watched return new_grammar
from grammar import (Symbol , EmptySymbol,Terminal, Nonterminal, Rule, Grammar) from conversion import (has_empty_chain, convert_grammar, find_disappearing_nonterminals, delete_empty_rules, delete_useless_nonterminals, convert_to_greibach) grammar = Grammar() S = Nonterminal('S') A = Nonterminal('A') B = Nonterminal('B') grammar.nonterminals.update([A, B, S]) grammar.axiom = S a = Terminal('a') b = Terminal('b') grammar.terminals.update([a, b]) e = EmptySymbol() grammar.rules.append(Rule([S], [A, B])) grammar.rules.append(Rule([A], [a, A])) grammar.rules.append(Rule([A], [e])) grammar.rules.append(Rule([B], [b, A])) grammar.rules.append(Rule([B], [e])) print "grammar:\n", grammar #disappearing_nonterminals = find_disappearing_nonterminals(grammar) #new_grammar = convert_grammar(grammar, disappearing_nonterminals)