-
Notifications
You must be signed in to change notification settings - Fork 0
/
driver.cpp
275 lines (239 loc) · 6.79 KB
/
driver.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
// Honor Pledge:
//
// I pledge that I have neither given nor
// received any help on this assignment.
//
// blakbenn
//********* Stack, Array, and Base Array **********
#include "BaseArray.h"
#include "Array.h"
#include "Stack.h"
//********* include nodes **********************
#include "Expr_Node.h"
#include "Binary_Expr_Node.h"
#include "Add_Node.h"
#include "Subtract_Node.h"
#include "Multiply_Node.h"
#include "Divide_Node.h"
#include "Mod_Node.h"
#include "Parentheses_Node.h"
#include "Closed_Parentheses_Node.h"
#include "Integer_Node.h"
//**********Other Includes*************************
#include "Expr_Builder.h"
#include "Expr_Tree_Builder.h"
#include "Eval_Expr_Tree.h"
#include "Visitor.h"
//********** C++ libraries ************************
#include "stdio.h"
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstring> // for size_t definition
#include <sstream>
//
// main
//
bool checkIsValidExpression(const std::string & inputStr);
int Build (const std::string & inputStr);
int main (int argc, char * argv [])
{
std::string inputStr;
std::string quitStr;
std::string postFixStr;
std::string tempStr;
quitStr = "QUIT";
printf("Please enter a valid expression or 'QUIT' to quit:\n");
getline(std::cin, inputStr);
while (inputStr.compare(quitStr) != 0)
{
//check for a valid expression
if (checkIsValidExpression(inputStr) == true)
{
try
{
//compute the expression
printf("Result: %d \n", Build(inputStr));
}
// catch "divide by" exceptions
catch(divide_by_zero_exception)
{
printf("Divide by zero error, try again.\n");
}
catch(mod_by_zero_exception)
{
printf("Mod by zero error, try again.\n");
}
}
else
{
//print this message if we dont have a valid expression, get new line
printf("Invalid Expression, please retype. \n");
}
printf("Please enter a valid expression or 'QUIT' to quit:\n");
getline(std::cin, inputStr);
}
}
//
//infix_to_postfix
//
int Build (const std::string & infix)
{
std::istringstream input(infix); // create a input stream parser
std::string token; // current token in string/stream
//create our builder and visitor
Expr_Tree_Builder builder;
Eval_Expr_Tree visitor;
int count = 0; //count the position in the array
int number = 0;
//loop until the end of the string
while (!input.eof())
{
//parse the istringstream
input >> token;
//create our command based on the token
if (token == "+")
builder.Build_Add_Node();
else if (token == "-")
builder.Build_Subtract_Node();
else if (token == "*")
builder.Build_Multiply_Node();
else if (token == "/")
builder.Build_Divide_Node();
else if (token == "%")
builder.Build_Mod_Node();
else if (token == "(")
builder.Build_Parentheses_Node();
else if (token == ")")
builder.Build_Closed_Parentheses_Node();
//uses stoi to convert the string to an integer to be used as input for build_integer_command(int integer)
else
{
number = std::stoi(token.c_str());
builder.Build_Integer_Node(number);
}
}
//build our tree and visit the nodes
builder.Build_Tree().accept(visitor);
//return the result of our visitations
return visitor.result();
}
//
//checkIsValidExpression
//
bool checkIsValidExpression(const std::string & inputStr)
{
std::istringstream input(inputStr); // create a input stream parser
std::string token; // current token in string/stream
// Flags to check if we have two operators next to each other or two operands next to each other
bool SecondOperatorFlag = false;
bool SecondOperandFlag = false;
bool firstToken = true;
//counts parantheses both opened and closed
int numOpenParen = 0;
int numCloseParen = 0;
int number = 0;
//loop until the end of file
while (!input.eof())
{
input >> token;
//check to ensure the first token is an integer or an open paren
if (firstToken == true)
{
firstToken = false;
if(token == "(")
{
//do nothing
}
else
{
SecondOperandFlag == true;
try
{
//convert a string into an integer
number = std::stoi(token.c_str());
}
catch(const std::invalid_argument& err)
{
return false;
}
}
}
//check if token is an operator token
if (token == "+" || token == "-" || token == "*" || token == "/" || token == "%" || token == "(" || token == ")")
{
if(SecondOperatorFlag && token != "(")
{
return false;
}
//set operator flag to true and operand flag to false (next token we want is an operand)
SecondOperandFlag = false;
SecondOperatorFlag = true;
//increment respective parentheses counter
if(token == "(")
{
numOpenParen++;
}
else if(token == ")")
{
numCloseParen++;
SecondOperatorFlag = false; // this is done to ensure an operator can follow a closed paren
SecondOperandFlag = true; // this is done to ensure an operand may not follow a cloden paren
}
//if we have more closed parentheses than open at any time it cannot be a valid expression
if(numOpenParen < numCloseParen)
{
return false;
}
if(numCloseParen == 1)
{
//remove a close and open parentheses from our count
numCloseParen--;
numOpenParen--;
}
}
//if it is not an operator token it must be an operand token
else
{
//check for two operands in a row, if found return false
if(SecondOperandFlag)
{
return false;
}
//this try catch will cause this function to return false for any invalid input ie: "1 ++ 1"
try
{
//convert a string into an integer
number = std::stoi(token.c_str());
}
catch(const std::invalid_argument& err)
{
return false;
}
//set operand flag to true and operator flag to false (next token we want is an operator)
SecondOperandFlag = true;
SecondOperatorFlag = false;
}
}
//check the number of close parentheses matches the number of open parentheses
//last token should be an integer or a closen parentheses, so this will check that and return false if that is not the case
if(token != ")")
{
try
{
//convert a string into an integer
number = std::stoi(token.c_str());
}
catch(const std::invalid_argument& err)
{
return false;
}
}
//check the number of closed parentheses matches the number of open parentheses
if(numCloseParen != numOpenParen)
{
return false;
}
//return true if the expression passes all of the tests
return true;
}