// // File: hzNumexp.cpp // // 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. //
// // Implimentation of the hzNumexp (numeric expression) class and the hzNumexpTerm classes defined in hzNumexp.h //
#include <fstream>
#include "hzTextproc.h" #include "hzProcess.h"
#include "hzNumexp.h"
/* ** hzNumexpForm Functions */
double hzNumexpForm::Evaluate (void) { // Evaluate this expression (hzNumexpForm instance) to a single atomic value. A hzNumexpForm instance is created by an expression parser when the // expression amounts to a 'term operator term' rather than only a single term. hzNumexpForm Evaluation is thus always a matter of evaluating // both terms and applying the operator. Where the terms are themselves hzNumexpForm instances, this function recurses. // // Arguments: None // Returns: Value - the numeric result
_hzfunc("hzNumexpForm::Evaluate_a") ;
double A ; // Term A double B ; // Term B
A = m_pA->Evaluate() ; B = m_pB->Evaluate() ;
switch (m_eBinary) { //case OP_ASSIGN: break ; case OP_EQUAL: m_Result = (A == B) ; break ; case OP_GT: m_Result = (A > B) ; break ; case OP_LT: m_Result = (A < B) ; break ; case OP_GTEQ: m_Result = (A >= B) ; break ; case OP_LTEQ: m_Result = (A <= B) ; break ;
case OP_PLUS: m_Result = A ; m_Result += B ; break ; case OP_MINUS: m_Result = A ; m_Result -= B ; break ; case OP_MULT: m_Result = A ; m_Result *= B ; break ; case OP_DIVIDE: m_Result = A ; m_Result /= B ; break ; //case OP_AND: m_Result = A ; m_Result &= B ; break ; //case OP_OR: m_Result = A ; m_Result |= B ; break ; }
return m_Result ; }
/* ** hzNumexp Functions */
double hzNumexp::Evaluate (void) { // Evaluate expression into single atomic value. // // Arguments: None // Returns: Value - the numeric result
_hzfunc("hzNumexp::Evaluate_b") ;
if (m_pRoot) return m_pRoot->Evaluate() ; return m_Default ; }
hzEcode hzNumexp::Parse (const char* pExp) { // Parses extression into a single operand or more generally, a tree of formulae that will evaluate to a single value. // // Arguments: 1) pExp Numeric expression // // Returns: E_SYNTAX If the expression could not be tokenized or could not be parsed. // E_OK If the expression was parsed.
_hzfunc("hzNumexp::Parse_a") ;
hzEcode rc ; // Return code
// tokenize the expression
rc = TokenizeString(m_Tokens, pExp, TOK_MO_BOOL) ; if (rc != E_OK) return E_SYNTAX ;
m_pRoot = Parse() ; if (!m_pRoot) return E_SYNTAX ;
return E_OK ; }
hzNumexpTerm* hzNumexp::Parse (void) { // convert text tokens into tree of hzNumexpForm, hzReference & hzNumexpValue // // Arguments: None // Returns: Pointer to numeric expresssion term base class instance
_hzfunc("hzIdSetExp::Parse(hzTokenlist&)") ;
hzNumexpForm* pFormula = 0 ; // Pointer to a formula hzNumexpValue* pConstant = 0 ; // Pointer to a constant hzNumexpTerm* pOperand1 = 0 ; // Pointer to term A hzNumexpTerm* pOperand2 = 0 ; // Pointer to term B hzOperator binOp = OP_NULL ; // Binary op applicable to A and B hzUnary unaOp = UOP_NULL ; // Unary op applicable to result hzToken tok ; // Current token double val ; // result value
tok = m_Tokens[m_tokIter] ;
if (!tok) { m_Error.Printf("No more tokens - returning null\n") ; return 0 ; }
/* ** Occupy first operand */
// Unary operators are permitted while expecting operand if (tok == "!") { m_Error.Printf("Setting unary for first operand\n") ; unaOp = UOP_NOT ; m_tokIter++ ; tok = m_Tokens[m_tokIter] ; if (!tok) { m_Error.Printf("Expected an operand or '(' to follow unary") ; return 0 ; } }
// Binary operators are not permitted here though if (tok == "&&" || tok == "||") { m_Error.Printf("Expected an operand or '('. Got an operator") ; return 0 ; }
if (tok == "(") { // The operand can be a formula, recurse if it is m_nParLevel++ ; m_tokIter++ ; tok = m_Tokens[m_tokIter] ; pOperand1 = Parse() ; } else { // Token is not a unary or an open bracket. We assume token is a constant m_Error.Printf("Set first operand as constant\n") ; pConstant = new hzNumexpValue() ; IsDouble(val, *tok.Value()) ; *pConstant = val ; //tok.Value() ; pOperand1 = pConstant ; m_tokIter++ ; tok = m_Tokens[m_tokIter] ; }
/* ** Obtain the operator */
if (tok.Value()) { m_Error.Printf("Processing token %s\n", *tok.Value()) ;
// we now expect an binary operator or a terminating ) if (tok == ")") { m_tokIter++ ; tok = m_Tokens[m_tokIter] ; return pOperand1 ; }
// Test for operator if (tok == "&&") { binOp = OP_AND ; m_tokIter++ ; tok = m_Tokens[m_tokIter] ; } else if (tok == "||") { binOp = OP_OR ; m_tokIter++ ; tok = m_Tokens[m_tokIter] ; } else if (tok == "(") { m_Error.Printf("Line %d: Expected an operator", tok.LineNo()) ; return 0 ; } else { // Token is not an operator and not an open or a close. We assume it is another constant and thus there is an implied AND operator.
m_Error.Printf("asserting operator as AND\n") ; binOp = OP_AND ; } }
/* ** Recurse to get second operand */
if (tok.Value()) { m_Error.Printf("Recursing for 2nd operand\n") ; m_nParLevel++ ; pOperand2 = Parse() ; m_nParLevel-- ; if (pOperand2) m_Error.Printf("Got 2nd operand\n") ; else m_Error.Printf("Got 2nd operand\n") ; }
/* ** Decide if we return a constant or a formula */
if (!pOperand1) { m_Error.Printf("returning null (no first operand)\n") ; return 0 ; } if (binOp == OP_NULL) { m_Error.Printf("returning single operand\n") ; return pOperand1 ; } if (!pOperand2) { // report syntax error m_Error.Printf("returning null (no second operand)\n") ; return 0 ; }
// Allocate a formula node m_Error.Printf("returning double operand\n") ; pFormula = new hzNumexpForm() ; pFormula->AddOperand(pOperand1) ; pFormula->AddOperand(pOperand2) ; pFormula->SetUnaryOp(unaOp) ; pFormula->SetOperator(binOp) ; return pFormula ; }