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