Belle II Software development
FormulaParser< VariableConstructor > Class Template Reference

FormulaParser to parse a text formula like "a + b * c ^ d" where the separate parts can be either variables (with and without arguments) or numbers. More...

#include <FormulaParser.h>

Inheritance diagram for FormulaParser< VariableConstructor >:
FormulaParserBase

Public Types

typedef VariableConstructor::type VariableType
 Type of the return variable object.
 
typedef std::variant< VariableType, double > OutputToken
 typedef for output tokens on the stack: either a variable or a double
 
enum class  EOperator : unsigned char {
  c_noop = 0x00 ,
  c_roundBracketOpen = 0x01 ,
  c_roundBracketClose = 0x02 ,
  c_squareBracketOpen = 0x03 ,
  c_squareBracketClose = 0x04 ,
  c_plus = 0x11 ,
  c_minus = 0x12 ,
  c_multiply = 0x21 ,
  c_divide = 0x22 ,
  c_power = 0x31
}
 List of known operators. More...
 
enum class  ENumberStatus {
  c_Invalid ,
  c_Empty ,
  c_Sign ,
  c_Int ,
  c_Dot ,
  c_LeadingDot ,
  c_Float ,
  c_Exponent ,
  c_ExponentSign ,
  c_Scientific
}
 States of a string literal when checking if it is a valid number. More...
 
typedef std::variant< std::string, double > InputToken
 Input token type: an input tokein is either a string or a float variable.
 

Public Member Functions

VariableType parse (const std::string &formula)
 Parse the formula and return a varible object of the correct type.
 

Static Public Member Functions

static char operatorToChar (EOperator op) noexcept
 Convert operator code to character.
 
static double applyOperator (EOperator op, double a, double b)
 Apply operator on two values.
 
static ENumberStatus checkNumber (ENumberStatus current, char next)
 Check if a string literal with a given number status continues to be a valid number if next is appended to it.
 

Protected Member Functions

void executeOperator (EOperator op) override
 Execute the given operator by taking the operands from the stack and applying the operator to them.
 
void addVariable (const InputToken &var) override
 Add the variable to the output token stack, create it from a string or keep it as it is.
 
void processString (const std::string &formula)
 Process the given formula and store the final state.
 
void raiseError (const std::runtime_error &e)
 Format the given runtime_error with context information and rethrow a new one.
 

Static Protected Member Functions

static void assertOperatorUsable (size_t stacksize)
 Make sure we have enough operands to use an operator.
 

Protected Attributes

std::stack< OutputTokenm_outputStack
 Stack of output tokens in the reversh polish notation.
 

Private Member Functions

void addOperator (EOperator op)
 Add an operator to the internal state, convert them to reverse polish notation using the shunting yard algorithm and execute them as they become available.
 
void flushCurrentVariable ()
 Flush the currently parsed variable name and add it to the state either as variable or number.
 
void flushPendingOperators ()
 Flush all pending operators at the end of processing.
 
EOperator checkForOperator (char next)
 Check if the next character is a operator.
 

Private Attributes

bool m_lastTokenWasOperator
 Bool to check whether there were consecutive operators or variables.
 
std::istringstream m_buffer
 Buffer for the formula.
 
std::string m_currentVariableName
 collect characters into a variable name
 
ENumberStatus m_currentVariableNameNumberStatus
 State of the current variable name being a valid float literal.
 
std::stack< EOperatorm_operatorStack
 Stack of operators for the Shunting-yard algorithm.
 

Detailed Description

template<class VariableConstructor>
class Belle2::FormulaParser< VariableConstructor >

FormulaParser to parse a text formula like "a + b * c ^ d" where the separate parts can be either variables (with and without arguments) or numbers.

The output can be configured by providing a custom VariableConstructor which creates the desired type of output variables. This VariableConstructor object needs to have

  1. a member type type specifying the desired type of the output object
  2. overloads for the call operator to create such objects from strings, doubles and to combine variables and doubles with a given EOperator. The necessary overloads are
    • type operator()(const std::string &name)
    • type operator()(double value)
    • type operator()(EOperator op, const type& a, const type& b)
    • type operator()(EOperator op, double a, const type &b)
    • type operator()(EOperator op, const type &a, double b)
See also
StringFormulaConstructor for an example

Definition at line 134 of file FormulaParser.h.

Member Typedef Documentation

◆ InputToken

typedef std::variant<std::string, double> InputToken
inherited

Input token type: an input tokein is either a string or a float variable.

Definition at line 59 of file FormulaParser.h.

◆ OutputToken

typedef std::variant<VariableType, double> OutputToken

typedef for output tokens on the stack: either a variable or a double

Definition at line 139 of file FormulaParser.h.

◆ VariableType

typedef VariableConstructor::type VariableType

Type of the return variable object.

Definition at line 137 of file FormulaParser.h.

Member Enumeration Documentation

◆ ENumberStatus

enum class ENumberStatus
stronginherited

States of a string literal when checking if it is a valid number.

Enumerator
c_Invalid 

Not a valid number.

c_Empty 

Empty string.

c_Sign 

Leading sign.

c_Int 

[leading sign] + digits

c_Dot 

[leading sign] + digits + dot

c_LeadingDot 

leading dot without preceding digits

c_Float 

[leading sign] + [digits] + dot + digits

c_Exponent 

[float] + E or e

c_ExponentSign 

exponent followed by plus or minus

c_Scientific 

exponent followed by sign and digits

Definition at line 45 of file FormulaParser.h.

