def build_test_nfa(): # example NFA on EC pp.51 nfa = NFA() for i in range(10): nfa.add_state(i) nfa.mark_starting(0) nfa.mark_accepting(9, 1) nfa.classifier = CharClassifier( [ord('a'), ord('b'), ord('c'), ord('c') + 1]) nfa.add_transition(0, 1, 1) nfa.add_transition(1, 2, epsilon) nfa.add_transition(2, 9, epsilon) nfa.add_transition(2, 3, epsilon) nfa.add_transition(3, 4, epsilon) nfa.add_transition(3, 6, epsilon) nfa.add_transition(4, 5, 2) nfa.add_transition(5, 8, epsilon) nfa.add_transition(6, 7, 3) nfa.add_transition(7, 8, epsilon) nfa.add_transition(8, 3, epsilon) nfa.add_transition(8, 9, epsilon) return nfa
def cat(nfa_list): nfa_list = list(nfa_list) cat_nfa = NFA() cat_classifier, class_maps = merge_classifiers(nfa.classifier for nfa in nfa_list) cat_nfa.classifier = cat_classifier for i, z in enumerate(zip(nfa_list, class_maps)): nfa, class_map = z # add everything to cat_nfa for start, d in nfa.trans_matrix.items(): cat_nfa.add_state((i, start)) for char, end_set in d.items(): if char == epsilon: for end in end_set: cat_nfa.add_transition((i, start), (i, end), epsilon) else: for domain in class_map[char]: for end in end_set: cat_nfa.add_transition((i, start), (i, end), domain) # cat_nfa.alphabet |= nfa.alphabet for i in range(len(nfa_list) - 1): # link these nfa this = nfa_list[i] next_ = nfa_list[i + 1] for state in this.accepting_states: cat_nfa.add_transition((i, state), (i + 1, next_.starting_state), epsilon) cat_nfa.mark_starting((0, nfa_list[0].starting_state)) for state, category in nfa_list[-1].accepting_states.items(): cat_nfa.mark_accepting((len(nfa_list) - 1, state), category) return cat_nfa
def alt(nfa_list): nfa_list = list(nfa_list) alt_nfa = NFA() alt_classifier, class_maps = merge_classifiers(nfa.classifier for nfa in nfa_list) alt_nfa.classifier = alt_classifier for i, z in enumerate(zip(nfa_list, class_maps)): nfa, class_map = z for start, d in nfa.trans_matrix.items(): alt_nfa.add_state((i, start)) for char, end_set in d.items(): if char == epsilon: for end in end_set: alt_nfa.add_transition((i, start), (i, end), epsilon) else: for domain in class_map[char]: for end in end_set: alt_nfa.add_transition((i, start), (i, end), domain) # alt_nfa.alphabet |= nfa.alphabet for state, category in nfa.accepting_states.items(): alt_nfa.mark_accepting((i, state), category) alt_nfa.add_state(1) # starting state for i, nfa in enumerate(nfa_list): alt_nfa.add_transition(1, (i, nfa.starting_state), epsilon) alt_nfa.mark_starting(1) return alt_nfa
def dot(category): nfa = NFA() nfa.classifier = CharClassifier([0]) nfa.add_state(0) nfa.add_state(1) nfa.add_transition(0, 1, 1) nfa.mark_starting(0) nfa.mark_accepting(1, category) return nfa
def atom(char, category): nfa = NFA() nfa.classifier = CharClassifier([ord(char), ord(char) + 1]) nfa.add_state(0) nfa.add_state(1) nfa.add_transition(0, 1, 1) nfa.mark_starting(0) nfa.mark_accepting(1, category) return nfa
def char_set(markers, accept, category): nfa = NFA() nfa.classifier = CharClassifier(markers) nfa.add_state(0) nfa.add_state(1) for domain in accept: nfa.add_transition(0, 1, domain) nfa.mark_starting(0) nfa.mark_accepting(1, category) return nfa
def build_nfa1(): # NFA on page 151 of the Dragon Book nfa = NFA() for i in range(4): nfa.add_state(i) nfa.add_transition(0, 0, 2) nfa.add_transition(0, 1, 1) nfa.add_transition(1, 1, 1) nfa.add_transition(1, 2, 2) nfa.add_transition(2, 1, 1) nfa.add_transition(2, 3, 2) nfa.add_transition(3, 0, 2) nfa.add_transition(3, 1, 1) nfa.mark_starting(0) nfa.mark_accepting(3, 0) nfa.classifier = CharClassifier([ord('a'), ord('b'), ord('b') + 1]) return nfa