philsupertramp/game-math
Loading...
Searching...
No Matches
EquationParser.h
Go to the documentation of this file.
1#pragma once
2
3#include <utility>
4
5#include "MathNode.h"
6#include "Operand.h"
7#include "Operator.h"
8
9
15{
17 std::string processString;
18
19
21 bool prevWasOperator = true;
23 bool nextIsNegative = false;
25 std::vector<std::string> operatorStack;
27 std::vector<std::shared_ptr<MathNode>> operandStack;
28
29public:
31 std::vector<std::shared_ptr<Symbolic>> symbols;
32
36 explicit EquationParser(std::string in)
37 : processString(std::move(in)) { }
38
45 static std::vector<std::shared_ptr<Symbolic>> buildSymbolSuperSet(
46 const std::vector<std::shared_ptr<Symbolic>>& a, const std::vector<std::shared_ptr<Symbolic>>& b) {
47 std::vector<std::shared_ptr<Symbolic>> out = a;
48 auto testIsInContainer = [&out](const std::shared_ptr<Symbolic>& sym) {
49 for(const auto& elem : out) {
50 if(bool(strcmp(elem->value, sym->value) == 0) && elem->isNegative == sym->isNegative) return true;
51 }
52 return false;
53 };
54
55 size_t numElements = out.size();
56 for(const auto& i : b) {
57 if(!testIsInContainer(i)) {
58 out.push_back(i);
59 numElements++;
60 }
61 }
62
63 return out;
64 }
65
73 std::shared_ptr<MathNode> createAST();
74
80 static std::shared_ptr<Operator> GetOperator(const std::string& valString) {
81 if(valString.empty()) { return {}; }
82 if(valString.size() > 1) { return GetFunction(valString); }
83 switch(int(strip(valString).c_str()[0])) {
84 case int(OperatorValue::VALUE_MULTIPLICATION): return GenerateOperator(OperatorType::TYPE_MULTIPLICATION);
85 case int(OperatorValue::VALUE_DIVISION): return GenerateOperator(OperatorType::TYPE_DIVISION);
86 case int(OperatorValue::VALUE_ADDITION): return GenerateOperator(OperatorType::TYPE_ADDITION);
87 case int(OperatorValue::VALUE_SUBTRACTION): return GenerateOperator(OperatorType::TYPE_SUBTRACTION);
88 case int(OperatorValue::VALUE_POWER): return GenerateOperator(OperatorType::TYPE_POWER);
89 case int(OperatorValue::VALUE_PARENTHESES_OPEN): return GenerateOperator(OperatorType::TYPE_PARENTHESES_OPEN);
90 case int(OperatorValue::VALUE_PARENTHESES_CLOSE): return GenerateOperator(OperatorType::TYPE_PARENTHESES_CLOSE);
91 }
92 return {};
93 }
94
95private:
101 bool parseSequence(const std::string& c) {
102 std::string copy = c;
103 if(isNumber(copy)) {
104 auto sym = std::make_shared<Number>(copy);
105 sym->isNegative = nextIsNegative;
106 nextIsNegative = false;
107 operandStack.push_back(sym);
108 } else if(isConstant(copy)) {
109 auto sym = DefaultSymbols[copy];
110 sym->isNegative = nextIsNegative;
111 nextIsNegative = false;
112 operandStack.push_back(sym);
113 } else if(isSymbol(copy)) {
114 auto symbol = std::make_shared<Symbolic>(copy);
115 symbol->isNegative = nextIsNegative;
116 nextIsNegative = false;
117 operandStack.push_back(symbol);
118 if(!hasSymbol(symbols, symbol)) symbols.push_back(symbol);
119 } else if(isParenthesesOpen(copy) || isFunction(copy)) {
120 operatorStack.push_back(copy);
121 } else if(isOperator(copy)) {
122 auto currentOp = GetOperator(copy);
123 if(prevWasOperator && currentOp->value[0] == '-') {
125 } else {
126 if(currentOp->value[0] == '-') {
127 currentOp = GetOperator("+");
128 copy = "+";
130 }
132 operatorStack.push_back(copy);
133 }
134 } else if(isParenthesesClose(copy)) {
136 } else if(isAny(copy)) {
137 // ignore
138 } else {
139 // error
140 std::cerr << "Error detecting character " << copy << std::endl;
141 return false;
142 }
144 return true;
145 }
146
152 static std::shared_ptr<Function> GetFunction(const std::string& valString) {
153 auto elem = DefaultFunctions.find(valString);
154 return (elem != DefaultFunctions.end()) ? elem->second : nullptr;
155 }
156
162 std::vector<std::string> splitFunctionsOrElementwise(const std::string& in) {
163 std::vector<std::string> out;
164 auto eq = in;
165
166 std::vector<std::string> functionNames;
167 functionNames.reserve(DefaultFunctions.size());
168 for(const auto& elem : DefaultFunctions) { functionNames.push_back(elem.first); }
169 auto res = extractObjects(eq, functionNames);
170 out.insert(out.end(), res.begin(), res.end());
171
172 std::vector<std::string> constantNames;
173 constantNames.reserve(DefaultSymbols.size());
174 for(const auto& elem : DefaultSymbols) { constantNames.push_back(elem.first); }
175 res = extractObjects(eq, constantNames);
176 out.insert(out.end(), res.begin(), res.end());
177
178 if(!eq.empty()) {
179 auto remainingPart = split_by_regex(eq, GetRegex(MathNodeType::NodeType_Operator_or_Parentheses));
180 out.insert(out.end(), remainingPart.begin(), remainingPart.end());
181 }
182 return out;
183 }
184
191 std::vector<std::string> splitEquation(const std::string& eqString);
192
198 static bool isNumber(const std::string& in) {
199 static auto numberRegex = GetRegex(MathNodeType::NodeType_Numeric);
200 std::cmatch m;
201 return std::regex_match(in.c_str(), m, numberRegex);
202 };
208 static bool isSymbol(const std::string& in) {
209 static auto symbolRegex = GetRegex(MathNodeType::NodeType_Symbolic);
210 std::cmatch m;
211 return std::regex_match(in.c_str(), m, symbolRegex);
212 };
218 static bool isOperator(const std::string& in) {
219 static auto operatorRegex = GetRegex(MathNodeType::NodeType_Operator);
220 std::cmatch m;
221 return std::regex_match(in.c_str(), m, operatorRegex);
222 };
228 static bool isAny(const std::string& in) {
229 static auto anyRegex = GetRegex(MathNodeType::NodeType_Any);
230 std::cmatch m;
231 return std::regex_match(in.c_str(), m, anyRegex);
232 };
238 static bool isParenthesesOpen(const std::string& in) { return in.find('(') != std::string::npos; };
244 static bool isParenthesesClose(const std::string& in) { return in.find(')') != std::string::npos; };
245
252 static void processCurrentOP(
253 const std::shared_ptr<Operator>& currentOp,
254 std::vector<std::string>& operatorStack,
255 std::vector<std::shared_ptr<MathNode>>& operandStack);
256
262 static void
263 rearrangeStack(std::vector<std::string>& operatorStack, std::vector<std::shared_ptr<MathNode>>& operandStack);
264
265
272 std::vector<std::string> extractObjects(std::string& eq, const std::vector<std::string>& container);
273};
std::regex GetRegex(MathNodeType type)
static std::map< std::string, std::shared_ptr< Symbolic > > DefaultSymbols
Definition: Operand.h:66
bool isConstant(const std::string &in)
bool hasSymbol(const std::vector< std::shared_ptr< Symbolic > > &container, const std::shared_ptr< Symbolic > &sym)
std::shared_ptr< Operator > GenerateOperator(OperatorType type)
const std::map< std::string, std::shared_ptr< Function > > DefaultFunctions
Definition: Operator.h:161
bool isFunction(const std::string &in)
Definition: EquationParser.h:15
bool prevWasOperator
flag for parsing process
Definition: EquationParser.h:21
std::shared_ptr< MathNode > createAST()
EquationParser(std::string in)
Definition: EquationParser.h:36
static bool isParenthesesClose(const std::string &in)
Definition: EquationParser.h:244
std::vector< std::shared_ptr< Symbolic > > symbols
storage for symbols, gets cleared on EquationParser::createAST
Definition: EquationParser.h:31
static bool isAny(const std::string &in)
Definition: EquationParser.h:228
bool nextIsNegative
flag for parsing process to detect whether a node is negated
Definition: EquationParser.h:23
std::vector< std::string > splitEquation(const std::string &eqString)
std::vector< std::string > splitFunctionsOrElementwise(const std::string &in)
Definition: EquationParser.h:162
std::vector< std::string > extractObjects(std::string &eq, const std::vector< std::string > &container)
std::vector< std::string > operatorStack
operator stack object, used during parsing
Definition: EquationParser.h:25
std::string processString
equation string to parse
Definition: EquationParser.h:17
static bool isNumber(const std::string &in)
Definition: EquationParser.h:198
static std::shared_ptr< Operator > GetOperator(const std::string &valString)
Definition: EquationParser.h:80
static void rearrangeStack(std::vector< std::string > &operatorStack, std::vector< std::shared_ptr< MathNode > > &operandStack)
static std::vector< std::shared_ptr< Symbolic > > buildSymbolSuperSet(const std::vector< std::shared_ptr< Symbolic > > &a, const std::vector< std::shared_ptr< Symbolic > > &b)
Definition: EquationParser.h:45
static bool isParenthesesOpen(const std::string &in)
Definition: EquationParser.h:238
static void processCurrentOP(const std::shared_ptr< Operator > &currentOp, std::vector< std::string > &operatorStack, std::vector< std::shared_ptr< MathNode > > &operandStack)
bool parseSequence(const std::string &c)
Definition: EquationParser.h:101
static bool isOperator(const std::string &in)
Definition: EquationParser.h:218
static std::shared_ptr< Function > GetFunction(const std::string &valString)
Definition: EquationParser.h:152
static bool isSymbol(const std::string &in)
Definition: EquationParser.h:208
std::vector< std::shared_ptr< MathNode > > operandStack
operand stack object, used during parsing
Definition: EquationParser.h:27
std::vector< std::string > split_by_regex(const std::string &s, const std::regex &regex)
std::string strip(const std::string &in)
Definition: vec3.h:360