11 #include <framework/utilities/FormulaParser.h>
24 case EOperator::c_noop:
return ' ';
25 case EOperator::c_plus:
return '+';
26 case EOperator::c_minus:
return '-';
27 case EOperator::c_multiply:
return '*';
28 case EOperator::c_divide:
return '/';
29 case EOperator::c_power:
return '^';
30 case EOperator::c_roundBracketOpen:
return '(';
31 case EOperator::c_roundBracketClose:
return ')';
32 case EOperator::c_squareBracketOpen:
return '[';
33 case EOperator::c_squareBracketClose:
return ']';
46 default:
throw std::runtime_error(std::string(
"Cannot apply operator ") +
operatorToChar(op));
54 case ENumberStatus::c_Invalid:
56 return ENumberStatus::c_Invalid;
57 case ENumberStatus::c_Empty:
59 if (std::isdigit(next))
return ENumberStatus::c_Int;
60 if (next ==
'.')
return ENumberStatus::c_LeadingDot;
61 if (next ==
'+' or next ==
'-')
return ENumberStatus::c_Sign;
63 return ENumberStatus::c_Invalid;
64 case ENumberStatus::c_Sign:
66 if (std::isdigit(next))
return ENumberStatus::c_Int;
67 if (next ==
'.')
return ENumberStatus::c_Dot;
68 return ENumberStatus::c_Invalid;
69 case ENumberStatus::c_Int:
72 if (std::isdigit(next))
return ENumberStatus::c_Int;
73 if (next ==
'.')
return ENumberStatus::c_Dot;
74 if (next ==
'E' or next ==
'e')
return ENumberStatus::c_Exponent;
75 return ENumberStatus::c_Invalid;
76 case ENumberStatus::c_Dot:
78 if (std::isdigit(next))
return ENumberStatus::c_Float;
79 if (next ==
'E' or next ==
'e')
return ENumberStatus::c_Exponent;
80 return ENumberStatus::c_Invalid;
81 case ENumberStatus::c_LeadingDot:
83 if (std::isdigit(next))
return ENumberStatus::c_Float;
84 return ENumberStatus::c_Invalid;
86 case ENumberStatus::c_Float:
87 if (std::isdigit(next))
return ENumberStatus::c_Float;
88 if (next ==
'E' or next ==
'e')
return ENumberStatus::c_Exponent;
89 return ENumberStatus::c_Invalid;
90 case ENumberStatus::c_Exponent:
92 if (std::isdigit(next))
return ENumberStatus::c_Scientific;
93 if (next ==
'+' or next ==
'-')
return ENumberStatus::c_ExponentSign;
94 return ENumberStatus::c_Invalid;
95 case ENumberStatus::c_ExponentSign:
96 case ENumberStatus::c_Scientific:
98 if (std::isdigit(next))
return ENumberStatus::c_Scientific;
99 return ENumberStatus::c_Invalid;
101 return ENumberStatus::c_Invalid;
108 throw std::runtime_error(
"could not parse, stack of operands empty. Please report, this is most likely a bug");
110 throw std::runtime_error(
"Missing operand");
131 if (tok == wrong)
throw std::runtime_error(
"wrong type of closing bracket");
132 if (tok == correct)
return;
136 throw std::runtime_error(
"unmatched bracket");
145 int op_precedence = (int)op >> 4;
150 int tok_precedence = (int)tok >> 4;
155 if (tok_precedence < op_precedence or (tok_precedence == op_precedence and tok_right))
break;
170 throw std::runtime_error(
"missing closing bracket");
195 if (next ==
'+' or next ==
'-')
199 auto isvalid = checkNumber(m_currentVariableNameNumberStatus, next);
200 if (isvalid != ENumberStatus::c_Invalid and checkNumber(isvalid, m_buffer.peek()) != ENumberStatus::c_Invalid) {
202 return EOperator::c_noop;
204 if (next ==
'+')
return EOperator::c_plus;
205 if (next ==
'-')
return EOperator::c_minus;
207 if (next ==
'/')
return EOperator::c_divide;
208 if (next ==
'^')
return EOperator::c_power;
213 if (m_buffer.peek() ==
'*') {
215 return EOperator::c_power;
218 return EOperator::c_multiply;
220 if (next ==
'(')
return EOperator::c_roundBracketOpen;
221 if (next ==
')')
return EOperator::c_roundBracketClose;
222 if (next ==
'[')
return EOperator::c_squareBracketOpen;
223 if (next ==
']')
return EOperator::c_squareBracketClose;
225 return EOperator::c_noop;
231 m_buffer = std::istringstream(formula);
242 for (
char next;
m_buffer.get(next);) {
248 if (next ==
'(') ++nestlevel;
249 if (next ==
')') --nestlevel;
277 if (next ==
' ' or next ==
'\n' or next ==
'\t' or next ==
'\r') {
291 if (nestlevel > 0)
throw std::runtime_error(
"unterminated variable arguments");
300 std::ostringstream message;
304 if (pos == -1) pos =
m_buffer.str().size() + 1;
306 message <<
"Error parsing formula at character " << pos <<
": " << e.what() << std::endl;
308 std::istringstream errbuff(
m_buffer.str());
310 bool arrowShown{
false};
311 for (std::string line; std::getline(errbuff, line);) {
313 message <<
" " << line << std::endl;
315 auto curpos = errbuff.tellg();
317 if (!arrowShown && (curpos == -1 || curpos >= pos)) {
319 for (
long i = lastpos - 1; i < pos; ++i) message <<
"-";
320 message <<
"^" << std::endl;
326 throw std::runtime_error(message.str());