diff --git a/src/automata.cpp b/src/automata.cpp index b2d1a34..2f4406e 100644 --- a/src/automata.cpp +++ b/src/automata.cpp @@ -1,5 +1,6 @@ #include "Lexesis/automata.h" +#include #include #include #include @@ -94,11 +95,25 @@ namespace lxs { return s; } - std::set ENFA::eClose(State) { - + std::set ENFA::eClose(State s) const { + std::set states; + std::queue statequeue; + statequeue.push(s); + while(!statequeue.empty()) { + auto state = statequeue.front(); + statequeue.pop(); + auto newStates = epsilonTransitions.find(state)->second; + for(auto newstate: newStates) { + if(states.find(newstate) == states.end()) { + states.insert(newstate); + statequeue.push(newstate); + } + } + } + return states; } - std::set NFA::eClose(State s) { + std::set NFA::eClose(State s) const { return {s}; } @@ -260,5 +275,87 @@ namespace lxs { computeDistinguishable(reversed, dist); return compress(d, reachable, dist); } + + namespace { // Utility functions for mssc + + std::set getNextState(std::set oldstate, char symbol, const NFA& e) { + std::set states; + for(auto &state: oldstate) { + auto a = e.delta.find(state)->second; + auto newStates = a.find(symbol); + if(newStates != a.end()) { + for(auto &newstate:newStates->second) { + auto eclosestates = e.eClose(newstate); + for(auto &eclosestate:eclosestates) { + states.insert(eclosestate); + } + } + } + } + if(states.empty()) states.insert(-1); + return states; + } + + } //namespace + + DFA mssc(const NFA& e) { + std::map,std::map > > dfa; + + std::map > trans; + for (int c = 0; c < 256; c++) { + trans.insert(std::pair >(c,{(unsigned long long) -1})); + } + dfa.insert(std::pair,std::map > > ({(unsigned long long) -1},trans)); + + std::queue > tocheck; + tocheck.push(e.eClose(e.starting)); + while(!tocheck.empty()) { + auto state = tocheck.front(); + tocheck.pop(); + std::map > trans; + for (int c = 0; c < 256; c++) { + auto nextstate = getNextState(state,c,e); + trans.insert(std::pair > (c,nextstate)); + if(dfa.find(nextstate) == dfa.end()) { + tocheck.push(nextstate); + } + } + dfa.insert(std::pair, std::map > > (state,trans)); + } + std::map,State> lookup; + State numStates = 0; + for(auto &state:dfa) { + lookup.insert(std::pair, State> (state.first, numStates++)); + } + DFA result; + result.numStates = numStates; + result.starting = lookup.find(e.eClose(e.starting))->second; + std::map reversepriority; + for(auto &state:dfa) { + std::set priorityset; + State newstate = lookup.find(state.first)->second; + std::map newtransitions; + for(auto &item:state.first) { + auto accepting = e.priority.find(item); + if(accepting != e.priority.end()) { + priorityset.insert(accepting->second); + } + } + if(!priorityset.empty()) { + result.accepting.insert(newstate); + result.priority.insert(std::pair (newstate,*priorityset.begin())); + reversepriority.insert(std::pair (*priorityset.begin(),newstate)); + } + for(auto &tranition:state.second) { + newtransitions.insert(std::pair (tranition.first, lookup.find(tranition.second)->second)); + } + result.delta.insert(std::pair > (newstate,newtransitions)); + } + for(auto &priority: e.priority) { + auto newstate = reversepriority.find(priority.second)->second; + result.acceptingToken.insert(std::pair (newstate,e.acceptingToken.find(priority.first)->second)); + } + return result; + } } //namespace lxs