116 return empty() ?
"" : _str.substr(_start, _end - _start);
121 stator_throw() <<
"Expected " << ((token.empty()) ?
"end of expression": (
"\""+token+
"\"")) <<
" but found " << (
empty() ?
"the end of expression" :
next()) <<
"\" instead?\n" <<
parserLoc();
126 return _start == _str.size();
133 while ((_str[_start] ==
' ') && (_start < _str.size())) ++_start;
146 if (std::isdigit(_str[_start])) {
152 if (std::isalpha(_str[_start])) {
153 while ((_end < _str.size()) && std::isalpha(_str[_end]))
168 bool decimal =
false;
169 bool exponent =
false;
171 while (_end != _str.size()) {
172 if (_str[_end] ==
'.') {
173 if (!decimal && !exponent) {
182 if ((_str[_end] ==
'e') || (_str[_end] ==
'E')) {
188 if (_end == _str.size())
192 if ((_str[_end] ==
'+') || (_str[_end] ==
'-'))
195 if (_end == _str.size())
198 if (!std::isdigit(_str[_end]))
206 if (std::isdigit(_str[_end])) {
217 + std::string(_start,
' ') + std::string((_start < _end) ? _end - _start -1: 0,
'-') +
"^";
226 virtual int LBP()
const = 0;
228 virtual int NBP()
const = 0;
236 virtual int BP()
const = 0;
245 int LBP()
const {
return Op::leftBindingPower; }
247 int NBP()
const {
return detail::NBP<Op>(); }
253 virtual int LBP()
const {
return -1; }
269 template<
class Op,
int tBP>
316 std::string token =
next();
323 if (std::isdigit(token[0])) {
324 std::stringstream ss;
332 auto it = _left_operators.find(token);
333 if (it != _left_operators.end()) {
339 if ((token.size() == 1) && (std::isalpha(token[0])))
399 int maxLBP = std::numeric_limits<int>::max();
401 std::string token =
next();
404 if (token.empty())
break;
407 auto it = _right_operators.find(token);
410 if (it == _right_operators.end())
419 if ((minLBP > it->second->LBP()) || (it->second->LBP() > maxLBP))
break;
422 t = it->second->apply(t, *
this);
423 maxLBP = it->second->NBP();
440 *
this =
simplify(tokenizer.parseExpression());
443 if (!tokenizer.empty())
444 stator_throw() <<
"Parsing terminated unexpectedly early?\n" << tokenizer.parserLoc();
A CRTP helper base class which transforms the visitor interface into a call to the derived classes ap...
int LBP() const
Left binding power (Precedence of this operator)
Expr apply(Expr l, ExprTokenizer &tk) const
Takes one operand and returns the corresponding Expr.
Expr apply(Expr l, ExprTokenizer &tk) const
Takes one operand and returns the corresponding Expr.
Expr apply(Expr l, ExprTokenizer &tk) const
Takes left operand and returns the corresponding Expr, fetching the right operands from the tokenizer...
virtual int LBP() const =0
Left binding power (Precedence of this operator)
int NBP() const
Next binding power (highest precedence of the operator that this operator can be a left operand of) ...
void expect(std::string token)
std::map< std::string, shared_ptr< LeftOperatorBase > > _left_operators
int BP() const
Binding power to the right arguments of the Token.
virtual Expr apply(Expr, ExprTokenizer &) const =0
Takes left operand and returns the corresponding Expr, fetching the right operands from the tokenizer...
virtual int LBP() const
Left binding power (Precedence of this operator)
Expr parseExpression(int minLBP=0)
Main parsing entry function.
int BP() const
Binding power to the right arguments of the Token.
Expr simplify(const Expr &f)
int NBP() const
Next binding power (highest precedence of the operator that this operator can be a left operand of) ...
The generic holder/smart pointer for a runtime Abstract Syntax Tree (AST) (expression).
std::map< std::string, shared_ptr< RightOperatorBase > > _right_operators
The stator symbolic math library.
Expr parseToken()
Parses a single token (unary/prefix op, variable, or number), where precedence issues do not arise...
Implementation of expression tokenization and parsing into Expr types.
Expr apply(Expr l, ExprTokenizer &tk) const
Takes one operand and returns the corresponding Expr.
int BP() const
Binding power to the right arguments of the Token.
int BP() const
Binding power to the right arguments of the Token.
virtual Expr apply(Expr, ExprTokenizer &) const
Takes left operand and returns the corresponding Expr, fetching the right operands from the tokenizer...
std::pair< int, int > BP(const T &v)
Returns the binding powers (precedence) of binary operators.
virtual int NBP() const =0
Next binding power (highest precedence of the operator that this operator can be a left operand of) ...
Expr apply(Expr l, ExprTokenizer &tk) const
Takes one operand and returns the corresponding Expr.
ExprTokenizer(const std::string &str)