-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
111 lines (92 loc) · 3.53 KB
/
main.cpp
File metadata and controls
111 lines (92 loc) · 3.53 KB
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
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>
#include "tokenizer.h"
#include "parser.h"
#include "evaluator.h"
#include "variables.h"
#include "history.h"
static std::string formatResult(double val) {
if (val == std::floor(val) && std::abs(val) < 1e15)
return std::to_string((long long)val);
std::ostringstream oss;
oss << std::setprecision(10) << std::noshowpoint << val;
return oss.str();
}
// checks if input is "x = something"
static bool isAssignment(const std::string& input, std::string& varName, std::string& rhs) {
auto eq = input.find('=');
if (eq == std::string::npos) return false;
std::string lhs = input.substr(0, eq);
lhs.erase(0, lhs.find_first_not_of(" \t"));
lhs.erase(lhs.find_last_not_of(" \t") + 1);
if (lhs.empty()) return false;
for (char c : lhs)
if (!std::isalnum(c) && c != '_') return false;
if (std::isdigit(lhs[0])) return false;
if (lhs == "pi" || lhs == "e" || lhs == "ans") return false;
varName = lhs;
rhs = input.substr(eq + 1);
return true;
}
int main() {
std::cout << "Expression Evaluator — type 'help' for commands\n\n";
Tokenizer tokenizer;
Parser parser;
VariableStore variables;
History history;
Evaluator evaluator(variables);
std::string input;
while (true) {
std::cout << ">> ";
if (!std::getline(std::cin, input)) break;
input.erase(0, input.find_first_not_of(" \t"));
input.erase(input.find_last_not_of(" \t") + 1);
if (input.empty()) continue;
if (input == "exit" || input == "quit") break;
if (input == "help") {
std::cout << "operators : + - * / ^ %\n";
std::cout << "functions : sqrt sin cos tan log log2 ln abs floor ceil\n";
std::cout << "constants : pi e\n";
std::cout << "variables : x = 10, then use x in expressions\n";
std::cout << "ans : reuse last result\n";
std::cout << "commands : history, vars, clear, exit\n\n";
continue;
}
if (input == "history") { history.print(); continue; }
if (input == "vars") { variables.list(); continue; }
if (input == "clear") { history.clear(); std::cout << "cleared\n"; continue; }
// replace 'ans' with last result
std::string expr = input;
std::string lastAns = history.lastResult();
size_t p = 0;
while ((p = expr.find("ans", p)) != std::string::npos) {
expr.replace(p, 3, "(" + lastAns + ")");
p += lastAns.size() + 2;
}
try {
std::string varName, rhs;
if (isAssignment(expr, varName, rhs)) {
auto tokens = tokenizer.tokenize(rhs);
auto postfix = parser.toPostfix(tokens);
double val = evaluator.evaluate(postfix);
variables.set(varName, val);
std::string result = formatResult(val);
std::cout << varName << " = " << result << "\n";
history.add(input, result);
continue;
}
auto tokens = tokenizer.tokenize(expr);
auto postfix = parser.toPostfix(tokens);
double val = evaluator.evaluate(postfix);
std::string result = formatResult(val);
std::cout << "= " << result << "\n";
history.add(input, result);
} catch (const std::exception& ex) {
std::cout << "error: " << ex.what() << "\n";
}
}
return 0;
}