MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
nfa2dfa.cpp
Go to the documentation of this file.
1#include "automaton/nfa2dfa.h"
2
3#include <map>
4#include <queue>
5#include <set>
6#include <unordered_map>
7
8namespace automaton {
9
10// calculate epsilon closure of a set of states
11std::set<const NFANode*> epsilonClosure(const std::set<const NFANode*>& states) {
12 std::set<const NFANode*> closure;
13 std::queue<const NFANode*> stateQueue;
14 for (const auto& state : states) stateQueue.push(state);
15 while (!stateQueue.empty()) {
16 auto currentState = stateQueue.front();
17 stateQueue.pop();
18 closure.insert(currentState);
19 currentState->for_transitions([&](auto c, auto to) {
21 if (closure.find(to) == closure.end()) stateQueue.push(to);
22 }
23 });
24 }
25 return closure;
26}
27
28std::set<const NFANode*> epsilonClosure(const NFANode* state) {
29 return epsilonClosure(std::set<const NFANode*>{state});
30}
31
32// nfa2dfa implementation
33std::unique_ptr<DFA> nfa2dfa(const NFA& nfa) {
34 auto dfa = std::make_unique<DFA>();
35 std::map<std::set<const NFANode*>, DFANode*> dfaStates;
36 std::queue<std::set<const NFANode*>> stateQueue;
37 std::set<const NFANode*> startState = epsilonClosure(nfa.get_start());
38 dfaStates.emplace(startState, dfa->add_state());
39 stateQueue.push(startState);
40 while (!stateQueue.empty()) {
41 auto currentState = stateQueue.front();
42 stateQueue.pop();
43 auto currentDfaState = dfaStates[currentState];
44 std::map<std::uint16_t, std::set<const NFANode*>> nextStates;
45 // calculate next states
46 for (auto& nfaState : currentState) {
47 nfaState->for_transitions([&](auto c, auto to) {
48 if (c == NFA::SpecialTransitons::EPSILON) return;
49 if (nextStates.find(c) == nextStates.end())
50 nextStates.emplace(c, std::set<const NFANode*>{to});
51 else
52 nextStates[c].insert(to);
53 });
54 }
55 // add new states for unknown next states
56 for (auto& [c, tos] : nextStates) {
57 auto toStateClosure = epsilonClosure(tos);
58 if (dfaStates.find(toStateClosure) == dfaStates.end()) {
59 dfaStates.emplace(toStateClosure, dfa->add_state());
60 stateQueue.push(toStateClosure);
61 }
62 currentDfaState->add_transition(dfaStates[toStateClosure], c);
63 }
64 }
65 dfa->set_start(dfaStates[startState]);
66 for (auto& [state, dfaState] : dfaStates) {
67 for (auto& nfaState : state) {
68 if (nfaState->is_accepting()) dfaState->set_accepting(true);
69 if (nfaState->is_erroring()) {
70 dfaState->set_accepting(false);
71 dfaState->set_erroring(true);
72 break;
73 }
74 }
75 }
76 return dfa;
77}
78
79} // namespace automaton
const NodeType * get_start() const
Definition automaton.h:33
std::unique_ptr< DFA > nfa2dfa(const NFA &nfa)
Definition nfa2dfa.cpp:33
std::set< const NFANode * > epsilonClosure(const std::set< const NFANode * > &states)
Definition nfa2dfa.cpp:11