// 所有从from通过一次ch到达的NFA状态 // 这里有-1,表示上次fill只有一个最终状态,即-1 static States expand(const std::vector<NFATran>& trans, const States& from, char ch) { States to; for (States::const_iterator it = from.begin(); it != from.end(); ++it) { int s = *it; if (s == -1) { to.clear(); to.insert(-1); break; } const NFATran& tran = trans[s]; NFATran::const_iterator tit = tran.find(ch); if (tit == tran.end()) { continue; } const States& next = tit->second; for (States::const_iterator nit = next.begin(); nit != next.end(); ++nit) { to.insert(*nit); } } return to; }
// 所有能从from通过EPSILON能达到的NFA状态(包括from) static States fill(const std::vector<NFATran>& trans, const States& last, const States& from, bool* is_last) { std::queue<int> q; for (States::const_iterator it = from.begin(); it != from.end(); ++it) { q.push(*it); } // ends表示终点(即最终状态),要判断这次转移是否只有-1 States ends; States to; while (!q.empty()) { int s = q.front(); q.pop(); to.insert(s); if (last.find(s) != last.end()) { *is_last = true; } if (s == -1) { ends.insert(-1); continue; } const NFATran& tran = trans[s]; NFATran::const_iterator it = tran.find(EPSILON); if (it == tran.end()) { ends.insert(s); continue; } const States& next = it->second; for (States::const_iterator nit = next.begin(); nit != next.end(); ++nit) { if (to.find(*nit) == to.end()) { q.push(*nit); } } } if (ends.find(-1) == ends.end() || ends.size() > 1) { to.erase(-1); } else { to.clear(); to.insert(-1); } return to; }
bool DFAConverter::build(int start, int last, const std::vector<NFATran>& trans, const std::map<size_t, Tag>& tags) { States lasts; lasts.insert(last); return build(start, lasts, trans, tags); }
/** * * @brief returns all targets that correspond with the given source * * @param - source: the source whose targets to look for * @return the set of all targets that correspond with the given source * */ const TransitionStorage::States TransitionStorage::getTargets( State source ) const { States targets; const Info::Internals & src = T_info.fromTrans(source); for( Info::InternalIterator it = src.begin(); it != src.end(); it++ ) { targets.insert(getTarget(*it)); } return targets; }
/** * * @brief returns all entry sites that correspond with the given call site * * @param - callSite: the call site whose entry sites to look for * @return the set of all entry sites that correspond with the given call site * */ const TransitionStorage::States TransitionStorage::getEntries( State callSite ) const { States entries; const Info::Calls & cll = T_info.callTrans(callSite); for( Info::CallIterator it = cll.begin(); it != cll.end(); it++ ) { entries.insert(getEntry(*it)); } return entries; }
/** * * @brief returns all return sites that correspond with the given call site * * @param - callSite: the call site whose return sites to look for * @return the set of all return sites that correspond with the given call site * */ const TransitionStorage::States TransitionStorage::getReturnSites( State callSite ) const { States returns; const Info::Returns & pred = T_info.predTrans(callSite); for( Info::ReturnIterator it = pred.begin(); it != pred.end(); it++ ) { returns.insert(getReturnSite(*it)); } return returns; }
/** * * @brief returns all call sites that correspond with the given exit - return site pair * * @param - exitSite: the exit of the pair whose call sites to look for * @param = returnSite: the return site of the pair whose call sites to look for * @return the set of all call sites that correspond with the exit - return site pair * */ const TransitionStorage::States TransitionStorage::getCallSites( State exitSite, State returnSite ) const { States calls; const Info::Returns & exit = T_info.exitTrans(exitSite); for( Info::ReturnIterator it = exit.begin(); it != exit.end(); it++ ) { if( getReturnSite(*it) == returnSite ) calls.insert(getCallSite(*it)); } return calls; }
//Return a queue of the calculated transition pairs, based on the non-deterministic // finite automaton, initial state, and queue of inputs; each pair in the returned // queue is of the form: input, set of new states. //The first pair contains "" as the input and the initial state. //If any input i is illegal (does not lead to any state in the non-deterministic finite // automaton), ignore it. TransitionsQueue process(const NDFA& ndfa, std::string state, const InputsQueue& inputs) { TransitionsQueue answer; States initialState; initialState.insert(state); answer.enqueue(Transitions("", (initialState))); for (auto x : inputs) { if((ndfa[state].has_key(x))) { answer.enqueue(Transitions(x, ndfa[state][x])); //std::cout << "answer after enqueue: " << answer << std::endl; } else { break; } } return answer; }
bool DFAConverter::build(int start, const States& last, const std::vector<NFATran>& trans, const std::map<size_t, Tag>& tags) { reset(); std::map<States, int> nfa_to_dfa; States v; v.insert(-1); nfa_to_dfa[v] = -1; v.clear(); bool is_last = false; v.insert(start); v = fill(trans, last, v, &is_last); _start = new_state(); nfa_to_dfa[v] = _start; if (is_last) { _last.insert(_start); } merge_tags(v, tags, _start, &_tags); std::queue<States> q; q.push(v); while (!q.empty()) { v = q.front(); q.pop(); int from = nfa_to_dfa[v]; std::set<Byte> dedup; dedup.insert(EPSILON); for (States::const_iterator it = v.begin(); it != v.end(); ++it) { int s = *it; assert(s >= 0); const NFATran& tran = trans[s]; for (NFATran::const_iterator it = tran.begin(); it != tran.end(); ++it) { if (dedup.find(it->first) != dedup.end()) { continue; } is_last = false; States next = expand(trans, v, it->first); next = fill(trans, last, next, &is_last); int to = -1; if (nfa_to_dfa.find(next) == nfa_to_dfa.end()) { to = new_state(); nfa_to_dfa[next] = to; q.push(next); if (is_last) { _last.insert(to); } merge_tags(next, tags, to, &_tags); } else { to = nfa_to_dfa[next]; } _trans[from][it->first] = to; dedup.insert(it->first); } } } return true; }