//
// File: hzNumexp.h
//
// Legal Notice: This file is part of the HadronZoo C++ Class Library.
//
// Copyright 2025 HadronZoo Project (http://www.hadronzoo.com)
//
// The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free
// Software Foundation, either version 3 of the License, or any later version.
//
// The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses.
//
//
// This package provides a means of evaluating arithmetic (numerical) expressions. An expression as a minimum, has a single term but otherwise
// has the general form of 'term operator remainder-of-expression' (effectively term-operator-term). In the single term case, evaluation of an
// expression is done by evaluating the term and returning the result. In all other cases evaluation of an expression is done by evaluating the
// first term, then recursing to evaluate the remainder-of-expression as though it were just a second term, and then applying the operator to
// the to the two evaluations and returning the result.
//
// Note that only binary operators can be applied to two terms. Unary operators are applied directly to the terms as part of term evaluation.
//
// Five classes are used as follows:-
//
// 1) hzNumexpTerm This is the 'term' and is the base class for two types of term as follows:-
//
// a) hzNumexpValue This is fixed value of any legal data type.
//
// b) hzNumexpForm By having this as a derivative of hzNumexpTerm is what enables expressions to be built in tree form. It is comprised
// of a single binary operator and a pair of operands which can be themselves hzNumexpForm instances.
//
// 2) hzNumexp This is the class that parses the expression.
//
#ifndef hzNumexp_h
#define hzNumexp_h
/*
** Other includes and re-emptive class defs
*/
#include "hzTokens.h"
/*
** Enumerated operators
*/
enum hzUnary
{
// Category: Expression
//
// Unary operators
UOP_NULL, // No operator
UOP_NOT, // ! reverse bool
UOP_COMP // ~ apply one's compliment
} ;
enum hzOperator
{
// Category: Expression
//
// Binary operators
OP_NULL, // No operator
OP_ASSIGN, // =
OP_EQUAL, // ==
OP_GT, // >
OP_LT, // <
OP_GTEQ, // >=
OP_LTEQ, // <=
OP_PLUS, // +
OP_MINUS, // -
OP_MULT, // *
OP_DIVIDE, // /
OP_POWER, // ^
OP_AND, // &&
OP_OR // ||
} ;
class hzNumexpTerm
{
// Category: Expression
//
// Base class unifying the three primary entities of constants, references and formulae
public:
virtual void SetUnaryOp (hzUnary uop) = 0 ;
virtual double Evaluate (void) = 0 ;
} ;
class hzNumexpValue : public hzNumexpTerm
{
// Category: Expression
//
// The hzNumexpValue class is a value of any legal HadronZoo type
protected:
double m_Atom ; // Result of term eveluation
hzUnary m_eUnary ; // Unary operator to apply to the result (if applicable)
public:
hzNumexpValue (void) {}
~hzNumexpValue (void) {}
void operator= (double v) { m_Atom = v ; }
void SetUnaryOp (hzUnary eUOP) { m_eUnary = eUOP ; }
double Evaluate (void) { return m_Atom ; }
} ;
/*
** The hzNumexpForm class provides the method of parenthesis
*/
class hzNumexpForm : public hzNumexpTerm
{
// Category: Expression
//
// The hzNumexpForm class provides the method of parenthesis by allowing two operands to be tied to a binary operator. The operands
// can themselves be formulae and so any expression can be represented as a series of hzNumexpForm instance. Any unary operations
// are to be applied to the formula as a whole and not to the individual operands.
protected:
double m_Result ; // Result of expression evaluation
hzNumexpTerm* m_pA ; // First term in numeric expression
hzNumexpTerm* m_pB ; // Second term in numeric expression
hzUnary m_eUnary ; // Unary operator to apply to the result (if applicable)
hzOperator m_eBinary ; // Operator to apply to the two terms
public:
hzNumexpForm (void) {}
~hzNumexpForm (void) {}
// These called by hzNumexp::Parse()
void SetUnaryOp (hzUnary uop) { m_eUnary = uop ; }
void SetOperator (hzOperator bOp) { m_eBinary = bOp ; }
bool AddOperand (hzNumexpTerm* pOperand)
{
if (!m_pA)
{ m_pA = pOperand ; return true ; }
if (!m_pB)
{ m_pB = pOperand ; return true ; }
return false ;
}
double Evaluate (void) ;
} ;
class hzNumexp
{
// Category: Expression
//
// The hzNumexp class can now evaluate an unlimited tree of constants, variables and expressions in parenthesis.
protected:
hzVect<hzToken> m_Tokens ; // Tokens of numeric expression
hzNumexpTerm* m_pRoot ; // Expression root
hzChain m_Error ; // Error reporting
double m_Default ; // Default value
uint32_t m_nParLevel ; // Current level in expression tree
uint32_t m_tokIter ; // Token iterator
//uint32_t _ProcessReference (void) ;
public:
hzNumexp (void)
{
m_pRoot = 0 ;
m_nParLevel = 0 ;
}
~hzNumexp (void) {}
hzChain& Show (void) { return m_Error ; }
double Evaluate (void) ;
hzEcode Parse (const char* pExpression) ;
hzNumexpTerm* Parse (void) ;
} ;
#endif // hzNumexp_h