-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSubsetConstructor.cpp
More file actions
126 lines (110 loc) · 3 KB
/
SubsetConstructor.cpp
File metadata and controls
126 lines (110 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "SubsetConstructor.h"
using namespace std;
set<State *> SubsetConstructor::epsilonClosure(set<State *> states)
{
set<State *> result = states;
queue<State *> q;
for (State *s : states)
{
q.push(s);
}
while (!q.empty())
{
State *current = q.front();
q.pop();
map<char, vector<State *>> transitions = current->getTransitions();
if (transitions.find('\0') != transitions.end())
{
for (State *next : transitions['\0'])
{
if (result.find(next) == result.end())
{
result.insert(next);
q.push(next);
}
}
}
}
return result;
}
DFA *SubsetConstructor::constructDFA(NFA *nfa)
{
DFA *dfa = new DFA();
set<State *> startSet = epsilonClosure({nfa->getStartState()});
CombinedState *startCS = new CombinedState(startSet);
dfa->addState(startCS);
dfa->setStartState(startCS);
map<set<State *>, CombinedState *> visited;
visited[startSet] = startCS;
queue<set<State *>> q;
q.push(startSet);
while (!q.empty())
{
set<State *> curSet = q.front();
q.pop();
CombinedState *currentDfa = visited[curSet];
CombinedState *nextDFA;
for (char c : this->getAlphabet(nfa))
{
set<State *> nextSet;
for (State *state : curSet)
{
map<char, vector<State *>> trans = state->getTransitions();
if (state->getTransitions().find(c) != trans.end())
{
for (State *target : trans[c])
{
nextSet.insert(target);
}
}
}
nextSet = epsilonClosure(nextSet);
if (nextSet.empty())
{
continue;
}
if (visited.find(nextSet) == visited.end())
{
nextDFA = new CombinedState(nextSet);
visited[nextSet] = nextDFA;
dfa->addState(nextDFA);
q.push(nextSet);
}
else
{
nextDFA = visited[nextSet];
}
dfa->addTransition(currentDfa, c, nextDFA);
}
}
for (auto &pair : visited)
{
set<State *> stateSet = pair.first;
for (State *state : stateSet)
{
if (state->getAcceptance())
{
pair.second->isAccepting = true;
break;
}
}
}
return dfa;
}
set<char> SubsetConstructor::getAlphabet(NFA *nfa)
{
set<char> alphabet;
map<char, vector<State *>> trans;
for (State *state : nfa->getAllStates())
{
for (auto &pair : state->getTransitions())
{
char character = pair.first;
if (character != '\0')
{
alphabet.insert(character);
}
}
}
return alphabet;
}