def nfa_to_dfa(nfa): dfa = DFA(set(nfa.alphabet)) def e_colsure(state_set): # 能够从NFA状态T开始只通过ε转换到达的NFA状态集合 if not isinstance(state_set, set): raise Exception('state_set must be set') queue = list(state_set) result = set(state_set) while queue: h = queue.pop(0) for state in h.get_transfer(Epsilon): if state not in result: result.add(state) queue.append(state) return result def move(state_set, symbol): result = set() for s in state_set: result = result.union(set(s.get_transfer(symbol))) return result state_set_to_node = {} start = tuple(e_colsure(set([nfa.S]))) state_set_to_node[start] = dfa.S queue = [start] while queue: h = queue.pop(0) for symbol in nfa.alphabet: new_set = tuple(e_colsure(move(set(h), symbol))) if not new_set: continue if new_set not in state_set_to_node: node = dfa.create_node() node.data['token'] = set() state_set_to_node[new_set] = node for state in new_set: # if state in nfa.final_state: if state.data: node.data['token'].add(state.data['token']) queue.append(new_set) dfa.add_transfer(state_set_to_node[h], symbol, state_set_to_node[new_set]) return dfa
def create_lr_dfa(final, syntaxs, vn, vt): if vn.intersection(vt): raise Exception('VN and VT has intersection') else: alptabet = list(vn) + list(vt) productions = {} for syntax in syntaxs: if syntax[0] not in productions: productions[syntax[0]] = [] productions[syntax[0]].append(syntax) # print 'productions:' # print productions items_set_to_node = {} # tuple to Node first = {} nullable = {} getting_nullable = set() def get_nullable(item): # 判断一个非终结符是否可以为Epsilon if not isinstance(item, str): raise Exception('item is not str') if item not in vn: raise Exception('item not in vn') if item in nullable: return nullable[item] if item in getting_nullable: nullable[item] = False return nullable[item] getting_nullable.add(item) nullable[item] = False for production in productions[item]: _nullable = True for t in production[1:]: if t in vt: _nullable = False else: _nullable &= get_nullable(t) nullable[item] |= _nullable getting_nullable.remove(item) return nullable[item] getting_first = set() def get_first(item): # 获取first集,返回set if not isinstance(item, tuple): raise Exception('item is not tuple') if item in first: return first[item] getting_first.add(item) first[item] = set() for t in item: if t in vt: first[item].add(t) break else: for production in productions[t]: if production[0] in vt: first[item].add(production[0]) elif production[1:] not in getting_first: first[item] = first[item].union( get_first(production[1:])) if not get_nullable(t): break getting_first.remove(item) return first[item] def closure(item, item_set): pos, production, ahead = item # print 'pos,production,ahead:' # print pos,production,ahead right_part = production[pos + 1:] # print right_part if not right_part or right_part[0] not in vn: return for production in productions[right_part[0]]: new_set = set() for t in ahead: new_set = new_set.union(get_first(right_part[1:] + (t,))) new_item = (0, production, tuple(new_set)) if new_item not in item_set: item_set.add(new_item) closure(new_item, item_set) # create the start Node init_item = (0, (final + '\'', final), ('#',)) init_set = set() init_set.add(init_item) closure(init_item, init_set) dfa = DFA(set(alptabet)) dfa.S.data = tuple(init_set) items_set_to_node[dfa.S.data] = dfa.S # start to build dfa queue = [dfa.S] while queue: head = queue.pop(0) # print 'head %4d' % head.index for symbol in alptabet: # print symbol new_set = set() for item in head.data: pos, production, ahead = item # print 'production, production[pos + 1: pos + 2]:' # print production, production[pos + 1] if (pos + 1 < len(production) and production[pos + 1] == symbol): new_item = (pos + 1, production, ahead) new_set.add(new_item) closure(new_item, new_set) new_set = tuple(new_set) if not new_set: continue if new_set not in items_set_to_node: node = dfa.create_node() node.data = new_set items_set_to_node[new_set] = node queue.append(node) dfa.add_transfer(head, symbol, items_set_to_node[new_set]) print "%d ----%10s---->%d" % (head.index, symbol, items_set_to_node[new_set].index) # print '-----------items_set--------------' # for item in dfa.states[6].data: # print item # raise Exception('') return dfa