1
+ #ifndef _eval_main_engine
2
+ #define _eval_main_engine
3
+ #include " iostream"
4
+ #include " iomanip"
5
+ using namespace std ;
6
+
7
+ const string VALID_SET (" .0123456789+-*/^()" );
8
+
9
+ double eval (string &);
10
+ double eval (string &);
11
+ double convertToNumber (string &);
12
+ double operation (double , double , string &);
13
+ int precedence (char );
14
+ bool isDigit (char );
15
+ bool isOperand (string &);
16
+ bool isValidCharacter (char );
17
+ vector<string> breakIntoTokens (string &);
18
+ vector<string> convertToPostfixExp (vector<string> &);
19
+ void manageLeadingNegativeSign (vector<string> &);
20
+ void manageFirstBracketAfterOperand (vector<string> &);
21
+ bool contains_x (string &);
22
+ int mainEngine (argCVDef);
23
+
24
+
25
+
26
+ int mainEngine (argCVDef) {
27
+ string exp;
28
+ cout << dye::light_green (" Eval " ) << __VERSION << endl;
29
+ cout << dye::grey (" Enter '.' or '.exit' to exit" ) << endl;
30
+ // Manual input
31
+ while (true ){
32
+ cout << dye::grey (" > " );
33
+
34
+ fflush (stdin);
35
+ getline (cin, exp);
36
+
37
+ // Exit statements
38
+ if (exp == " ." || exp == " .exit" ){
39
+ cout << dye::grey (" Bye :) !" ) << endl;
40
+ return 0 ;
41
+ }
42
+
43
+ // Checks if there is any whitespace
44
+ if (exp.find_first_not_of (" \t\n\v\f\r " ) == string::npos)
45
+ continue ;
46
+
47
+ cout << dye::grey (" < " ) << setprecision (16 ) << dye::light_green (eval (exp)) << endl;
48
+ }
49
+ return 0 ;
50
+ }
51
+
52
+ float evalSingle (string &exp) {
53
+ return eval (exp);
54
+ }
55
+
56
+
57
+
58
+ void manageFirstBracketAfterOperand (vector<string> &tokens) {
59
+ // cout << "Manage first bracket" << endl;
60
+ if (tokens.size () == 0 )
61
+ return ;
62
+ string multiplySign = " *" ;
63
+ if (tokens.size () == 0 ) return ;
64
+ for (int i = 0 ; i < tokens.size () - 1 ; i++) {
65
+ if (isOperand (tokens[i]) && tokens[i + 1 ] == " (" ) {
66
+ i++;
67
+ tokens.insert (tokens.begin () + i, multiplySign);
68
+ }
69
+ }
70
+ }
71
+ void manageLeadingNegativeSign (vector<string> &tokens) {
72
+ // cout << "Manage Leading Negative Sign" << endl;
73
+ if (tokens.size () == 0 )
74
+ return ;
75
+ string openBracket = " (" ;
76
+ string closeBracket = " )" ;
77
+ string zero = " 0" ;
78
+
79
+ // If the expression starts with '-' sign add '0' before it
80
+ if (tokens[0 ][0 ] == ' -' ) {
81
+ tokens.insert (tokens.begin (), zero);
82
+ }
83
+
84
+ for (int i = 0 ; i < tokens.size () - 1 ; i++) {
85
+ // If there is '-' sign after any operator "*"
86
+ if (!isOperand (tokens[i]) && tokens[i + 1 ] == " -" ) {
87
+ // if there is '(' after that add the end bracket after matching the
88
+ // correct bracket
89
+ if (tokens.begin () + i + 2 != tokens.end () &&
90
+ tokens[i + 2 ] == " (" ) {
91
+ tokens.insert (tokens.begin () + ++i, openBracket);
92
+ tokens.insert (tokens.begin () + ++i, zero);
93
+ i += 2 ;
94
+ int bracesCount = 1 ;
95
+ int j = i + 1 ;
96
+ while (bracesCount != 0 &&
97
+ (tokens.begin () + j != tokens.end ())) {
98
+ char currentCh = tokens[j][0 ];
99
+ if (currentCh == ' (' )
100
+ bracesCount++;
101
+ else if (currentCh == ' )' )
102
+ bracesCount--;
103
+ j++;
104
+ }
105
+ tokens.insert (tokens.begin () + j, closeBracket);
106
+ } else {
107
+ tokens.insert (tokens.begin () + ++i, openBracket);
108
+ tokens.insert (tokens.begin () + ++i, zero);
109
+ i += 2 ;
110
+ tokens.insert (tokens.begin () + ++i, closeBracket);
111
+ }
112
+ }
113
+ }
114
+ }
115
+ double eval (string &exp) {
116
+ vector<string> tokens = breakIntoTokens (exp);
117
+ // if(tokens.size() == 0) return -1;
118
+ manageFirstBracketAfterOperand (tokens);
119
+ manageLeadingNegativeSign (tokens);
120
+ tokens = convertToPostfixExp (tokens);
121
+ stack<double > excStack;
122
+ for (auto &token : tokens) {
123
+ if (isOperand (token)) {
124
+ excStack.push (convertToNumber (token));
125
+ } else {
126
+ double op1 = excStack.top ();
127
+ excStack.pop ();
128
+ double op2 = excStack.top ();
129
+ excStack.pop ();
130
+ excStack.push (operation (op1, op2, token));
131
+ }
132
+ }
133
+ return excStack.empty () ? -1 : excStack.top ();
134
+ }
135
+
136
+
137
+ vector<string> breakIntoTokens (string &exp) {
138
+ // cout << "Breaking Into Tokens" << endl;
139
+
140
+ vector<string> tokens;
141
+ string currentToken = " " ;
142
+
143
+ for (char &ch : exp) {
144
+ if (ch == ' ' || ch == ' \n ' || ch == ' \t ' ) continue ;
145
+
146
+ if (!isValidCharacter (ch)) {
147
+ cout << dye::light_red (" Invalid Expression " );
148
+ return tokens;
149
+ }
150
+
151
+ if (isDigit (ch))
152
+ currentToken.push_back (ch);
153
+ else {
154
+ if (currentToken.length () != 0 ) {
155
+ tokens.push_back (currentToken);
156
+ currentToken = " " ;
157
+ }
158
+ string s = " " ;
159
+ s.push_back (ch);
160
+ tokens.push_back (s);
161
+ }
162
+ }
163
+ if (currentToken.length () != 0 ) tokens.push_back (currentToken);
164
+
165
+ return tokens;
166
+ }
167
+
168
+ vector<string> convertToPostfixExp (vector<string> &tokens) {
169
+ // cout << "Convert to postfix" << endl;
170
+ vector<string> postfix;
171
+ stack<string> stk;
172
+ if (tokens.size () == 0 )
173
+ return tokens;
174
+ for (auto &token : tokens) {
175
+ if (isOperand (token))
176
+ postfix.push_back (token);
177
+
178
+ else if (token == " (" )
179
+ stk.push (token);
180
+
181
+ else if (token == " )" ) {
182
+ while (!stk.empty () && stk.top () != " (" ) {
183
+ postfix.push_back (stk.top ());
184
+ stk.pop ();
185
+ }
186
+
187
+ if (!stk.empty () && stk.top () != " (" )
188
+ break ;
189
+ else
190
+ stk.pop ();
191
+
192
+ } else {
193
+ while (!stk.empty () &&
194
+ precedence (token[0 ]) <= precedence (stk.top ()[0 ])) {
195
+ postfix.push_back (stk.top ());
196
+ stk.pop ();
197
+ }
198
+ stk.push (token);
199
+ }
200
+ }
201
+
202
+ while (!stk.empty ()) {
203
+ postfix.push_back (stk.top ());
204
+ stk.pop ();
205
+ }
206
+ return postfix;
207
+ }
208
+
209
+
210
+
211
+
212
+ double convertToNumber (string &token) {
213
+ char num[token.length ()];
214
+ strcpy (num, token.c_str ());
215
+ return atof (num);
216
+ }
217
+
218
+ double operation (double op1, double op2, string &token) {
219
+ switch (token[0 ]) {
220
+ case ' +' :
221
+ return op2 + op1;
222
+ case ' -' :
223
+ return op2 - op1;
224
+ case ' *' :
225
+ return op2 * op1;
226
+ case ' /' :
227
+ return op2 / op1;
228
+ case ' ^' :
229
+ return pow (op2, op1);
230
+ }
231
+ return 0 ;
232
+ }
233
+
234
+ int precedence (char ch) {
235
+ switch (ch) {
236
+ case ' +' :
237
+ case ' -' :
238
+ return 1 ;
239
+
240
+ case ' *' :
241
+ case ' /' :
242
+ return 2 ;
243
+
244
+ case ' ^' :
245
+ return 3 ;
246
+ }
247
+ return -1 ;
248
+ }
249
+
250
+ bool isOperand (string &s) {
251
+ if (s.length () == 1 )
252
+ return isdigit (s[0 ]);
253
+ else
254
+ return true ;
255
+ }
256
+ bool isValidCharacter (char ch) {
257
+ string validSet = VALID_SET;
258
+ for (auto &c : validSet)
259
+ if (ch == c) return true ;
260
+ return false ;
261
+ }
262
+
263
+ bool isDigit (char c) { return c == ' .' || (c >= ' 0' && c <= ' 9' ); }
264
+
265
+
266
+ #endif
0 commit comments