Clean up mssc

This commit is contained in:
Robin Jadoul 2016-05-10 16:04:34 +02:00
parent 95f8b4dac1
commit 32f4d6be81
2 changed files with 44 additions and 24 deletions

View File

@ -2,6 +2,7 @@
#ifndef AUTOMATA_H #ifndef AUTOMATA_H
#define AUTOMATA_H #define AUTOMATA_H
#include <climits>
#include <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
@ -11,6 +12,7 @@
namespace lxs { namespace lxs {
typedef unsigned long long State; typedef unsigned long long State;
typedef unsigned long long Priority; typedef unsigned long long Priority;
const State deadState = ULLONG_MAX;
struct Automaton { struct Automaton {
State numStates = 0; State numStates = 0;

View File

@ -103,7 +103,7 @@ namespace lxs {
while(!statequeue.empty()) { while(!statequeue.empty()) {
auto state = statequeue.front(); auto state = statequeue.front();
statequeue.pop(); statequeue.pop();
auto newStates = epsilonTransitions.find(state)->second; const auto& newStates = epsilonTransitions.find(state)->second;
for(auto newstate: newStates) { for(auto newstate: newStates) {
if(states.find(newstate) == states.end()) { if(states.find(newstate) == states.end()) {
states.insert(newstate); states.insert(newstate);
@ -296,20 +296,21 @@ namespace lxs {
} }
} }
} }
if(states.empty()) states.insert(-1);
return states; return states;
} }
} //namespace } //namespace
DFA mssc(const NFA& e) { DFA mssc(const NFA& e) {
//Temporary, improper dfa structure
std::map<std::set<State>,std::map<char,std::set<State> > > dfa; std::map<std::set<State>,std::map<char,std::set<State> > > dfa;
std::map<char, std::set<State> > trans; std::map<char, std::set<State> > trans;
for (int c = 0; c < 256; c++) { for (int c = 0; c < 256; c++) {
trans.insert(std::pair<char,std::set<State> >(c,{(unsigned long long) -1})); trans[c] = {};
} }
dfa.insert(std::pair<std::set<State>,std::map<char,std::set<State> > > ({(unsigned long long) -1},trans)); dfa[{}] = trans;
//Lazy evaluation, on a still implicit DFA
std::queue<std::set<State> > tocheck; std::queue<std::set<State> > tocheck;
tocheck.push(e.eClose(e.starting)); tocheck.push(e.eClose(e.starting));
while(!tocheck.empty()) { while(!tocheck.empty()) {
@ -318,46 +319,63 @@ namespace lxs {
std::map<char, std::set<State> > trans; std::map<char, std::set<State> > trans;
for (int c = 0; c < 256; c++) { for (int c = 0; c < 256; c++) {
auto nextstate = getNextState(state,c,e); auto nextstate = getNextState(state,c,e);
trans.insert(std::pair<char,std::set<State> > (c,nextstate)); trans[c] = nextstate;
if(dfa.find(nextstate) == dfa.end()) { if(dfa.find(nextstate) == dfa.end()) {
tocheck.push(nextstate); tocheck.push(nextstate);
} }
} }
dfa.insert(std::pair<std::set<State>, std::map<char,std::set<State> > > (state,trans)); dfa[state] = trans;
} }
//Assign sequential indices for the actual DFA
std::map<std::set<State>,State> lookup; std::map<std::set<State>,State> lookup;
State numStates = 0; State numStates = 0;
for(auto &state:dfa) { for(auto &state : dfa) {
lookup.insert(std::pair<std::set<State>, State> (state.first, numStates++)); if (state.first.size())
lookup[state.first] = numStates++;
else
lookup[state.first] = deadState;
} }
//Setup the actual DFA
DFA result; DFA result;
result.numStates = numStates; result.numStates = numStates;
result.starting = lookup.find(e.eClose(e.starting))->second; result.starting = lookup.find(e.eClose(e.starting))->second;
std::map<Priority, State> reversepriority;
//Setup the transitions
//Merge priorities and acceptingTokens
for(auto &state:dfa) { for(auto &state:dfa) {
std::set<Priority> priorityset; Priority priority = std::numeric_limits<Priority>::max();
std::string acTok = "";
State newstate = lookup.find(state.first)->second; State newstate = lookup.find(state.first)->second;
std::map<char,State> newtransitions; std::map<char,State> newtransitions;
for(auto &item:state.first) { for(auto &item : state.first) {
auto accepting = e.priority.find(item); if(e.accepting.count(item) > 0) {
if(accepting != e.priority.end()) { const auto& newPrior = e.priority.find(item)->second;
priorityset.insert(accepting->second); if (newPrior < priority)
{
priority = newPrior;
acTok = e.acceptingToken.find(item)->second;
}
} }
} }
if(!priorityset.empty()) {
//Insert the found priority
if(priority != std::numeric_limits<Priority>::max()) {
result.accepting.insert(newstate); result.accepting.insert(newstate);
result.priority.insert(std::pair<State,Priority> (newstate,*priorityset.begin())); result.priority[newstate] = priority;
reversepriority.insert(std::pair<Priority,State> (*priorityset.begin(),newstate)); result.acceptingToken[newstate] = acTok;
} }
for(auto &tranition:state.second) {
newtransitions.insert(std::pair<char,State> (tranition.first, lookup.find(tranition.second)->second)); //Do transition
for(auto &transition : state.second) {
newtransitions[transition.first] = lookup[transition.second];
} }
result.delta.insert(std::pair<State,std::map<char,State> > (newstate,newtransitions));
} result.delta[newstate] = std::move(newtransitions);
for(auto &priority: e.priority) {
auto newstate = reversepriority.find(priority.second)->second;
result.acceptingToken.insert(std::pair<State,std::string> (newstate,e.acceptingToken.find(priority.first)->second));
} }
return result; return result;
} }