forked from bikaldev/GraphingCalc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.cpp
302 lines (275 loc) · 8.33 KB
/
Parser.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#include "include/Parser.hpp"
#include "include/ParserException.hpp"
Parser::Parser(std::string s):exp{s}
{
//this doesn't work
StringToInfix();
InfixToPostfix();
}
// Convert a string to an infix queue
void Parser::StringToInfix()
{
Tokenizer ps(exp);
//queue<Token*> output;
string temp;
char t;
double d;
unsigned int left_bracket_num = 0;
unsigned int right_bracket_num = 0;
// Loop until no other string to parse
// Each time we get a new token, push to the output queue
while (!ps.isEmpty())
{
temp = ps.nextToken();
switch (ps.getType())
{
case token::OPERAND:
// Get the number converted from the next string token
d = ps.getNumber();
infix_exprn.push(new Operand(d));
break;
// In other cases, convert the parsed string to character
case token::OPERATOR:
//check if there are multiple datas.
if (infix_exprn.back()->TypeOf() == token::OPERATOR)
{
throw INVALIDFORMAT("Multiple operators used at once");
}
t = temp[0];
infix_exprn.push(new Operator(t));
break;
case token::LEFTBRACKET:
t = temp[0];
infix_exprn.push(new LeftBracket(t));
left_bracket_num++;
break;
case token::RIGHTBRACKET:
t = temp[0];
infix_exprn.push(new RightBracket(t));
right_bracket_num++;
break;
case token::VARIABLE:
//we have an exception here dealt using if.
if (!infix_exprn.empty())
{
switch (infix_exprn.back()->TypeOf())
{
//this case works perfectly fine but there seems to be some problem with the variable case used here.
case token::OPERAND:
infix_exprn.push(new Operator('*'));
break;
default:
break;
}
}
t = temp[0];
infix_exprn.push(new Variable(t));
break;
case token::FUNCTION:
infix_exprn.push(new Function(temp));
break;
default:
break;
}
}
if (left_bracket_num != right_bracket_num)
{
throw INVALIDFORMAT("Right or Left Bracket missing in the expression");
}
}
void Parser::InfixToPostfix()
{
std::queue<Token*> infix_expr = infix_exprn;
Token* p;
// While there are still tokens to be read from the input
while (!(infix_expr.empty()))
{
// Pop the token from the input and check its type
p = infix_expr.front();
infix_expr.pop();
switch (p->TypeOf())
{
// If it is a number, push into the output queue
case token::OPERAND: {
postfix_expr.push(p);
break;
}
case token::VARIABLE: {
postfix_expr.push(p);
break;
}
// If it is a left bracket, push into the operator stack
case token::LEFTBRACKET: {
operator_stack.push(p);
break;
}
// If it is a function, push into the operator stack
case token::FUNCTION: {
operator_stack.push(p);
break;
}
// If it is a right bracket, pop all the operators from the operator stack until the left bracket
// onto the output queue
case token::RIGHTBRACKET: {
while (!(operator_stack.empty()) && (operator_stack.top())->TypeOf() != token::LEFTBRACKET)
{
postfix_expr.push(operator_stack.top());
operator_stack.pop();
}
operator_stack.pop();
break;
}
// If it is an operator
case token::OPERATOR: {
// while ((there is a function at the top of the operator stack)
// or (there is an operator at the top of the operator stack with greater precedence)
// or (the operator at the top of the operator stack has equal precedence and is left associative))
// and (the operator at the top of the operator stack is not a left bracket):
// Push to the postfix queue
while (!(operator_stack.empty()) && (((operator_stack.top())->TypeOf() == token::FUNCTION) || (((operator_stack.top())->TypeOf() == token::OPERATOR && (static_cast<Operator*>(operator_stack.top())->getPrecendence() > static_cast<Operator*>(p)->getPrecendence() || (static_cast<Operator*>(operator_stack.top())->getPrecendence() == static_cast<Operator*>(p)->getPrecendence() && !(static_cast<Operator*>(operator_stack.top())->isRightAssociative())))))) && (operator_stack.top())->TypeOf() != token::LEFTBRACKET)
{
postfix_expr.push(operator_stack.top());
operator_stack.pop();
}
// After the while loop, push all the operator in the operator stack
operator_stack.push(p);
break;
}
default:
break;
}
}
// Push the remaining operators in the operator stack to the postfix queue
while (!(operator_stack.empty()))
{
postfix_expr.push(operator_stack.top());
operator_stack.pop();
}
//return postfix;
}
// Evaluate the postfix queue
double Parser::EvaluatePostfix(double x, double y)
{
std::queue<Token*>postfix = postfix_expr;
//if output stack is not created here we will run into problems regarding the use of unary operators.
stack<Token*> output_stack;
Token* p;
double left = 0, right = 0, output = 0;
while (!(postfix.empty()))
{
p = postfix.front();
postfix.pop();
switch (p->TypeOf())
{
// If the type of the node in the Queue is an operand, push it to the Stack
case token::OPERAND: {
output_stack.push(p);
//std::cout<<static_cast<Operand*>(output_stack.top())->GetOperand()<<std::endl;
break;
}
// If the type of the node in the Queue is a variable, push it to the Stack as an Operand
case token::VARIABLE: {
switch (static_cast<Variable*>(p)->VariableTypeOf())
{
case X:
output_stack.push(new Operand(x));
break;
case Y:
output_stack.push(new Operand(y));
break;
default:
break;
}
break;
}
case token::RIGHTBRACKET:
break;
case token::LEFTBRACKET:
break;
case token::LETTER:
break;
case token::OTHER:
break;
// If the type is an operator, get the operator, pop at the Stack, do the operation then push the result to the Stack
case token::OPERATOR:
{
try
{
//is this code going in an endless loop
if (output_stack.size() == 1)
{
//this needs to be used so that we can use the equation y=-6.
//std::cout<<"this part of the code is being used"<<std::endl;
//for some reason this code not code
//std::cout<<static_cast<Operand*>(output_stack.top())->GetOperand()<<std::endl;
//here after minus -6 we are getting -12
right = static_cast<Operand*>(output_stack.top())->GetOperand();
output_stack.pop();
output = static_cast<Operator*>(p)->evaluate(left, right);
//output_stack.push(new Operand(output));
//break;
}
// For regular operators
else
{
//this is the place where the error occurs if the operand is the first member used.
//since there is no term in front of the operand as it is the first term in the solution
//std::cout<<"this is the part of the code working and it works well"<<std::endl;
//we get an error right here for 0-6
right = static_cast<Operand*>(output_stack.top())->GetOperand();
output_stack.pop();
//there is a error on this part of the code
left = static_cast<Operand*>(output_stack.top())->GetOperand();
output_stack.pop();
output = static_cast<Operator*>(p)->evaluate(left, right);
//output_stack.push(new Operand(output));
//break;
}
}
//use this to put x=0
catch(IMAGINARY)
{
//this might be a better option because this ensures that the nothing is drawn. The previous solution only made sure that the terminal point is origin which isn't alwaays true
//termination of programs might be a better option here.
output = 1000;
//output_stack.push(new Operand(output));
//break;
}
output_stack.push(new Operand(output));
break;
}
// If the type is a function, pop the operand at the stack and push the result to the Stack
case token::FUNCTION: {
right = static_cast<Operand*>(output_stack.top())->GetOperand();
output_stack.pop();
output = static_cast<Function*>(p)->evaluate(right);
output_stack.push(new Operand(output));
break;
}
default:
break;
}
}
return static_cast<Operand*>(output_stack.top())->GetOperand();
}
Parser::~Parser()
{
while (!postfix_expr.empty())
{
Token* k = postfix_expr.front();
delete k;
k=NULL;
postfix_expr.pop();
}
//this might be the reason for the seg fault.
//lets not delete the output stack for now
/*
while (!output_stack.empty())
{
Token * k = output_stack.top();
delete k;
k = NULL;
output_stack.pop();
}
*/
}