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: prod = item.production if prod.Left == G.startSymbol: self._register(self.action, (idx, G.EOF), (self.OK, None)) else: for t in follows[prod.Left]: self._register(self.action, (idx, t), (self.REDUCE, prod)) else: symbol = item.NextSymbol goto_id = node.get(symbol.Name).idx if goto_id is not None: if symbol.IsTerminal: self._register(self.action, (idx, symbol), (self.SHIFT, goto_id)) else: self._register(self.goto, (idx, symbol), goto_id)
def first_follows(): result = gp.load_grammar() if result[0]: st.error('No se ha definido una gramatica\ o la gramatica definida no es correcta') st.error('Errors: ' + str(result[1])) else: G = result[1] firsts = compute_firsts(G) follows = compute_follows(G, firsts) st.subheader('Firsts:') st.write( pd.DataFrame({ 'keys': firsts.keys(), 'values': firsts.values() })) st.subheader('Follows:') st.write( pd.DataFrame({ 'keys': follows.keys(), 'values': follows.values() }))
def isLL1(G, M=None): if not M: firsts = compute_firsts(G) follows = compute_follows(G, firsts) M = build_parsing_table(G, firsts, follows) for cell in M: if len(M[cell]) > 1: return False return True
def build_parsing_table(G, firsts=None, follows=None): # init parsing table if firsts is None: firsts = compute_firsts(G) if follows is None: follows = compute_follows(G, firsts) M = {} # P: X -> alpha for production in G.Productions: X = production.Left alpha = production.Right ################################################### # working with symbols on First(alpha) ... ################################################### # <CODE_HERE> # ################################################### first = compute_local_first(firsts, alpha) for t in first: if M.get((X, t)): M[(X, t)].append(production) else: M[(X, t)] = [production] ################################################### # working with epsilon... ################################################### # <CODE_HERE> # ################################################### try: alpha_is_epsilon = alpha.IsEpsilon except: alpha_is_epsilon = False if alpha_is_epsilon: for t in follows[X]: if M.get((X, t)): M[(X, t)].append(production) else: M[(X, t)] = [production] # parsing table is ready!!! return M
def build_lalr_automaton(G): def centers(items: [Item]): return frozenset(item.Center() for item in items) def lookaheads(items: [Item]): return {item.Center(): item.lookaheads for item in items} def subset(items1, items2): return all(items1[i] <= items2[i] for i in items1) 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, (G.EOF, )) start = State(frozenset(closure_lr1([start_item], firsts)), True) pending = [start_item] visisted_centers = {centers(start.state): start} visited = {start_item: start} while pending: current_state = visited[pending.pop()] for symbol in G.terminals + G.nonTerminals: next_item = frozenset(goto_lr1(current_state.state, symbol, firsts)) if next_item: try: next_state = visisted_centers[centers(next_item)] if not subset(lookaheads(next_item), lookaheads(next_state.state)): next_state.state = compress( list(next_state.state) + list(next_item)) pending.append(frozenset(next_state.state)) visited[frozenset(next_state.state)] = next_state except KeyError: next_state = State(next_item, True) pending += [next_item] visisted_centers[centers(next_item)] = next_state visited[next_item] = next_state current_state.add_transition(symbol.Name, next_state) return start
def generate_lr_conflict_string(G, parser): automaton = build_LR1_automaton(G.AugmentedGrammar(True)) states = {} for it, node in enumerate(automaton): states[it] = node # for conf in parser.conflicts: # print(f'conf.key {conf.key}, conf.value {conf.value}') # if conf.value[0][0] == 'REDUCE': # st, symbol = conf.key # production = conf.value[0][1] # print(states[st]) # if conf.value[1][0] == 'REDUCE': # st, symbol = conf.key # production = conf.value[1][1] # print(states[st]) st, symbol = parser.conflicts.key _, production = parser.action[st, symbol].pop() print(f'state: {st}') print(f'symbol: {symbol}') assert (st is not None and production is not None and symbol is not None) print(production) input() path = sentence_path(automaton, states[st], symbol, production) for p in path: print(f'path: {p}') input() firsts = compute_firsts(G) follows = compute_follows(G, firsts) extended = expand_path(automaton, path, follows) return extended
def LL1_to_dataframe(G): firsts = compute_firsts(G) follows = compute_follows(G, firsts) M = build_parsing_table(G, firsts, follows) rows, columns = set(), set() matrix = [] for item in M: rows.add(item[0]) columns.add(item[1]) for row in rows: matrix.append([]) for column in columns: try: production = M[row, column][0] matrix[-1].append( str(production.Left) + ' -> ' + str(production.Right)) except KeyError: matrix[-1].append(' ') return pd.DataFrame(matrix, index=rows, columns=columns)
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 = frozenset(goto_lr1(closure, symbol, just_kernel=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
def LL1_to_dataframe(G): firsts = compute_firsts(G) follows = compute_follows(G, firsts) M = build_parsing_table(G, firsts, follows) rows, columns = set(), set() matrix = [] for item in M: rows.add(item[0]) columns.add(item[1]) for row in rows: matrix.append([]) for column in columns: try: productions = "" for prod in M[row, column]: productions += f'{prod.Left} -> {prod.Right}\n' matrix[-1].append(productions) except KeyError: matrix[-1].append(' ') return pd.DataFrame(matrix, index=rows, columns=columns)
if isLL1(new_G): st.success('La gramática transformada es LL(1).') else: st.error('La gramática transformada tampoco es LL(1).') # Calcular Firsts & Follows elif choice == choices[2]: result = gp.load_grammar() if result[0]: st.error('No se ha definido una gramatica\ o la gramatica definida no es correcta') st.error('Errors: ' + str(result[1])) else: G = result[1] firsts = compute_firsts(G) follows = compute_follows(G, firsts) st.subheader('Firsts:') st.write(pd.DataFrame({ 'keys': firsts.keys(), 'values': firsts.values() })) st.subheader('Follows:') st.write(pd.DataFrame({ 'keys': follows.keys(), 'values': follows.values() }))
def metodo_predictivo_no_recursivo(G, M=None, firsts=None, follows=None): # checking table... 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) # parser construction... def parser(w): ################################################### # w ends with $ (G.EOF) ################################################### # init: ### stack = ???? ### cursor = ???? ### output = ???? ################################################### stack = [G.startSymbol] cursor = 0 output = [] # parsing w... while len(stack) > 0 and cursor < len(w): top = stack.pop() a = w[cursor] ################################################### # <CODE_HERE> # ################################################### nextToken = cursor if top.IsTerminal: nextToken += 1 if a != top: # print(a, "!=", top) return False elif top.IsNonTerminal: if not M.get((top, w[nextToken])): return False production = M[ (top, w[nextToken]) ][0] prodRight = production.Right # if not production: # return False output.append(production) for i in range(len(prodRight) - 1, -1, -1): stack.append(prodRight[i]) cursor = nextToken if len(stack) or cursor != len(w) - 1: # print("different size: ", len(stack), "!= 0 or", cursor, "!=", len(w)) # print("the partial output is: ", output) return False # left parse is ready!!! return output # parser is ready!!! return parser