diff --git a/src/include/PFunctionAst.h b/src/include/PFunctionAst.h new file mode 100644 index 000000000..af09a3fb8 --- /dev/null +++ b/src/include/PFunctionAst.h @@ -0,0 +1,306 @@ +/*************************************************************************** + + PFunctionAst.h + + 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-2026 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_H_ +#define _PFUNCTIONAST_H_ + +#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_H_