Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ A flexible and extensible C++ library for parsing and evaluating mathematical ex
- Parentheses and operator precedence
- Floating-point number support
- Easy to add new operators, functions and constans
- Convertation to RPN and it's evaluation
- Easy to add and use variables

## Quick Start

Expand All @@ -28,7 +28,11 @@ int main() {
parser.registerOperator("max", parser::Operator{
parser::Operator::Type::FUNCTION,
4, false, 2,
[](auto args) { return std::max(args[0], args[1]); },
[&](auto args) {
double left = parser.tokenToDouble(args[0]); // this function convert token to double, according of its type
double right = parser.tokenToDouble(args[1]);
return Token{MathParser::Token::Type::NUMBER, std::max(left, right)};
},
"max"
});

Expand All @@ -49,7 +53,10 @@ parser.registerOperator("log", parser::Operator{
4, // Precedence
false, // Right associativity
1, // Single argument
[](auto args) { return std::log(args[0]); },
[](auto args) {
double arg = parser.tokenToDouble(args[0]);
return MathParser::Token{MathParser::Token::Type::NUMBER, std::log(arg)};
}, // Evaluating function
"log" // Function name
});
```
Expand Down
38 changes: 34 additions & 4 deletions include/mathparser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,34 @@
#include <functional>
#include <cmath>
#include <map>
#include <variant>
#include <stdexcept>

class MathParser {
public:
using EvaluateFunc = std::function<double(const std::vector<double>&)>;
struct Token {
enum class Type {
OPERATOR,
NUMBER,
VARIABLE,
CONSTANT
};
Type type;
std::variant<double, std::string> value;

bool operator<(const Token& other) const {
if (type != other.type)
return static_cast<int>(type) < static_cast<int>(other.type);

switch(type) {
case Type::NUMBER:
return std::get<double>(value) < std::get<double>(other.value);
default:
return std::get<std::string>(value) < std::get<std::string>(other.value);
}
}
};
using EvaluateFunc = std::function<Token(const std::vector<Token>&)>;
struct Operator {
enum class Type {
UNARY,
Expand All @@ -23,24 +47,30 @@ class MathParser {
int operandCount;
EvaluateFunc evaluate;
std::string symbol;
};
};

private:
std::unordered_map<std::string, Operator> operators;
std::map<std::string, double> constants;
std::map<std::string, double> variables;
void init();

bool isOperator(const std::string& symbol);
bool isOperator(char symbol);

bool isConstant(const std::string& symbol);


double evaluateRPN(const std::vector<Token>& RPN); //evaluate Reverse Polish notation
std::vector<Token> toRPN(const std::string& expression); //make Reverse Polish notation

public:
MathParser();
~MathParser() = default;

void registerOperator(const std::string& symbol, Operator op);
void registerConstant(const std::string& symbol, double value);
double evaluate(const std::string& expression);
double evaluateRPN(const std::vector<std::string>& RPN); //evaluate Reverse Polish notation
std::vector<std::string> toRPN(const std::string& expression); //make Reverse Polish notation
double tokenToDouble(const Token& token);
double getVariableValue(const std::string& varName);
};
10 changes: 9 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
int main() {
#include "mathparser.hpp"
#include <iostream>

int main() {
MathParser math;
std::cout<<math.evaluate("x=5")<<'\n';
std::cout<<math.evaluate("y=7")<<'\n';
std::cout<<math.evaluate("x = x+y+1")<<'\n';
std::cout<<math.evaluate("variable = x - y")<<'\n';
std::cout<<math.getVariableValue("variable");
return 0;
}
Loading