NFA NFA::createConcatenatingNFA(const NFA &a, const NFA &b) { NFA result; int initialA, finalA, initialB, finalB; result.initializeFromPair(a, b, &initialA, &finalA, &initialB, &finalB); result.addTransition(result.initialState, Epsilon, initialA); result.addTransition(finalA, Epsilon, initialB); result.addTransition(finalB, Epsilon, result.finalState); return result; }
NFA NFA::createSingleInputNFA(InputType input) { NFA result; result.initialize(2); result.addTransition(result.initialState, input, result.finalState); return result; }
NFA NFA::createAlternatingNFA(const NFA &a, const NFA &b) { NFA result; int newInitialA, newFinalA, newInitialB, newFinalB; result.initializeFromPair(a, b, &newInitialA, &newFinalA, &newInitialB, &newFinalB); result.addTransition(result.initialState, Epsilon, newInitialA); result.addTransition(result.initialState, Epsilon, newInitialB); result.addTransition(newFinalA, Epsilon, result.finalState); result.addTransition(newFinalB, Epsilon, result.finalState); return result; }
NFA NFA::createOptionalNFA(const NFA &a) { NFA result; result.initialize(a.states.count() + 2); int baseIdxA = 1; int initialA = a.initialState + baseIdxA; int finalA = a.finalState + baseIdxA; result.copyFrom(a, baseIdxA); result.addTransition(result.initialState, Epsilon, initialA); result.addTransition(result.initialState, Epsilon, result.finalState); result.addTransition(finalA, Epsilon, initialA); result.addTransition(finalA, Epsilon, result.finalState); return result; }
automata::NFA<nfa_state_t, token_t>* RuleState::createNFA() { using automata::NFA; /// maps paths uniquely to an nfa_state std::map<path_t, nfa_state_t> nfa_states; nfa_states.clear(); path_t prefix; // START and EMPTY are both: tokens and nfa_states prefix.push_back(START); nfa_states[prefix] = START; prefix[0] = EMPTY; nfa_states[prefix] = EMPTY; std::set<nfa_state_t> deflt; deflt.insert(EMPTY); NFA<nfa_state_t, token_t> *nfa = new NFA<nfa_state_t, token_t>(START, deflt); nfa->addState(EMPTY); nfa->addInput(ANY); nfa->addTransition(EMPTY, ANY, EMPTY); for (unsigned int i = 0; i < rules.size(); ++i) { const std::string currPattern(fromXMLString(rules[i].first)); const unsigned int len = currPattern.length(); int pos; nfa_state_t lastState; // determine if this is a start pattern prefix.resize(1); if (currPattern[0] == '/') { prefix[0] = START; pos = 1; lastState = START; } else { prefix[0] = EMPTY; pos = 0; lastState = EMPTY; } // std::cerr << "looking at pattern: " << currPattern << "\n"; // for all prefixes do { std::string::size_type pos2 = currPattern.find('/', pos); if (pos2 == std::string::npos) pos2 = len; std::string diff(currPattern.substr(pos, pos2-pos)); token_t tok = createToken(fromSTLString(diff)); // std::cerr << pos << "-" << pos2 << "\t: " << diff << " = " << tok << "\n"; // create loop if REPEAT token if (tok == REPEAT) { nfa->addTransition(lastState, ANY, lastState); //FIXME: that's wrong, need to create repeating state // std::cerr << "T " << lastState << "--*-->" << lastState << "\n"; pos = pos2 + 1; continue; } prefix.push_back(tok); // create new state if necessary nfa_state_t nstate; if (nfa_states.find(prefix) != nfa_states.end()) { nstate = nfa_states[prefix]; } else { nstate = nfa_states.size(); nfa->addState(nstate); nfa_states[prefix] = nstate; } // add transition nfa->addInput(tok); nfa->addTransition(lastState, tok, nstate); // std::cerr << "T " << lastState << "--(" << tok << ")-->" << nstate << "\n"; lastState = nstate; pos = pos2 + 1; } while(pos < signed(len)); accepting.push_back(lastState); // std::cerr << "accepted in " << lastState << "\n"; // copy all transition from EMPTY to all other states const NFA<nfa_state_t, token_t>::Transitions& transFromEmpty(nfa->transitions(EMPTY)); std::set<nfa_state_t>::const_iterator it, st; NFA<nfa_state_t, token_t>::Transitions::const_iterator tr; for (it = nfa->states().begin(); it != nfa->states().end(); ++it) { if (*it == EMPTY) continue; for (tr = transFromEmpty.begin(); tr != transFromEmpty.end(); ++tr) for (st = tr->second.begin(); st != tr->second.end(); ++st) nfa->addTransition(*it, tr->first, *st); } // ANY transitions const std::set<token_t>& inputs(nfa->inputs()); std::set<token_t>::const_iterator tok; for (it = nfa->states().begin(); it != nfa->states().end(); ++it) { const std::set<nfa_state_t>& anyStates(nfa->next(*it, ANY)); for (st = anyStates.begin(); st != anyStates.end(); ++st) for (tok=inputs.begin(); tok != inputs.end(); ++tok) if (*tok != ANY) nfa->addTransition(*it, *tok, *st); } } return nfa; }