-
Notifications
You must be signed in to change notification settings - Fork 0
/
pda.cpp
148 lines (131 loc) · 4.77 KB
/
pda.cpp
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include "pda.h"
pushdown_automata::pushdown_automata(ifstream& infile)
{
char line[256], current_state, current_input, top_of_stack, next_state, stack_operator, stack_input = 0, temp;
bool found_state = false, isInitial = false;
do {
// find beginning of user defined transition table
if (infile.eof()) {
cout << "Error: input file must contain \"%BT\" to signify the beginning of the table\n";
exit(1);
}
infile.getline(line, 256);
} while(strcmp(line, "%BT"));
cout << "Building non-deterministic pushdown automata...\n";
while (true) {
if ((current_state = infile.get()) == '+') {
isInitial = true;
current_state = infile.get();
}
temp = infile.get();
current_input = infile.get();
// test whether end of the transition table is reached
if (current_state == '%' && temp == 'E' && current_input == 'T')
break;
infile.get();
top_of_stack = infile.get();
infile.get();
next_state = infile.get();
infile.get();
stack_operator = infile.get();
// stack operator must be valid
if (stack_operator != 'p' && stack_operator != 's') {
cout << "Error: stack operator must be either 's' (push) or 'p' (pop)\n";
exit(1);
}
infile.get();
stack_input = infile.get();
if (infile.get() != '\n') {
cout << "Error: line must be six characters separated by spaces\n";
exit(1);
}
// insert transition into data structure
for (int i = 0; i < relations.size(); ++i)
if (relations[i].statecmp(current_state, current_input, top_of_stack)) {
relations[i].addTransition(next_state, stack_operator, stack_input);
found_state = true;
break;
}
if (!found_state) {
relations.push_back(state(current_state, current_input, top_of_stack, isInitial));
relations.back().addTransition(next_state, stack_operator, stack_input);
}
stack_input = 0;
found_state = false;
isInitial = false;
}
infile.get();
cout << "Machine read to accept input.\n\n";
}
bool pushdown_automata::test_string(char *s, int pos)
{
char prevState;
if (pos < (int)strlen(s))
if (pos == -1) {
for (int i = 0; i < relations.size(); ++i)
if (relations[i].isInitial()) {
current_state = relations[i].getState();
if (relations[i].statecmp(current_state, '#', '#')) // test lambda before first input
for (int j = 0; j < relations[i].getTransitions().size(); ++j) {
prevState = current_state;
takeTransition(relations[i].getTransitions()[j]);
if (test_string(s,pos+1))
return true;
reverseTransition(relations[i].getTransitions()[j], prevState);
}
if (relations[i].statecmp(current_state, s[pos+1], '#')) // test whether first input has initial state
for (int j = 0; j < relations[i].getTransitions().size(); ++j) {
prevState = current_state;
takeTransition(relations[i].getTransitions()[j]);
if (test_string(s,pos+2))
return true;
reverseTransition(relations[i].getTransitions()[j], prevState);
}
}
}
else
// test each transition from the current state
for (int i = 0; i < relations.size(); ++i) {
if (relations[i].statecmp(current_state, '#', Stack.top())) // test lambda transition
for (int j = 0; j < relations[i].getTransitions().size(); ++j) {
prevState = current_state;
takeTransition(relations[i].getTransitions()[j]);
if (test_string(s,pos))
return true;
reverseTransition(relations[i].getTransitions()[j], prevState);
}
if (relations[i].statecmp(current_state, s[pos], Stack.top())) // test next input in string
for (int j = 0; j < relations[i].getTransitions().size(); ++j) {
prevState = current_state;
takeTransition(relations[i].getTransitions()[j]);
if (test_string(s,pos+1))
return true;
reverseTransition(relations[i].getTransitions()[j], prevState);
}
}
else
for (int i = 0; i < relations.size(); ++i)
if (relations[i].statecmp(current_state, '#', Stack.top()))
return true;
return false;
}
void pushdown_automata::takeTransition(transition t)
{
current_state = t.getNextState();
if (t.getStackOperator() == 's')
Stack.push(t.getStackInput());
else
Stack.pop();
}
void pushdown_automata::reverseTransition(transition t, char prevState)
{
current_state = prevState;
if (t.getStackOperator() == 's')
Stack.pop();
else
Stack.push(t.getStackInput());
return;
}