/*************************************************************************** PFunctionAst.hpp Author: Andreas Suter e-mail: andreas.suter@psi.ch Abstract Syntax Tree (AST) definitions for Spirit X3 parser. Migrated from Qi to X3 for improved compile times and cleaner syntax. ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2025 by Andreas Suter * * andreas.suter@psi.ch * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _PFUNCTIONAST_HPP_ #define _PFUNCTIONAST_HPP_ #include #include #include #include #include #include namespace musrfit { namespace ast { /////////////////////////////////////////////////////////////////////////// /** * @brief Abstract Syntax Tree (AST) definitions for the function parser. * * This namespace defines the complete AST structure used to represent * parsed function expressions. The AST is built using Boost.Variant for * type-safe unions and Boost.Spirit X3's automatic AST generation from * grammar rules. * * The AST supports: * - Arithmetic operations: +, -, *, / * - Mathematical functions: cos, sin, tan, exp, log, sqrt, pow, etc. * - Constants: PI, GAMMA_MU, field (B), energy (EN), temperature (T#) * - Parameter references: PAR#, -PAR# * - Map references: MAP# * - Function labels: FUN# * - Expression evaluation with proper precedence */ /////////////////////////////////////////////////////////////////////////// /** * @brief Enumeration of arithmetic operators. * * These tokens represent the fundamental arithmetic operations supported * by the expression evaluator. */ enum optoken { op_plus, ///< Addition operator (+) op_minus, ///< Subtraction operator (-) op_times, ///< Multiplication operator (*) op_divide, ///< Division operator (/) }; /** * @brief Enumeration of supported mathematical functions. * * These function identifiers map to standard mathematical operations * evaluated during the semantic analysis phase. */ enum funid { fun_cos, ///< Cosine function fun_sin, ///< Sine function fun_tan, ///< Tangent function fun_cosh, ///< Hyperbolic cosine function fun_sinh, ///< Hyperbolic sine function fun_tanh, ///< Hyperbolic tangent function fun_acos, ///< Arccosine function fun_asin, ///< Arcsine function fun_atan, ///< Arctangent function fun_acosh, ///< Inverse hyperbolic cosine function fun_asinh, ///< Inverse hyperbolic sine function fun_atanh, ///< Inverse hyperbolic tangent function fun_log, ///< Base-10 logarithm function fun_ln, ///< Natural logarithm function fun_exp, ///< Exponential function fun_sqrt ///< Square root function }; /** * @brief Represents an empty/null AST node. * * Used as a placeholder in variant types where no value is present. */ struct nil {}; // Forward declarations for recursive AST structures struct expression; struct function_call; struct power_call; /** * @brief Represents a constant value in an expression. * * Constants can be: * - Mathematical constants: PI, GAMMA_MU * - Metadata values: B (field), EN (energy), T# (temperature) */ struct constant { /** * @brief Enumeration of constant types. */ enum type { pi, ///< Mathematical constant π (3.14159...) gamma_mu, ///< Muon gyromagnetic ratio constant field, ///< Magnetic field from experimental data (B or -B) energy, ///< Energy from experimental data (EN or -EN) temp ///< Temperature from experimental data (T# or -T#) }; type const_type; ///< The type of constant bool sign; ///< Sign flag: false for positive, true for negative int index; ///< Index for temperature (T0, T1, T2, ...) }; /** * @brief Represents a parameter reference in an expression. * * Parameters are fit parameters referenced as PAR# or -PAR#, * where # is the parameter number (1-based). */ struct parameter { int number; ///< Parameter number (extracted from PAR#) bool sign; ///< Sign flag: false for PAR#, true for -PAR# }; /** * @brief Represents a map reference in an expression. * * Maps provide indirect parameter references: MAP# or -MAP# * references the map vector at index #-1, which then indexes * into the parameter vector. */ struct map_ref { int number; ///< Map number (extracted from MAP#) bool sign; ///< Sign flag: false for MAP#, true for -MAP# }; /** * @brief Variant type representing any operand in an expression. * * An operand can be a literal number, constant, parameter, map reference, * function call, power operation, or parenthesized expression. The variant * uses recursive_wrapper for types that contain expressions to handle * recursive grammar structures. */ typedef boost::variant< nil ///< Empty placeholder , double ///< Numeric literal , constant ///< Constant value , parameter ///< Parameter reference , map_ref ///< Map reference , boost::recursive_wrapper ///< Function call (recursive) , boost::recursive_wrapper ///< Power operation (recursive) , boost::recursive_wrapper ///< Parenthesized expression (recursive) > operand; /** * @brief Represents a binary operation with an operator and right operand. * * Used in expression chains where the left operand is the accumulated * result from previous operations. */ struct operation { optoken operator_; ///< The binary operator (+, -, *, /) operand operand_; ///< The right-hand operand }; /** * @brief Represents a complete expression with operator precedence. * * Expressions are built as a first operand followed by a sequence of * operations. This structure naturally encodes operator precedence as * determined by the grammar rules. */ struct expression { operand first; ///< The first operand in the expression std::list rest; ///< Sequence of operations applied left-to-right }; /** * @brief Represents a function call with a single argument. * * Examples: COS(PAR1), SQRT(B), EXP(-PAR2 * T0) */ struct function_call { funid func_id; ///< The function identifier expression arg; ///< The argument expression }; /** * @brief Represents a power operation. * * Syntax: POW(base, exponent) * Both base and exponent are full expressions. */ struct power_call { expression base; ///< The base expression expression pow; ///< The exponent expression }; /** * @brief Represents an assignment statement. * * Syntax: FUN# = expression * Assigns the result of evaluating the right-hand expression to a * function label. */ struct assignment { int func_number; ///< Function number (extracted from FUN#) expression rhs; ///< The right-hand side expression to evaluate }; /** * @brief Stream output operator for nil nodes (debugging support). * @param out the output stream * @return the output stream for chaining */ inline std::ostream& operator<<(std::ostream& out, nil) { out << std::string("nil"); return out; } }} // Boost.Fusion adaptations to make structures compatible with X3 attribute propagation BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::constant, (musrfit::ast::constant::type, const_type) (bool, sign) (int, index) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::parameter, (int, number) (bool, sign) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::map_ref, (int, number) (bool, sign) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::operation, (musrfit::ast::optoken, operator_) (musrfit::ast::operand, operand_) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::expression, (musrfit::ast::operand, first) (std::list, rest) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::function_call, (musrfit::ast::funid, func_id) (musrfit::ast::expression, arg) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::power_call, (musrfit::ast::expression, base) (musrfit::ast::expression, pow) ) BOOST_FUSION_ADAPT_STRUCT( musrfit::ast::assignment, (int, func_number) (musrfit::ast::expression, rhs) ) #endif // _PFUNCTIONAST_HPP_