45 {
46 c_Invalid,
47 c_Empty,
48 c_Sign,
49 c_Int,
50 c_Dot,
52 c_Float,
56 };
@ c_LeadingDot
leading dot without preceding digits
@ c_Float
[leading sign] + [digits] + dot + digits
@ c_Scientific
exponent followed by sign and digits
@ c_Dot
[leading sign] + digits + dot
@ c_ExponentSign
exponent followed by plus or minus

◆ EOperator

enum class EOperator : unsigned char
stronginherited

List of known operators.

The second word encodes the operator precedence

Enumerator
c_noop 

No operation.

c_roundBracketOpen 

Open round bracket.

c_roundBracketClose 

Close round bracket.

c_squareBracketOpen 

Open square bracket.

c_squareBracketClose 

Close square bracket.

c_plus 

Addition.

c_minus 

Subtraction.

c_multiply 

Multiply.

c_divide 

Division.

c_power 

Exponentation.

Definition at line 31 of file FormulaParser.h.

31 : unsigned char {
32 c_noop = 0x00,
33 c_roundBracketOpen = 0x01,
34 c_roundBracketClose = 0x02,
35 c_squareBracketOpen = 0x03,
37 c_plus = 0x11,
38 c_minus = 0x12,
39 c_multiply = 0x21,
40 c_divide = 0x22,
41 c_power = 0x31
42 };
@ c_roundBracketClose
Close round bracket.
@ c_roundBracketOpen
Open round bracket.
@ c_squareBracketOpen
Open square bracket.
@ c_squareBracketClose
Close square bracket.

Member Function Documentation

◆ addVariable()

void addVariable ( const InputToken var)
inlineoverrideprotectedvirtual

Add the variable to the output token stack, create it from a string or keep it as it is.

Implements FormulaParserBase.

Definition at line 186 of file FormulaParser.h.

187 {
188 m_outputStack.push(std::visit(Utils::VisitOverload {
189 // if the variable is a string its an identifier and we have to construct a variable from it
190 [](const std::string & s) -> OutputToken { return VariableConstructor()(s); },
191 // otherwise keep as is
192 [](auto s) -> OutputToken { return s; }
193 }, var));
194 }
std::variant< VariableType, double > OutputToken
typedef for output tokens on the stack: either a variable or a double
std::stack< OutputToken > m_outputStack
Stack of output tokens in the reversh polish notation.

◆ executeOperator()

void executeOperator ( EOperator  op)
inlineoverrideprotectedvirtual

Execute the given operator by taking the operands from the stack and applying the operator to them.

Implements FormulaParserBase.

Definition at line 168 of file FormulaParser.h.

169 {
171 // so far all a binary operators
172 // cppcheck-suppress unreadVariable; used in lambda below
173 OutputToken op2 = m_outputStack.top(); m_outputStack.pop();
174 // cppcheck-suppress unreadVariable; used in lambda below
175 OutputToken op1 = m_outputStack.top(); m_outputStack.pop();
176 // and apply ...
177 m_outputStack.push(std::visit(Utils::VisitOverload {
178 // eagerly apply operations if both operands are numbers
179 [op](double a, double b) -> OutputToken { return OutputToken(applyOperator(op, a, b)); },
180 // otherwise defer to variable constructor
181 [op](auto a, auto b) -> OutputToken { return VariableConstructor()(op, a, b); },
182 }, op1, op2));
183 }
static double applyOperator(EOperator op, double a, double b)
Apply operator on two values.
static void assertOperatorUsable(size_t stacksize)
Make sure we have enough operands to use an operator.

◆ parse()

VariableType parse ( const std::string &  formula)
inline

Parse the formula and return a varible object of the correct type.

Throws std::runtime_error if there is a problem with parsing.

Definition at line 144 of file FormulaParser.h.

145 {
146 try {
147 // clear stacks
148 std::stack<OutputToken>().swap(m_outputStack);
149 // process
150 processString(formula);
151 // sanity checks
152 if (m_outputStack.empty())
153 throw std::runtime_error("empty string");
154 if (m_outputStack.size() != 1)
155 throw std::runtime_error("could not parse, stack size not 1, probably a bug, please report");
156 // so return the object
157 return std::visit(Utils::VisitOverload{
158 [](const VariableType & v) -> VariableType {return v;},
159 [](double d) -> VariableType { return VariableConstructor()(d); }
160 }, m_outputStack.top());
161 } catch (std::runtime_error& e) {
162 // add context to error
163 raiseError(e);
164 }
165 }
VariableConstructor::type VariableType
Type of the return variable object.
void processString(const std::string &formula)
Process the given formula and store the final state.
void raiseError(const std::runtime_error &e)
Format the given runtime_error with context information and rethrow a new one.

Member Data Documentation

◆ m_buffer

std::istringstream m_buffer
privateinherited

Buffer for the formula.

Definition at line 103 of file FormulaParser.h.

◆ m_currentVariableName

std::string m_currentVariableName
privateinherited

collect characters into a variable name

Definition at line 105 of file FormulaParser.h.

◆ m_currentVariableNameNumberStatus

ENumberStatus m_currentVariableNameNumberStatus
privateinherited

State of the current variable name being a valid float literal.

Definition at line 107 of file FormulaParser.h.

◆ m_lastTokenWasOperator

bool m_lastTokenWasOperator
privateinherited

Bool to check whether there were consecutive operators or variables.

Definition at line 101 of file FormulaParser.h.

◆ m_operatorStack

std::stack<EOperator> m_operatorStack
privateinherited

Stack of operators for the Shunting-yard algorithm.

Definition at line 109 of file FormulaParser.h.

◆ m_outputStack

std::stack<OutputToken> m_outputStack
protected

Stack of output tokens in the reversh polish notation.

Definition at line 197 of file FormulaParser.h.


The documentation for this class was generated from the following file: