def _build_parsing_table(self): G = self.G.AugmentedGrammar(True) firsts = compute_firsts(G) follows = compute_follows(G, firsts) automaton = build_LR0_automaton(G).to_deterministic() for i, node in enumerate(automaton): if self.verbose: print(i, '\t', '\n\t '.join(str(x) for x in node.state), '\n') node.idx = i for node in automaton: idx = node.idx for state in node.state: item = state.state # Your code here!!! # - Fill `self.Action` and `self.Goto` according to `item`) # - Feel free to use `self._register(...)`) if item.IsReduceItem and item.production.Left == G.startSymbol: self._register(self.action, (idx, G.EOF), (self.OK, 0)) elif item.IsReduceItem: for symbol in follows[item.production.Left]: self._register(self.action, (idx, symbol), (self.REDUCE, item.production)) elif item.NextSymbol.IsTerminal: next_idx = node.transitions[item.NextSymbol.Name][0].idx self._register(self.action, (idx, item.NextSymbol), (self.SHIFT, next_idx)) elif item.NextSymbol.IsNonTerminal: next_idx = node.transitions[item.NextSymbol.Name][0].idx self._register(self.goto, (idx, item.NextSymbol), next_idx)
def deprecated_metodo_predictivo_no_recursivo(G, M=None, firsts=None, follows=None): if M is None: if firsts is None: firsts = compute_firsts(G) if follows is None: follows = compute_follows(G, firsts) M = build_parsing_table(G, firsts, follows) def parser(w): stack = [G.startSymbol] cursor = 0 output = [] while len(stack) != 0: top = stack.pop() a = w[cursor] if top.IsTerminal: if a == top: cursor += 1 else: raise Exception("Parsing error") elif top.IsNonTerminal: production = M[top, a] for i in reversed(production[0].Right): stack.append(i) output.append(production[0]) return output return parser
def _regex(expression: str) -> DFA: tokens = regex_tokenizer(expression, G) first = compute_firsts(G) follow = compute_follows(G, first) parsing_table = build_parsing_table(G, first, follow) parser = metodo_predictivo_no_recursivo(G, parsing_table) left_parse = parser(tokens) ast = evaluate_parse(left_parse, tokens) nfa = ast.evaluate() dfa = nfa_to_dfa(nfa) mini = automata_minimization(dfa) return mini
def build_LR1_automaton(G): assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented' firsts = compute_firsts(G) firsts[G.EOF] = ContainerSet(G.EOF) start_production = G.startSymbol.productions[0] start_item = Item(start_production, 0, lookaheads=(G.EOF, )) start = frozenset([start_item]) closure = closure_lr1(start, firsts) automaton = State(frozenset(closure), True) pending = [start] visited = {start: automaton} while pending: current = pending.pop() current_state = visited[current] for symbol in G.terminals + G.nonTerminals: # Your code here!!! (Get/Build `next_state`) closure = closure_lr1(current, firsts) goto = goto_lr1(closure, symbol, firsts, True) if not goto: continue try: next_state = visited[goto] except KeyError: closure = closure_lr1(goto, firsts) next_state = visited[goto] = State(frozenset(closure), True) pending.append(goto) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
import first_follow as ff from cmp.pycompiler import Grammar G = Grammar() E = G.NonTerminal('E', True) T, F, X, Y = G.NonTerminals('T F X Y') plus, minus, star, div, opar, cpar, num = G.Terminals('+ - * / ( ) num') E %= T + X X %= plus + T + X | minus + T + X | G.Epsilon T %= F + Y Y %= star + F + Y | div + F + Y | G.Epsilon F %= num | opar + E + cpar import cmp.languages xcool = cmp.languages.BasicXCool(G) firsts = ff.compute_firsts(G) assert firsts == xcool.firsts
from first_follow import compute_firsts, compute_follows from ll1_parser import metodo_predictivo_no_recursivo, build_parsing_table G = Grammar() E = G.NonTerminal('E', True) T, F, X, Y = G.NonTerminals('T F X Y') plus, minus, star, div, opar, cpar, num = G.Terminals('+ - * / ( ) num') E %= T + X X %= plus + T + X | minus + T + X | G.Epsilon T %= F + Y Y %= star + F + Y | div + F + Y | G.Epsilon F %= num | opar + E + cpar print(G) firsts = compute_firsts(G) follows = compute_follows(G, firsts) M = build_parsing_table(G, firsts, follows) parser = metodo_predictivo_no_recursivo(G, M) left_parse = parser([ num, star, num, star, num, plus, num, star, num, plus, num, plus, num, G.EOF ]) assert left_parse == [ Production(E, Sentence(T, X)), Production(T, Sentence(F, Y)), Production(F, Sentence(num)), Production(Y, Sentence(star, F, Y)), Production(F, Sentence(num)), Production(Y, Sentence(star, F, Y)),