Z-Sharp/Slang/eval.cpp

153 lines
2.7 KiB
C++

// CPP program to evaluate a given expression
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <limits>
#include <stack>
#include "eval.h"
using namespace std;
float precedence(char op) {
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
return 0;
}
float applyOp(float a, float b, char op) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
}
}
// Function that returns value of
// expression after evaluation.
float evaluate(string tokens) {
float i;
stack <float> values;
stack <char> ops;
for (i = 0; i < tokens.length(); i++) {
// Current token is a whitespace,
// skip it.
if (tokens[i] == ' ')
continue;
// Current token is an opening
// brace, push it to 'ops'
else if (tokens[i] == '(')
{
ops.push(tokens[i]);
}
// Current token is a number, push
// it to stack for numbers.
else if (isdigit(tokens[i])) {
float val = 0;
bool encounteredDecimal = false;
int decPlaces = 0;
// There may be more than one
// digits in number.
while (i < tokens.length() && (isdigit(tokens[i]) || tokens[i] == '.'))
{
if (tokens[i] == '.')
{
encounteredDecimal = true;
i++;
decPlaces++;
continue;
}
if (encounteredDecimal == true)
{
val = (val)+(tokens[i] - '0') / pow(10.0f, decPlaces);
decPlaces++;
}
else
val = (val * 10) + (tokens[i] - '0');
i++;
}
values.push(val);
i--;
}
// Closing brace encountered, solve
// entire brace.
else if (tokens[i] == ')')
{
while (!ops.empty() && ops.top() != '(')
{
float val2 = values.top();
values.pop();
float val1 = values.top();
values.pop();
char op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
if (!ops.empty())
ops.pop();
}
// Current token is an operator.
else
{
while (!ops.empty() && precedence(ops.top())
>= precedence(tokens[i])) {
float val2 = values.top();
values.pop();
float val1 = values.top();
values.pop();
char op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
ops.push(tokens[i]);
}
}
// Entire expression has been parsed at this
// point, apply remaining ops to remaining
// values.
while (!ops.empty()) {
float val2 = values.top();
values.pop();
float val1 = values.top();
values.pop();
char op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
return values.top();
}
// Used to test evaluator
//int main() {
// cout << evaluate("10 + 2 * 6") << "\n";
// cout << evaluate("100 * 2 + 12") << "\n";
// cout << evaluate("100 * ( 2 + 12 )") << "\n";
// cout << evaluate("0.05*0.05");
// return 0;
//}