def build_LALR_automaton(G): assert len(G.startSymbol.productions) == 1, "Grammar must be augmented" lr1_automaton = build_LR1_automaton(G) same_kernel = {} for node in lr1_automaton: just_center = frozenset([item.Center() for item in node.state]) try: same_kernel[just_center].append(node) except KeyError: same_kernel[just_center] = [node] start = frozenset([item.Center() for item in lr1_automaton.state ]) # como cabecera solo quedan los items sin lookahead automaton = State( lr1_automaton.state, True ) # en visited se guarda el estado que corresponde a la fusion de estaods ocn el mismo nucleo pending = [start] visited = {start: automaton} while pending: current = pending.pop() current_state = visited[current] # se van a actualizar # todos los estados con los que el estado actual tiene alguna transicion lr1_state = same_kernel[current][0] # chequear que cada estado del cjto analizado tenga esa transicion for symbol in G.terminals + G.nonTerminals: if lr1_state.has_transition(symbol.Name): state = lr1_state.transitions[symbol.Name][0] center_items = frozenset( [item.Center() for item in state.state]) try: next_state = visited[center_items] except KeyError: kernel_set = same_kernel[center_items] items_with_lookahead = {} for node in kernel_set: for item in node.state: try: current_item = items_with_lookahead[ item.Center()] except KeyError: current_item = items_with_lookahead[ item.Center()] = set() current_item.update(item.lookaheads) completed_items = [ Item(item.production, item.pos, lookaheads) for item, lookaheads in items_with_lookahead.items() ] next_state = State(frozenset(completed_items), True) visited[center_items] = next_state pending.append(center_items) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
def build_LR1_automaton(self, 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 = self.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: closure_current = self.closure_lr1(current, firsts) goto = self.goto_lr1(closure_current, symbol, just_kernel=True) if len(goto) == 0: continue try: next_state = visited[goto] except KeyError: next_closure = self.closure_lr1(goto, firsts) visited[goto] = next_state = State(frozenset(next_closure), True) pending.append(goto) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
def build_lr0_automaton(G): assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented' start_production = G.startSymbol.productions[0] start_item = Item(start_production, 0) start = frozenset([start_item]) automaton = State(closure_lr0(start), True) pending = [start] visited = {start: automaton} while pending: current = pending.pop() current_state = visited[current] current_closure = current_state.state for symbol in G.terminals + G.nonTerminals: kernel = goto_lr0(current_closure, symbol) if kernel == frozenset(): continue try: next_state = visited[kernel] except KeyError: next_state = visited[kernel] = State(closure_lr0(kernel), True) pending.append(kernel) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
def build_larl1_automaton(G, firsts=None): assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented' if not firsts: firsts = compute_firsts(G) firsts[G.EOF] = ContainerSet(G.EOF) start_production = G.startSymbol.productions[0] start_item = Item(start_production, 0, lookaheads=ContainerSet(G.EOF)) start = frozenset([start_item.Center()]) closure = closure_lr1([start_item], firsts) automaton = State(frozenset(closure), True) pending = [start] visited = {start: automaton} while pending: current = pending.pop() current_state = visited[current] current_closure = current_state.state for symbol in G.terminals + G.nonTerminals: goto = goto_lr1(current_closure, symbol, just_kernel=True) closure = closure_lr1(goto, firsts) center = frozenset(item.Center() for item in goto) if center == frozenset(): continue try: next_state = visited[center] centers = {item.Center(): item for item in next_state.state} centers = { item.Center(): (centers[item.Center()], item) for item in closure } updated_items = set() for c, (itemA, itemB) in centers.items(): item = Item(c.production, c.pos, itemA.lookaheads | itemB.lookaheads) updated_items.add(item) updated_items = frozenset(updated_items) if next_state.state != updated_items: pending.append(center) next_state.state = updated_items except KeyError: visited[center] = next_state = State(frozenset(closure), True) pending.append(center) if current_state[symbol.Name] is None: current_state.add_transition(symbol.Name, next_state) else: assert current_state.get( symbol.Name) is next_state, 'Bad build!!!' automaton.set_formatter(multiline_formatter) return automaton
def build_LALR1_automaton(G): automaton = build_LR1_automaton(G) stKernel = {} for node in automaton: kernel = frozenset([item.Center() for item in node.state]) try: stKernel[kernel].append(node) except KeyError: stKernel[kernel] = [node] initial = frozenset([item.Center() for item in automaton.state]) automaton = State(automaton.state, True) visited = {initial: automaton} pending = [initial] while pending: current = pending.pop() current_state = visited[current] lr1_state = stKernel[current][0] for symbol in G.terminals + G.nonTerminals: if symbol.Name in lr1_state.transitions: dest_core = frozenset([ item.Center() for item in lr1_state.transitions[symbol.Name][0].state ]) try: next_state = visited[dest_core] except KeyError: union_core = {center: set() for center in dest_core} for node in stKernel[dest_core]: for item in node.state: union_core[item.Center()].update(item.lookaheads) union_core = frozenset([ Item(center.production, center.pos, lookaheads=lookaheads) for center, lookaheads in union_core.items() ]) next_state = State(union_core, True) visited[dest_core] = next_state pending.append(dest_core) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
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`) dest = goto_lr1(current_state.state, symbol, just_kernel=True) if not dest: continue if dest in visited: next_state = visited[dest] else: items = goto_lr1(current_state.state, symbol, firsts, just_kernel=False) next_state = State(frozenset(items), True) visited[dest] = next_state pending.append(dest) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
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]) # como cabecera solo queda el kernel closure = closure_lr1(start, firsts) automaton = State(frozenset(closure), True) # en visited si se guarda el estado completo pending = [start] visited = {start: automaton} while pending: current = pending.pop() current_state = visited[current] closure = closure_lr1(current, firsts) for symbol in G.terminals + G.nonTerminals: # (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: next_state = visited[goto] = State( frozenset(closure_lr1(goto, firsts)), True) pending.append(goto) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
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`) next_state_key = goto_lr1(current_state.state, symbol, just_kernel=True) # next_state_key = frozenset([i.NextItem() for i in current_state.state if i.NextSymbol == symbol]) if not next_state_key: continue try: next_state = visited[next_state_key] except KeyError: next_state_items = goto_lr1(current_state.state, symbol, firsts) next_state = State(frozenset(next_state_items), True) pending.append(next_state_key) visited[next_state_key] = next_state current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton
def build_lr1_automaton(G, firsts=None): assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented' if not firsts: 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] current_closure = current_state.state for symbol in G.terminals + G.nonTerminals: kernel = goto_lr1(current_closure, symbol, just_kernel=True) if kernel == frozenset(): continue try: next_state = visited[kernel] except KeyError: goto = closure_lr1(kernel, firsts) visited[kernel] = next_state = State(frozenset(goto), True) pending.append(kernel) current_state.add_transition(symbol.Name, next_state) automaton.set_formatter(multiline_formatter) return automaton