/* * automata.h * * * Created by Andreas Vox on 02.06.06. * Copyright 2006 under GPL2. All rights reserved. * */ #ifndef AUTOMATA_H #define AUTOMATA_H #include #include #include namespace automata { template class FA_base { public: FA_base(STATE s, OUTPUT d); FA_base(const std::set& states, const std::set& inputs, STATE start, STATE deflt); virtual ~FA_base(); typedef std::map Transitions; const std::set& states() const; const std::set& inputs() const; const Transitions& transitions(STATE s) const; const STATE start() const; const OUTPUT deflt() const; const OUTPUT next(STATE from, INPUT input) const; void addState(STATE newState); void addInput(INPUT newInput); void setTransition(STATE from, INPUT input, OUTPUT to); protected: std::set states_; std::set inputs_; std::map transitions_; const Transitions noTransitions; STATE start_; OUTPUT default_; }; template FA_base::FA_base(STATE s, OUTPUT d) : states_(), inputs_(), transitions_(), noTransitions(), start_(s), default_(d) { states_.insert(s); } template FA_base::FA_base(const std::set& states, const std::set& inputs, STATE start, STATE deflt) : states_(states), inputs_(inputs), transitions_(), noTransitions(), start_(start), default_(deflt) { if (states_.find(start) == states_.end()) states_.insert(start); } template const std::set& FA_base::states() const { return states_; } template const std::set& FA_base::inputs() const { return inputs_; } template const STATE FA_base::start() const { return start_; } template const OUTPUT FA_base::deflt() const { return default_; } template class DFA : public FA_base { public: DFA(STATE s, STATE deflt): FA_base(s, deflt) { } DFA(const std::set& states, const std::set& inputs, STATE start, STATE deflt) : FA_base(states, inputs, start, deflt) { } }; template class NFA : public FA_base > { public: NFA(STATE s, std::set d): FA_base >(s, d) { } NFA(std::set& states, std::set& inputs, STATE start, std::set deflt) : FA_base(states, inputs, start, deflt) { } void addTransition(STATE from, INPUT input, STATE to); /* NFA: S x I -> P(S) DFA': P(S) x I -> P(S) DFA: N x I -> N Algo: todo = { NFA.start } forall src in todo: from = create(src) ntrans: I -> P(S) for all s in src for all (i,t) in NFA.trans[s]: ntrans[i] += t; for all (i,nt) in ntrans: n = create(nt); if n is new: DFA.addState(n); todo += nt; DFA.addTransition(from, i, n) */ template DFA* constructDFA( XXX createState ) // DFA* constructDFA(NSTATE (*createState)( std::set )) // wont work { std::map, NSTATE> newStates; std::set startSet; startSet.insert(FA_base >::start_); NSTATE nstart = createState(startSet); newStates[startSet] = nstart; NSTATE deflt = createState(FA_base >::default_); newStates[FA_base >::default_] = deflt; DFA* result = new DFA(nstart, deflt); result->addState(deflt); std::deque > todo; todo.push_back(startSet); while (todo.size() > 0) { const std::set from = todo.front(); todo.pop_front(); std::map > ntrans; // for all states in from typename std::set::const_iterator s_it; typename std::map >::iterator tr_it; for (s_it=from.begin(); s_it != from.end(); ++s_it) { // for all transitions typename FA_base >::Transitions& trans(FA_base >::transitions_[*s_it]); for (tr_it = trans.begin(); tr_it != trans.end(); ++tr_it) { ntrans[tr_it->first].insert(tr_it->second.begin(), tr_it->second.end()); } } // construct new transitions const NSTATE nfrom = newStates[from]; for (tr_it = ntrans.begin(); tr_it != ntrans.end(); ++tr_it) { std::set & state(tr_it->second); // create follow state NSTATE nstate; if ( newStates.find(state) == newStates.end() ) { nstate = createState(state); result->addState(nstate); newStates[state] = nstate; // remember follow state in todo if new todo.push_back(state); } else { nstate = newStates[state]; } result->setTransition(nfrom, tr_it->first, nstate); } } const std::set& inp(FA_base >::inputs()); typename std::set::const_iterator i; for (i=inp.begin(); i != inp.end(); ++i) result->addInput(*i); return result; } }; template FA_base::~FA_base() { // clean up } template const typename FA_base::Transitions& FA_base::transitions(STATE s) const { typename std::map::const_iterator tr = transitions_.find(s); if (tr != transitions_.end()) return tr->second; else return noTransitions; } template const OUTPUT FA_base::next(STATE from, INPUT input) const { const Transitions& tr(transitions(from)); typename Transitions::const_iterator it = tr.find(input); return it==tr.end() ? default_ : it->second; } template void FA_base::addState(STATE newState) { if (states_.find(newState) == states_.end()) states_.insert(newState); } template void FA_base::addInput(INPUT newInput) { if (inputs_.find(newInput) == inputs_.end()) inputs_.insert(newInput); } template void FA_base::setTransition(STATE from, INPUT input, OUTPUT to) { Transitions& trans(transitions_[from]); trans[input] = to; } template void NFA::addTransition(STATE from, INPUT input, STATE to) { typename FA_base >::Transitions & trans(FA_base >::transitions_[from]); trans[input].insert(to); } } // namespace #endif