Skip to content

Commit f047d69

Browse files
committed
v1.5.0-beta.1
1 parent ae8d9f4 commit f047d69

File tree

10 files changed

+614
-1133
lines changed

10 files changed

+614
-1133
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
bin/
66
obj/
77
*.exe
8-
.vscode
8+
.vscode
9+
**/*.ignore.*

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ No need to open your calculator again for basic calculation. Just type `eval {{e
1212
> Must add this file's location to environment(path) variable.
1313
1414
# Download
15-
Download [eval_x64_1.0.1.exe](https://github.com/codeAbinash/eval/releases/download/v1.0.1/eval_x64_1.0.1.exe) (214kb)
15+
Download [eval_1.5.0_beta_1_64bit.exe](https://github.com/codeAbinash/eval/releases/download/v1.0.1/eval_x64_1.0.1.exe) (214kb)

color.hpp

Lines changed: 0 additions & 878 deletions
This file was deleted.

include/commands.hpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "iostream"
2+
using namespace std;
3+
#include "./define.hpp"
4+
#include "unordered_map"
5+
typedef bool (*scriptFunction)(int, char **);
6+
using namespace std;
7+
8+
namespace command {
9+
bool version(argCVDef) {
10+
std::cout << dye::light_green("Eval ") << dye::light_green(__VERSION);
11+
std::cout << dye::grey(" (C)codeAbinash ") << dye::light_yellow(__version_date) << std::endl;
12+
return true;
13+
}
14+
15+
bool help(argCVDef) {
16+
cout << "Visit " << dye::light_blue("https://github.com/codeAbinash/eval") << " for more information." << endl;
17+
return true;
18+
}
19+
20+
bool unknownCommand(argCVDef) {
21+
cout << "Unknown command "
22+
<< "`" << dye::light_yellow(argv[1]) << "`" << endl;
23+
cout << dye::grey("Akta command o valo kore lekhte parche na :) !") << endl;
24+
cout << "Use " << dye::light_yellow("`eval --help`") << " for more information." << endl;
25+
return false;
26+
}
27+
} // namespace command
28+
29+
/**
30+
* @param argc argument count
31+
* @param argv arguments
32+
* @returns true if the command is executed successfully else return false or
33+
* unknown command
34+
*/
35+
bool executeCommand(argCVDef) {
36+
char *s = argv[1];
37+
/**
38+
* create an unordered_map that contains all the commands and their function
39+
* pointers.
40+
*/
41+
unordered_map<string, scriptFunction> allCommands;
42+
allCommands["--version"] = &command::version;
43+
allCommands["--v"] = &command::version;
44+
allCommands["--help"] = &command::help;
45+
46+
bool (*commandCallbackFunc)(int, char **) = allCommands[s];
47+
48+
return commandCallbackFunc ? commandCallbackFunc(argCV)
49+
: command::unknownCommand(argCV);
50+
}

include/define.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#define __VERSION "v1.5.0" + dye::grey("-beta.1")
2+
#define __version_date "dec 2022"
3+
4+
#define argCVDef int argc, char **argv
5+
#define argCV argc, argv

include/engine/mainEngine.hpp

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
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

include/lib.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "./define.hpp"
2+
3+
/**
4+
* @param s contains the first command line argument
5+
* @return true if the argument is a command
6+
*/
7+
bool ifDashCommand(argCVDef) {
8+
char *s = argv[1];
9+
if (strlen(s) > 2 && s[0] == '-' && s[1] == '-') {
10+
/**
11+
* It seems that the entered command must be system command because it
12+
* starts with '--'
13+
*/
14+
// executeCommand(argCV);
15+
return true;
16+
}
17+
return false;
18+
}

include/main.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// #include "./engine/mainEngine.hpp"
2+
// #include "./define.hpp"
3+
4+
int mainEval(argCVDef) {
5+
if (argc == 1) {
6+
// Direct run,
7+
mainEngine(argCV);
8+
return 0;
9+
}
10+
if (argc == 2) {
11+
// Check for commands
12+
if (ifDashCommand(argCV)) {
13+
// Execute the specific command
14+
return executeCommand(argCV);
15+
}
16+
// The second argument is an expression
17+
string exp (argv[1]);
18+
cout << dye::grey("< ") << dye::light_green(eval(exp)) << endl;
19+
return 0;
20+
}
21+
return 0;
22+
}

0 commit comments

Comments
 (0)