-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathevox.cpp
More file actions
157 lines (151 loc) · 3.63 KB
/
evox.cpp
File metadata and controls
157 lines (151 loc) · 3.63 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
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
#include "evox.hpp"
namespace evox {
std::vector<function> functions;
int get_precedence(char op) {
switch (op) {
case '^':
return 3;
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}
double apply_operation(double a, double b, char op) {
switch (op) {
case '^':
return std::pow(a, b);
case '*':
return a * b;
case '/':
return a / b;
case '+':
return a + b;
case '-':
return a - b;
default:
return 0;
}
}
void register_function(const std::string &name, double (*func)(double)) {
functions.push_back({name, func});
}
bool init() {
register_function("sin", std::sin);
return true;
}
double evox(const std::string &expression) {
std::stack<double> numbers;
std::stack<char> operators;
bool reading_number = false;
double current_number = 0;
double decimal_place = 10; // To handle decimal digits
int open_parentheses_count = 0;
for (char c : expression) {
if (isdigit(c) || c == '.') { // Allow digits and decimal point
if (c == '.') {
decimal_place = 0.1;
} else {
if (reading_number) {
current_number += (c - '0') * decimal_place;
decimal_place *= 0.1;
} else {
current_number = current_number * 10 + (c - '0');
}
}
reading_number = true;
} else if (std::isalpha(c)) {
std::istringstream iss(expression);
std::string functionName;
while (std::isalpha(c)) {
functionName += c;
iss >> c;
}
// Skip any non-numeric characters
while (!std::isdigit(c) && c != '-' && c != '+') {
iss >> c;
}
iss.putback(c);
double argument;
iss >> argument; // Assume the argument is a single number
auto it = std::find_if(
functions.begin(), functions.end(), [&functionName](const function &f) {
return f.name == functionName;
});
if (it != functions.end()) {
numbers.push(it->func(argument));
}
} else {
if (reading_number) {
numbers.push(current_number);
current_number = 0;
decimal_place = 10; // Reset decimal place
reading_number = false;
}
if (c == '(') {
operators.push(c);
open_parentheses_count++;
} else if (c == ')') {
if (open_parentheses_count == 0) {
// throw std::runtime_error("Mismatched parentheses: Too many closing parentheses");
}
while (!operators.empty() && operators.top() != '(') {
char op = operators.top();
operators.pop();
double b = numbers.top();
numbers.pop();
double a = numbers.top();
numbers.pop();
numbers.push(apply_operation(a, b, op));
}
if (!operators.empty()) {
operators.pop();
open_parentheses_count--;
} else {
// TODO: fix this with the Teensy.
// throw std::runtime_error("Mismatched parentheses: Too many closing parentheses");
return 0.0;
}
} else {
while (!operators.empty() && get_precedence(operators.top()) >= get_precedence(c)) {
char op = operators.top();
operators.pop();
double b = numbers.top();
numbers.pop();
double a = numbers.top();
numbers.pop();
numbers.push(apply_operation(a, b, op));
}
operators.push(c);
}
}
}
if (reading_number) {
numbers.push(current_number);
}
if (open_parentheses_count > 0) {
// Fixme
// throw std::runtime_error("Mismatched parentheses: Too many opening parentheses");
return 0.0;
}
while (!operators.empty()) {
char op = operators.top();
operators.pop();
double b = numbers.top();
numbers.pop();
double a = numbers.top();
numbers.pop();
numbers.push(apply_operation(a, b, op));
}
if (numbers.size() != 1) {
// Fixme
// throw std::runtime_error("Invalid expression");
return 0.0;
}
return numbers.top();
}
} // namespace evox