Skip to content

Commit 2a692ed

Browse files
committed
add more error handlers
1 parent 3c257cc commit 2a692ed

2 files changed

Lines changed: 45 additions & 32 deletions

File tree

include/mathparser.hpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,6 @@ class MathParser {
1919
};
2020
Type type;
2121
std::variant<double, std::string> value;
22-
23-
bool operator<(const Token& other) const {
24-
if (type != other.type)
25-
return static_cast<int>(type) < static_cast<int>(other.type);
26-
27-
switch(type) {
28-
case Type::NUMBER:
29-
return std::get<double>(value) < std::get<double>(other.value);
30-
default:
31-
return std::get<std::string>(value) < std::get<std::string>(other.value);
32-
}
33-
}
3422
};
3523
using EvaluateFunc = std::function<Token(const std::vector<Token>&)>;
3624
struct Operator {
@@ -72,6 +60,6 @@ class MathParser {
7260
double evaluate(const std::string& expression);
7361
std::vector<Token> compile(const std::string& expression);
7462
double evaluate(const std::vector<Token>& complied);
75-
double tokenToDouble(const Token& token);
63+
double tokenToDouble(const Token& token) const;
7664
double getVariableValue(const std::string& varName);
7765
};

src/mathparser.cpp

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -169,22 +169,31 @@ bool MathParser::isConstant(const std::string& symbol) {
169169
return constants.find(symbol)!=constants.end();
170170
}
171171

172-
double MathParser::tokenToDouble(const MathParser::Token& token) {
173-
switch (token.type) {
174-
case Token::Type::NUMBER:
175-
return std::get<double>(token.value);
176-
case Token::Type::CONSTANT:
177-
return constants[std::get<std::string>(token.value)];
178-
case Token::Type::VARIABLE: {
179-
const std::string& name = std::get<std::string>(token.value);
180-
if (variables.find(name) == variables.end())
181-
throw std::runtime_error("Undefined variable: " + name);
182-
return variables[name];
183-
}
184-
default:
185-
throw std::runtime_error("Cannot convert token to number");
172+
double MathParser::tokenToDouble(const MathParser::Token& token) const {
173+
switch (token.type) {
174+
case Token::Type::NUMBER:
175+
return std::get<double>(token.value);
176+
177+
case Token::Type::CONSTANT: {
178+
const auto& name = std::get<std::string>(token.value);
179+
auto it = constants.find(name);
180+
if (it == constants.end())
181+
throw std::runtime_error("Unknown constant: " + name);
182+
return it->second;
183+
}
184+
185+
case Token::Type::VARIABLE: {
186+
const auto& name = std::get<std::string>(token.value);
187+
auto it = variables.find(name);
188+
if (it == variables.end())
189+
throw std::runtime_error("Undefined variable: " + name);
190+
return it->second;
186191
}
192+
193+
default:
194+
throw std::runtime_error("Cannot convert token to number");
187195
}
196+
}
188197

189198
std::vector<MathParser::Token> MathParser::toRPN(const std::string& expression) {
190199
std::stack<Operator> opStack;
@@ -256,7 +265,10 @@ std::vector<MathParser::Token> MathParser::toRPN(const std::string& expression)
256265
std::string symbol = std::string(1,expression[i]);
257266
//if we get - before operand its unary minus
258267
if (symbol=="-" && expectOperand) symbol = "~";
259-
Operator curOp = operators[symbol];
268+
auto it = operators.find(symbol);
269+
if (it == operators.end())
270+
throw std::runtime_error("Unknown operator: " + symbol);
271+
Operator curOp = it->second;
260272
while (!opStack.empty() && opStack.top().type !=Operator::Type::BRACKET) {
261273
Operator topOp = opStack.top();
262274
if (topOp.type == Operator::Type::COMMA || topOp.type == Operator::Type::FUNCTION) break;
@@ -284,7 +296,11 @@ double MathParser::evaluate(const std::vector<Token>& compiled) {
284296
std::stack<Token> numStack;
285297
for (const Token& token: compiled) {
286298
if (token.type == Token::Type::OPERATOR) {
287-
Operator op = operators[std::get<std::string>(token.value)];
299+
const std::string& opSymbol = std::get<std::string>(token.value);
300+
auto it = operators.find(opSymbol);
301+
if (it == operators.end())
302+
throw std::runtime_error("Unknown operator: " + opSymbol);
303+
const Operator& op = it->second;
288304
std::vector<Token> operands;
289305
for (int i=0; i<op.operandCount; i++) {
290306
operands.insert(operands.begin(),numStack.top());
@@ -309,7 +325,11 @@ std::vector<MathParser::Token> MathParser::compile(const std::string& expressio
309325
std::vector<Token> compiled;
310326
for (const Token& token: RPN) {
311327
if (token.type == Token::Type::OPERATOR) {
312-
Operator op = operators[std::get<std::string>(token.value)];
328+
const std::string& opName = std::get<std::string>(token.value);
329+
auto it = operators.find(opName);
330+
if (it == operators.end())
331+
throw std::runtime_error("Unknown operator: " + opName);
332+
Operator op = it->second;
313333
if (op.type==Operator::Type::COMMA) continue;
314334
bool allConstants = true;
315335
for (int i=0; i<op.operandCount; i++) {
@@ -331,8 +351,13 @@ std::vector<MathParser::Token> MathParser::compile(const std::string& expressio
331351
}
332352
}
333353
else {
334-
if (token.type==Token::Type::CONSTANT)
335-
compiled.push_back(Token{Token::Type::NUMBER, constants[std::get<std::string>(token.value)]});
354+
if (token.type==Token::Type::CONSTANT) {
355+
const std::string& constName = std::get<std::string>(token.value);
356+
auto it = constants.find(constName);
357+
if (it == constants.end())
358+
throw std::runtime_error("Unknown constant: " + constName);
359+
compiled.push_back(Token{Token::Type::NUMBER, it->second});
360+
}
336361
else
337362
compiled.push_back(token);
338363
}

0 commit comments

Comments
 (0)