def concatenate_nfa(self, nfa: NFA, char_to_concatenate: str) -> NFA: """ concatenate_nfa Concatenate a regex char to an existing NFA. :param nfa: The existing NFA. :param char_to_concatenate: Character from regex to concatenate. :return: The resulting NFA. """ # As states are added, update the last state to connect from # if this isn't the first char of the regex (only a start state), add an epsilon transition. if len(nfa.states) > 1: self.last_state = nfa.add_epsilon_connector(self.last_state) # add the last state as an last close group self.last_closed_group = self.last_state # Connect to to new state on concat_char if self.union_in_progress: self.last_state = nfa.add_normal_char( self.last_state, char_to_concatenate, True, self.union_in_progress[-1][1]) elif self.last_star: self.last_state = nfa.add_normal_char(self.last_state, char_to_concatenate, True, self.last_star[-1]) self.last_star = self.last_star[:-1] else: self.last_state = nfa.add_normal_char(self.last_state, char_to_concatenate, True, self.open_groups[-1]) return nfa
def union_nfa(self, nfa: NFA, unioning_state: State = None) -> None: """ union_nfa Add a union from the last open group (or initial state) to existing NFA. :param nfa: The existing NFA. :param unioning_state: An optional state to union from (otherwise: last open group) """ start_union = unioning_state if unioning_state else self.open_groups[-1] self.union_in_progress.append((start_union, self.last_state)) logging.debug('Opening union: ' + str((start_union, self.last_state))) if start_union in nfa.accepting_states: nfa.accepting_states.remove(start_union) # If my open group is at the initial state, make a new state if start_union == nfa.initial_state: self.last_state = nfa.replace_initial() # Otherwise, connect a new epsilon path out of the # open group state for the other part of the union else: self.last_state = nfa.add_epsilon_connector(start_union)