test spirit parser moved from classic to X3.

This commit is contained in:
2025-12-27 12:32:01 +01:00
parent 32d9970659
commit 33f9fd5845
11 changed files with 1072 additions and 1296 deletions

View File

@@ -0,0 +1,73 @@
# - spirit_fcn_test
cmake_minimum_required(VERSION 3.17)
project(spirit_fcn_test VERSION 0.1 LANGUAGES CXX)
#--- set a default build type if none was specified ---------------------------
set(default_build_type "Debug")
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif ()
#--- check for pkg-config -----------------------------------------------------
find_package(PkgConfig REQUIRED)
#--- check for ROOT -----------------------------------------------------------
find_package(ROOT 6.18 REQUIRED COMPONENTS Gui MathMore Minuit2 XMLParser)
if (ROOT_mathmore_FOUND)
execute_process(COMMAND root-config --bindir OUTPUT_VARIABLE ROOT_BINDIR)
string(STRIP ${ROOT_BINDIR} ROOT_BINDIR)
execute_process(COMMAND root-config --version OUTPUT_VARIABLE ROOT_VERSION)
string(STRIP ${ROOT_VERSION} ROOT_VERSION)
message("-- Found ROOT: ${ROOT_BINDIR} (found version: ${ROOT_VERSION})")
#---Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY)
include(${ROOT_USE_FILE})
endif (ROOT_mathmore_FOUND)
#--- check for boost ----------------------------------------------------------
find_package(Boost QUIET)
if (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
find_package(Boost REQUIRED
COMPONENTS
filesystem
)
else (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
find_package(Boost REQUIRED
COMPONENTS
system
filesystem
)
endif (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
#--- create executable --------------------------------------------------------
add_executable(spirit_fcn_test
spirit_fcn_test.cpp
PFunction.cpp
PFunctionHandler.cpp
)
#--- add include directories --------------------------------------------------
target_include_directories(spirit_fcn_test
BEFORE PRIVATE
${Boost_INCLUDE_DIR}
)
#--- link libraries -----------------------------------------------------------
target_link_libraries(spirit_fcn_test
${ROOT_LIBRARIES}
${Boost_LIBRARIES}
)
#--- installation info --------------------------------------------------------
install(
TARGETS
spirit_fcn_test
RUNTIME DESTINATION
bin
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +1,88 @@
/*************************************************************************** /***************************************************************************
PFunction.h PFunction.h - Test version (simplified, no PMetaData)
Author: Andreas Suter Author: Andreas Suter
e-mail: andreas.suter@psi.ch e-mail: andreas.suter@psi.ch
$Id$ Modernized test version using Boost.Spirit X3 and visitor pattern.
***************************************************************************/ ***************************************************************************/
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Andreas Suter * * Copyright (C) 2007-2026 by Andreas Suter *
* andreas.suter@psi.c * * andreas.suter@psi.ch *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. * * GNU General Public License for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the * * along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef _PFUNCTION_H_ #ifndef _PFUNCTION_H_
#define _PFUNCTION_H_ #define _PFUNCTION_H_
#include <vector> #include <vector>
#include <string> #include <string>
#include <boost/version.hpp> #include <boost/variant.hpp>
#if BOOST_VERSION >= 103800 #include "PFunctionAst.h"
# include <boost/spirit/include/classic_ast.hpp>
using namespace BOOST_SPIRIT_CLASSIC_NS; //----------------------------------------------------------------------------
#else /**
# include <boost/spirit/tree/ast.hpp> * \brief Test version of PFunction class - simplified without PMetaData.
using namespace boost::spirit; *
#endif * This test version uses the same X3 grammar and AST but with a simpler
* interface for testing purposes. It does not support metadata (field,
#include "PFunctionGrammar.h" * energy, temperature).
*/
//---------------------------------------------------------------------------- class PFunction {
#define OP_ADD 0 public:
#define OP_SUB 1 PFunction(const std::string& input, std::vector<double> param, std::vector<int> map, bool debug = false);
#define OP_MUL 2 virtual ~PFunction();
#define OP_DIV 3
virtual bool IsValid() { return fValid; }
#define FUN_COS 0 virtual int GetFuncNo() { return fFuncNo; }
#define FUN_SIN 1 virtual double Eval();
#define FUN_TAN 2
#define FUN_COSH 3 private:
#define FUN_SINH 4 musrfit::ast::expression fAst;
#define FUN_TANH 5 std::vector<double> fParam;
#define FUN_ACOS 6 std::vector<int> fMap;
#define FUN_ASIN 7 bool fValid;
#define FUN_ATAN 8 int fFuncNo;
#define FUN_ACOSH 9 bool fDebug;
#define FUN_ASINH 10
#define FUN_ATANH 11 // Simplified evaluation visitor (no metadata support)
#define FUN_LOG 12 class EvalVisitor : public boost::static_visitor<double> {
#define FUN_LN 13 public:
#define FUN_EXP 14 EvalVisitor(const std::vector<int>& map, const std::vector<double>& param)
: fMap(map), fParam(param) {}
//----------------------------------------------------------------------------
typedef struct func_tree_node { double operator()(const musrfit::ast::nil&) const;
int fID; ///< tag showing what tree element this is double operator()(double val) const;
int fOperatorTag; ///< tag for '+', '-', '*', '/' double operator()(const musrfit::ast::constant& c) const;
int fFunctionTag; ///< tag got "cos", "sin", ... double operator()(const musrfit::ast::parameter& p) const;
int fIvalue; ///< for parameter numbers and maps double operator()(const musrfit::ast::map_ref& m) const;
bool fSign; ///< for sign. true = '-', false = '+' double operator()(const musrfit::ast::function_call& f) const;
double fDvalue; ///< for numbers double operator()(const musrfit::ast::power_call& p) const;
vector<func_tree_node> children; ///< holding sub-tree double operator()(const musrfit::ast::expression& e) const;
} PFuncTreeNode;
private:
//---------------------------------------------------------------------------- const std::vector<int>& fMap;
class PFunction { const std::vector<double>& fParam;
public: };
PFunction(tree_parse_info<> info, vector<double> param, vector<int> map, bool debug); };
virtual ~PFunction();
#endif // _PFUNCTION_H_
virtual bool IsValid() { return fValid; }
virtual int GetFuncNo() { return fFuncNo; }
virtual double Eval();
protected:
virtual void InitNode(PFuncTreeNode &node);
virtual bool CheckParameterAndMapRange();
virtual bool CheckParameterAndMapInTree(iter_t const& i);
virtual bool SetFuncNo(iter_t const& i);
virtual bool GenerateFuncEvalTree();
virtual void FillFuncEvalTree(iter_t const& i, PFuncTreeNode &node);
virtual double EvalNode(PFuncTreeNode &node);
virtual void CleanupFuncEvalTree();
virtual void CleanupNode(PFuncTreeNode &node);
virtual long EvaluateTree(tree_parse_info<> info);
virtual long EvalTreeExpression(iter_t const& i);
virtual long PrintTree(tree_parse_info<> info);
virtual long PrintTreeExpression(iter_t const& i);
private:
tree_parse_info<> fInfo;
vector<double> fParam;
vector<int> fMap;
PFuncTreeNode fFunc;
bool fDebug;
bool fValid; ///< flag showing if the function is valid
int fFuncNo; ///< function number, i.e. FUNx with x the function number
string fFuncString;
};
#endif // _PFUNCTION_H_

View File

@@ -0,0 +1,306 @@
/***************************************************************************
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 <boost/config/warning_disable.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/optional.hpp>
#include <list>
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> ///< Function call (recursive)
, boost::recursive_wrapper<power_call> ///< Power operation (recursive)
, boost::recursive_wrapper<expression> ///< 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<operation> 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<musrfit::ast::operation>, 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_

View File

@@ -1,164 +1,196 @@
/*************************************************************************** /***************************************************************************
PFunctionGrammer.h PFunctionGrammar.h
Author: Andreas Suter Author: Andreas Suter
e-mail: andreas.suter@psi.ch e-mail: andreas.suter@psi.ch
$Id$ Header-only grammar for parsing function entries in msr-file FUNCTION blocks.
This version uses Boost.Spirit X3 in header-only mode for maximum compatibility.
***************************************************************************/
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007 by Andreas Suter * /***************************************************************************
* andreas.suter@psi.c * * 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 * * This program is free software; you can redistribute it and/or modify *
* the Free Software Foundation; either version 2 of the License, or * * it under the terms of the GNU General Public License as published by *
* (at your option) any later version. * * 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 * * This program is distributed in the hope that it will be useful, *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* GNU General Public License for more details. * * 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 * * You should have received a copy of the GNU General Public License *
* Free Software Foundation, Inc., * * along with this program; if not, write to the *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Free Software Foundation, Inc., *
***************************************************************************/ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef _PFUNCTIONGRAMMAR_H_
#define _PFUNCTIONGRAMMAR_H_ #ifndef _PFUNCTIONGRAMMAR_H_
#define _PFUNCTIONGRAMMAR_H_
#include <iostream>
using namespace std; // Check Boost version - require 1.61+ for Spirit X3
#include <boost/version.hpp>
//#define BOOST_SPIRIT_DEBUG #if BOOST_VERSION < 106100
# error "Boost version 1.61.0 or higher is required for Spirit X3. Please upgrade Boost."
#include <boost/version.hpp> #endif
#include <boost/spirit/version.hpp>
#include "PFunctionAst.h"
#if BOOST_VERSION >= 103800 #include <boost/spirit/home/x3.hpp>
# include <boost/spirit/include/classic_core.hpp>
# include <boost/spirit/include/classic_ast.hpp> namespace x3 = boost::spirit::x3;
using namespace BOOST_SPIRIT_CLASSIC_NS;
#else namespace musrfit { namespace grammar
# include <boost/spirit/core.hpp> {
# include <boost/spirit/tree/ast.hpp> using x3::int_;
using namespace boost::spirit; using x3::double_;
#endif using x3::lit;
using x3::lexeme;
typedef char const* iterator_t; using x3::attr;
typedef tree_match<iterator_t> parse_tree_match_t;
typedef parse_tree_match_t::tree_iterator iter_t; ///////////////////////////////////////////////////////////////////////////
// Symbol tables - using inline to avoid multiple definition errors
//-------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////
/**
* struct additive_op_ : x3::symbols<ast::optoken>
*/ {
struct PFunctionGrammar : public grammar<PFunctionGrammar> additive_op_()
{ {
static const int realID = 1; add("+", ast::op_plus)("-", ast::op_minus);
static const int constPiID = 2; }
static const int constGammaMuID = 3; };
static const int funLabelID = 4;
static const int parameterID = 5; inline additive_op_ additive_op;
static const int mapID = 6;
static const int functionID = 7; struct multiplicative_op_ : x3::symbols<ast::optoken>
static const int factorID = 8; {
static const int termID = 9; multiplicative_op_()
static const int expressionID = 10; {
static const int assignmentID = 11; add("*", ast::op_times)("/", ast::op_divide);
}
template <typename ScannerT> };
struct definition
{ inline multiplicative_op_ multiplicative_op;
definition(PFunctionGrammar const& /*self*/)
{ struct fun_tok_ : x3::symbols<ast::funid>
// Start grammar definition {
real = leaf_node_d[ real_p ]; fun_tok_()
{
const_pi = leaf_node_d[ str_p("PI") ]; add
("COS", ast::fun_cos)
const_gamma_mu = leaf_node_d[ str_p("GAMMA_MU") ]; ("SIN", ast::fun_sin)
("TAN", ast::fun_tan)
fun_label = leaf_node_d[ ( lexeme_d[ "FUN" >> +digit_p ] ) ]; ("COSH", ast::fun_cosh)
("SINH", ast::fun_sinh)
parameter = leaf_node_d[ ( lexeme_d[ "PAR" >> +digit_p ] ) | ("TANH", ast::fun_tanh)
( lexeme_d[ "-PAR" >> +digit_p ] ) ]; ("ACOS", ast::fun_acos)
("ASIN", ast::fun_asin)
map = leaf_node_d[ ( lexeme_d[ "MAP" >> +digit_p ] ) ]; ("ATAN", ast::fun_atan)
("ACOSH", ast::fun_acosh)
function = lexeme_d[ root_node_d[ str_p("COS") ] >> ch_p('(') ] >> expression >> ch_p(')') ("ASINH", ast::fun_asinh)
| lexeme_d[ root_node_d[ str_p("SIN") ] >> ch_p('(') ] >> expression >> ch_p(')') ("ATANH", ast::fun_atanh)
| lexeme_d[ root_node_d[ str_p("TAN") ] >> ch_p('(') ] >> expression >> ch_p(')') ("LOG", ast::fun_log)
| lexeme_d[ root_node_d[ str_p("COSH") ] >> ch_p('(') ] >> expression >> ch_p(')') ("LN", ast::fun_ln)
| lexeme_d[ root_node_d[ str_p("SINH") ] >> ch_p('(') ] >> expression >> ch_p(')') ("EXP", ast::fun_exp)
| lexeme_d[ root_node_d[ str_p("TANH") ] >> ch_p('(') ] >> expression >> ch_p(')') ("SQRT", ast::fun_sqrt);
| lexeme_d[ root_node_d[ str_p("ACOS") ] >> ch_p('(') ] >> expression >> ch_p(')') }
| lexeme_d[ root_node_d[ str_p("ASIN") ] >> ch_p('(') ] >> expression >> ch_p(')') };
| lexeme_d[ root_node_d[ str_p("ATAN") ] >> ch_p('(') ] >> expression >> ch_p(')')
| lexeme_d[ root_node_d[ str_p("ACOSH") ] >> ch_p('(') ] >> expression >> ch_p(')') inline fun_tok_ fun_tok;
| lexeme_d[ root_node_d[ str_p("ASINH") ] >> ch_p('(') ] >> expression >> ch_p(')')
| lexeme_d[ root_node_d[ str_p("ATANH") ] >> ch_p('(') ] >> expression >> ch_p(')') struct const_tok_ : x3::symbols<ast::constant::type>
| lexeme_d[ root_node_d[ str_p("LOG") ] >> ch_p('(') ] >> expression >> ch_p(')') {
| lexeme_d[ root_node_d[ str_p("LN") ] >> ch_p('(') ] >> expression >> ch_p(')') const_tok_()
| lexeme_d[ root_node_d[ str_p("EXP") ] >> ch_p('(') ] >> expression >> ch_p(')') {
; add("PI", ast::constant::pi)("GAMMA_MU", ast::constant::gamma_mu);
}
factor = real };
| const_pi
| const_gamma_mu inline const_tok_ const_tok;
| parameter
| map ///////////////////////////////////////////////////////////////////////////
| function // Rules
| inner_node_d[ch_p('(') >> expression >> ch_p(')')] ///////////////////////////////////////////////////////////////////////////
;
x3::rule<class assignment, ast::assignment> const assignment = "assignment";
term = factor >> x3::rule<class expression, ast::expression> const expression = "expression";
*( (root_node_d[ch_p('*')] >> factor) x3::rule<class term, ast::expression> const term = "term";
| (root_node_d[ch_p('/')] >> factor) x3::rule<class factor, ast::operand> const factor = "factor";
); x3::rule<class constant, ast::constant> const constant = "constant";
x3::rule<class parameter, ast::parameter> const parameter = "parameter";
expression = term >> x3::rule<class map_ref, ast::map_ref> const map = "map";
*( (root_node_d[ch_p('+')] >> term) x3::rule<class function_call, ast::function_call> const function = "function";
| (root_node_d[ch_p('-')] >> term) x3::rule<class power_call, ast::power_call> const power = "power";
);
///////////////////////////////////////////////////////////////////////////
assignment = (fun_label >> ch_p('=') >> expression); // Rule definitions
// End grammar definition ///////////////////////////////////////////////////////////////////////////
// turn on the debugging info. auto const assignment_def =
BOOST_SPIRIT_DEBUG_RULE(real); lit("FUN") >> int_ >> '=' >> expression;
BOOST_SPIRIT_DEBUG_RULE(const_pi);
BOOST_SPIRIT_DEBUG_RULE(const_gamma_mu); auto const expression_def =
BOOST_SPIRIT_DEBUG_RULE(fun_label); term >> *(additive_op >> term);
BOOST_SPIRIT_DEBUG_RULE(parameter);
BOOST_SPIRIT_DEBUG_RULE(map); auto const term_def =
BOOST_SPIRIT_DEBUG_RULE(function); factor >> *(multiplicative_op >> factor);
BOOST_SPIRIT_DEBUG_RULE(factor);
BOOST_SPIRIT_DEBUG_RULE(term); auto const factor_def =
BOOST_SPIRIT_DEBUG_RULE(expression); double_
BOOST_SPIRIT_DEBUG_RULE(assignment); | constant
} | parameter
| map
rule<ScannerT, parser_context<>, parser_tag<assignmentID> > assignment; | function
rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression; | power
rule<ScannerT, parser_context<>, parser_tag<termID> > term; | ('(' >> expression >> ')');
rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
rule<ScannerT, parser_context<>, parser_tag<functionID> > function; auto const constant_def =
rule<ScannerT, parser_context<>, parser_tag<mapID> > map; (const_tok >> attr(false) >> attr(0))
rule<ScannerT, parser_context<>, parser_tag<parameterID> > parameter; | (lit("B") >> attr(ast::constant::field) >> attr(false) >> attr(0))
rule<ScannerT, parser_context<>, parser_tag<funLabelID> > fun_label; | (lit("-B") >> attr(ast::constant::field) >> attr(true) >> attr(0))
rule<ScannerT, parser_context<>, parser_tag<constGammaMuID> > const_gamma_mu; | (lit("EN") >> attr(ast::constant::energy) >> attr(false) >> attr(0))
rule<ScannerT, parser_context<>, parser_tag<constPiID> > const_pi; | (lit("-EN") >> attr(ast::constant::energy) >> attr(true) >> attr(0))
rule<ScannerT, parser_context<>, parser_tag<realID> > real; | (lit('T') >> attr(ast::constant::temp) >> attr(false) >> int_)
| (lit("-T") >> attr(ast::constant::temp) >> attr(true) >> int_);
rule<ScannerT, parser_context<>, parser_tag<assignmentID> > const&
start() const { return assignment; } auto const parameter_def =
}; (lexeme[lit("-PAR") >> int_] >> attr(true))
}; | (lit("PAR") >> int_ >> attr(false));
#endif // _PFUNCTIONGRAMMAR_H_ auto const map_def =
(lexeme[lit("-MAP") >> int_] >> attr(true))
| (lit("MAP") >> int_ >> attr(false));
auto const function_def =
fun_tok >> '(' >> expression >> ')';
auto const power_def =
lit("POW") >> '(' >> expression >> ',' >> expression >> ')';
BOOST_SPIRIT_DEFINE(
assignment,
expression,
term,
factor,
constant,
parameter,
map,
function,
power
)
}}
namespace musrfit {
// Accessor for the top-level rule
inline auto const& function_grammar()
{
return grammar::assignment;
}
}
#endif // _PFUNCTIONGRAMMAR_H_

View File

@@ -31,9 +31,8 @@
#include <string> #include <string>
#include <cassert> #include <cassert>
#include <algorithm>
#include <fstream> #include <fstream>
using namespace std;
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
@@ -51,8 +50,8 @@ PFunctionHandler::PFunctionHandler(char *fln, bool debug) : fDebug(debug), fFile
{ {
fValid = true; fValid = true;
cout << endl << "in PFunctionHandler(char *fln)"; std::cout << std::endl << "in PFunctionHandler(char *fln)";
cout << endl << "fFileName = " << fFileName; std::cout << std::endl << "fFileName = " << fFileName;
fValid = ReadFile(); fValid = ReadFile();
if (fValid) if (fValid)
@@ -67,12 +66,12 @@ PFunctionHandler::PFunctionHandler(char *fln, bool debug) : fDebug(debug), fFile
* *
* \param lines * \param lines
*/ */
PFunctionHandler::PFunctionHandler(vector<string> lines) PFunctionHandler::PFunctionHandler(std::vector<std::string> lines)
{ {
fValid = true; fValid = true;
fFileName = ""; fFileName = "";
cout << endl << "in PFunctionHandler(vector<string> lines)"; std::cout << std::endl << "in PFunctionHandler(std::vector<std::string> lines)";
if (lines.size() == 0) { if (lines.size() == 0) {
fValid = false; fValid = false;
@@ -90,43 +89,43 @@ PFunctionHandler::PFunctionHandler(vector<string> lines)
continue; continue;
boost::to_upper(lines[i]); boost::to_upper(lines[i]);
if (lines[i].find("PAR") == 0) { if (lines[i].find("PAR") == 0) {
cout << endl << "this is a parameter line ..."; std::cout << std::endl << "this is a parameter line ...";
status = sscanf(lines[i].c_str(), "PAR %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", status = sscanf(lines[i].c_str(), "PAR %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
&dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[0], &dval[1], &dval[2], &dval[3], &dval[4],
&dval[5], &dval[6], &dval[7], &dval[8], &dval[9]); &dval[5], &dval[6], &dval[7], &dval[8], &dval[9]);
cout << endl << "status=" << status; std::cout << std::endl << "status=" << status;
if (status < 0) { if (status < 0) {
done = true; done = true;
fValid = false; fValid = false;
cout << endl << "invalid PAR line, sorry ..."; std::cout << std::endl << "invalid PAR line, sorry ...";
} else { // fill par } else { // fill par
cout << endl << "PAR line, status = " << status; std::cout << std::endl << "PAR line, status = " << status;
for (int i=0; i<status; i++) for (int i=0; i<status; i++)
fParam.push_back(dval[i]); fParam.push_back(dval[i]);
cout << endl << "fParam.size()=" << fParam.size() << endl; std::cout << std::endl << "fParam.size()=" << fParam.size() << std::endl;
for (unsigned int i=0; i<fParam.size(); i++) for (unsigned int i=0; i<fParam.size(); i++)
cout << endl << "Par" << i+1 << " = " << fParam[i]; std::cout << std::endl << "Par" << i+1 << " = " << fParam[i];
cout << endl; std::cout << std::endl;
} }
} else if (lines[i].find("MAP") == 0) { } else if (lines[i].find("MAP") == 0) {
cout << endl << "this is a map line ..."; std::cout << std::endl << "this is a map line ...";
status = sscanf(lines[i].c_str(), "MAP %d %d %d %d %d %d %d %d %d %d", status = sscanf(lines[i].c_str(), "MAP %d %d %d %d %d %d %d %d %d %d",
&val[0], &val[1], &val[2], &val[3], &val[4], &val[0], &val[1], &val[2], &val[3], &val[4],
&val[5], &val[6], &val[7], &val[8], &val[9]); &val[5], &val[6], &val[7], &val[8], &val[9]);
if (status < 0) { if (status < 0) {
done = true; done = true;
fValid = false; fValid = false;
cout << endl << "invalid MAP line, sorry ..."; std::cout << std::endl << "invalid MAP line, sorry ...";
} else { // fill map } else { // fill map
cout << endl << "MAP line, status = " << status; std::cout << std::endl << "MAP line, status = " << status;
for (int i=0; i<status; i++) for (int i=0; i<status; i++)
fMap.push_back(val[i]); fMap.push_back(val[i]);
} }
} else if (lines[i].find("FUNCTIONS") == 0) { } else if (lines[i].find("FUNCTIONS") == 0) {
cout << endl << "the functions block start ..."; std::cout << std::endl << "the functions block start ...";
inFcnBlock = true; inFcnBlock = true;
} else if (lines[i].find("END") == 0) { } else if (lines[i].find("END") == 0) {
cout << endl << "end tag found; rest will be ignored"; std::cout << std::endl << "end tag found; rest will be ignored";
done = true; done = true;
} else if (inFcnBlock) { } else if (inFcnBlock) {
fLines.push_back(lines[i]); fLines.push_back(lines[i]);
@@ -136,20 +135,20 @@ PFunctionHandler::PFunctionHandler(vector<string> lines)
// check if all blocks are given // check if all blocks are given
if ((fMap.size() == 0) || (fParam.size() == 0) || (fLines.size() == 0)) { if ((fMap.size() == 0) || (fParam.size() == 0) || (fLines.size() == 0)) {
if (fMap.size() == 0) if (fMap.size() == 0)
cout << endl << "MAP block is missing ..."; std::cout << std::endl << "MAP block is missing ...";
if (fParam.size() == 0) if (fParam.size() == 0)
cout << endl << "PAR block is missing ..."; std::cout << std::endl << "PAR block is missing ...";
if (fLines.size() == 0) if (fLines.size() == 0)
cout << endl << "FUNCTION block is missing ..."; std::cout << std::endl << "FUNCTION block is missing ...";
fValid = false; fValid = false;
} }
fValid = MapsAreValid(); fValid = MapsAreValid();
if (fValid) { if (fValid) {
cout << endl << "Functions: "; std::cout << std::endl << "Functions: ";
for (unsigned int i=0; i<fLines.size(); i++) for (unsigned int i=0; i<fLines.size(); i++)
cout << endl << fLines[i]; std::cout << std::endl << fLines[i];
} }
} }
@@ -162,7 +161,7 @@ PFunctionHandler::PFunctionHandler(vector<string> lines)
*/ */
PFunctionHandler::~PFunctionHandler() PFunctionHandler::~PFunctionHandler()
{ {
cout << endl << "in ~PFunctionHandler()" << endl << endl; std::cout << std::endl << "in ~PFunctionHandler()" << std::endl << std::endl;
fParam.clear(); fParam.clear();
fMap.clear(); fMap.clear();
fLines.clear(); fLines.clear();
@@ -179,22 +178,25 @@ PFunctionHandler::~PFunctionHandler()
*/ */
bool PFunctionHandler::DoParse() bool PFunctionHandler::DoParse()
{ {
cout << endl << "in PFunctionHandler::DoParse() ..."; std::cout << std::endl << "in PFunctionHandler::DoParse() ...";
bool success = true; bool success = true;
PFunctionGrammar function;
for (unsigned int i=0; i<fLines.size(); i++) { for (unsigned int i=0; i<fLines.size(); i++) {
cout << endl << "fLines[" << i << "] = '" << fLines[i] << "'"; std::cout << std::endl << "fLines[" << i << "] = '" << fLines[i] << "'";
tree_parse_info<> info = ast_parse(fLines[i].c_str(), function, space_p); // Convert to uppercase (grammar expects uppercase tokens)
std::string line = fLines[i];
std::transform(line.begin(), line.end(), line.begin(), ::toupper);
if (info.full) { // Use new Qi-based PFunction constructor
cout << endl << "parse successfull ..." << endl; PFunction func(line, fParam, fMap, fDebug);
PFunction func(info, fParam, fMap, fDebug);
if (func.IsValid()) {
std::cout << std::endl << "parse successfull ..." << std::endl;
fFuncs.push_back(func); fFuncs.push_back(func);
} else { } else {
cout << endl << "parse failed ... (" << i << ")" << endl; std::cout << std::endl << "parse failed ... (" << i << ")" << std::endl;
success = false; success = false;
break; break;
} }
@@ -205,8 +207,8 @@ bool PFunctionHandler::DoParse()
if (success) { if (success) {
for (unsigned int i=0; i<fFuncs.size(); i++) { for (unsigned int i=0; i<fFuncs.size(); i++) {
if (!fFuncs[i].IsValid()) { if (!fFuncs[i].IsValid()) {
cout << endl << "**ERROR**: function fun" << fFuncs[i].GetFuncNo(); std::cout << std::endl << "**ERROR**: function fun" << fFuncs[i].GetFuncNo();
cout << " has a problem with either parameter or map out of range!"; std::cout << " has a problem with either parameter or map out of range!";
success = false; success = false;
break; break;
} }
@@ -218,8 +220,8 @@ bool PFunctionHandler::DoParse()
for (unsigned int i=0; i<fFuncs.size(); i++) { for (unsigned int i=0; i<fFuncs.size(); i++) {
for (unsigned int j=i+1; j<fFuncs.size(); j++) { for (unsigned int j=i+1; j<fFuncs.size(); j++) {
if (fFuncs[i].GetFuncNo() == fFuncs[j].GetFuncNo()) { if (fFuncs[i].GetFuncNo() == fFuncs[j].GetFuncNo()) {
cout << endl << "**ERROR**: function number " << fFuncs[i].GetFuncNo(); std::cout << std::endl << "**ERROR**: function number " << fFuncs[i].GetFuncNo();
cout << " is at least twice present! Fix this first."; std::cout << " is at least twice present! Fix this first.";
success = false; success = false;
} }
} }
@@ -228,7 +230,7 @@ bool PFunctionHandler::DoParse()
if (success) { if (success) {
for (unsigned int i=0; i<fFuncs.size(); i++) for (unsigned int i=0; i<fFuncs.size(); i++)
cout << endl << "func number = " << fFuncs[i].GetFuncNo(); std::cout << std::endl << "func number = " << fFuncs[i].GetFuncNo();
} }
return success; return success;
@@ -245,13 +247,10 @@ bool PFunctionHandler::DoParse()
double PFunctionHandler::Eval(int i) double PFunctionHandler::Eval(int i)
{ {
if (GetFuncIndex(i) == -1) { if (GetFuncIndex(i) == -1) {
cout << endl << "**ERROR**: Couldn't find FUN" << i << " for evaluation"; std::cout << std::endl << "**ERROR**: Couldn't find FUN" << i << " for evaluation";
return 0.0; return 0.0;
} }
cout << endl << "PFunctionHandler::Eval: GetFuncIndex("<<i<<") = " << GetFuncIndex(i);
cout << endl;
return fFuncs[GetFuncIndex(i)].Eval(); return fFuncs[GetFuncIndex(i)].Eval();
} }
@@ -280,24 +279,24 @@ unsigned int PFunctionHandler::GetFuncNo(unsigned int i)
*/ */
bool PFunctionHandler::ReadFile() bool PFunctionHandler::ReadFile()
{ {
cout << endl << "in ~PFunctionHandler::ReadFile()"; std::cout << std::endl << "in ~PFunctionHandler::ReadFile()";
if (fFileName.length() == 0) { if (fFileName.length() == 0) {
cout << endl << "PFunctionHandler::ReadFile(): **ERROR**"; std::cout << std::endl << "PFunctionHandler::ReadFile(): **ERROR**";
cout << endl << " no file name given :-(. Will quit"; std::cout << std::endl << " no file name given :-(. Will quit";
return false; return false;
} }
ifstream f; std::ifstream f;
f.open(fFileName.c_str(), ifstream::in); f.open(fFileName.c_str(), std::ifstream::in);
if (!f.is_open()) { if (!f.is_open()) {
cout << endl << "PFunctionHandler::ReadFile(): **ERROR**"; std::cout << std::endl << "PFunctionHandler::ReadFile(): **ERROR**";
cout << endl << " File '" << fFileName.c_str() << "' couldn't being opened."; std::cout << std::endl << " File '" << fFileName.c_str() << "' couldn't being opened.";
return false; return false;
} }
string line; std::string line;
char c_line[128]; char c_line[128];
bool done = false; bool done = false;
bool success = true; bool success = true;
@@ -314,41 +313,41 @@ bool PFunctionHandler::ReadFile()
continue; continue;
boost::to_upper(line); boost::to_upper(line);
if (line.find("PAR") == 0) { if (line.find("PAR") == 0) {
cout << endl << "this is a parameter line ..."; std::cout << std::endl << "this is a parameter line ...";
status = sscanf(line.c_str(), "PAR %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", status = sscanf(line.c_str(), "PAR %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
&dval[0], &dval[1], &dval[2], &dval[3], &dval[4], &dval[0], &dval[1], &dval[2], &dval[3], &dval[4],
&dval[5], &dval[6], &dval[7], &dval[8], &dval[9]); &dval[5], &dval[6], &dval[7], &dval[8], &dval[9]);
if (status < 0) { if (status < 0) {
done = true; done = true;
success = false; success = false;
cout << endl << "invalid PAR line, sorry ..."; std::cout << std::endl << "invalid PAR line, sorry ...";
} else { // fill map } else { // fill map
cout << endl << "PAR line, status = " << status; std::cout << std::endl << "PAR line, status = " << status;
for (int i=0; i<status; i++) for (int i=0; i<status; i++)
fParam.push_back(dval[i]); fParam.push_back(dval[i]);
for (unsigned int i=0; i<fParam.size(); i++) for (unsigned int i=0; i<fParam.size(); i++)
cout << endl << "Par" << i+1 << " = " << fParam[i]; std::cout << std::endl << "Par" << i+1 << " = " << fParam[i];
cout << endl; std::cout << std::endl;
} }
} else if (line.find("MAP") == 0) { } else if (line.find("MAP") == 0) {
cout << endl << "this is a map line ..."; std::cout << std::endl << "this is a map line ...";
status = sscanf(line.c_str(), "MAP %d %d %d %d %d %d %d %d %d %d", status = sscanf(line.c_str(), "MAP %d %d %d %d %d %d %d %d %d %d",
&val[0], &val[1], &val[2], &val[3], &val[4], &val[0], &val[1], &val[2], &val[3], &val[4],
&val[5], &val[6], &val[7], &val[8], &val[9]); &val[5], &val[6], &val[7], &val[8], &val[9]);
if (status < 0) { if (status < 0) {
done = true; done = true;
success = false; success = false;
cout << endl << "invalid MAP line, sorry ..."; std::cout << std::endl << "invalid MAP line, sorry ...";
} else { // fill map } else { // fill map
cout << endl << "MAP line, status = " << status; std::cout << std::endl << "MAP line, status = " << status;
for (int i=0; i<status; i++) for (int i=0; i<status; i++)
fMap.push_back(val[i]); fMap.push_back(val[i]);
} }
} else if (line.find("FUNCTIONS") == 0) { } else if (line.find("FUNCTIONS") == 0) {
cout << endl << "the functions block start ..."; std::cout << std::endl << "the functions block start ...";
inFcnBlock = true; inFcnBlock = true;
} else if (line.find("END") == 0) { } else if (line.find("END") == 0) {
cout << endl << "end tag found; rest will be ignored"; std::cout << std::endl << "end tag found; rest will be ignored";
done = true; done = true;
} else if (inFcnBlock) { } else if (inFcnBlock) {
fLines.push_back(line); fLines.push_back(line);
@@ -361,18 +360,18 @@ bool PFunctionHandler::ReadFile()
// check if all blocks are given // check if all blocks are given
if ((fMap.size() == 0) || (fParam.size() == 0) || (fLines.size() == 0)) { if ((fMap.size() == 0) || (fParam.size() == 0) || (fLines.size() == 0)) {
if (fMap.size() == 0) if (fMap.size() == 0)
cout << endl << "MAP block is missing ..."; std::cout << std::endl << "MAP block is missing ...";
if (fParam.size() == 0) if (fParam.size() == 0)
cout << endl << "PAR block is missing ..."; std::cout << std::endl << "PAR block is missing ...";
if (fLines.size() == 0) if (fLines.size() == 0)
cout << endl << "FUNCTION block is missing ..."; std::cout << std::endl << "FUNCTION block is missing ...";
success = false; success = false;
} }
if (success) { if (success) {
cout << endl << "Functions: "; std::cout << std::endl << "Functions: ";
for (unsigned int i=0; i<fLines.size(); i++) for (unsigned int i=0; i<fLines.size(); i++)
cout << endl << fLines[i]; std::cout << std::endl << fLines[i];
} }
return success; return success;
@@ -395,7 +394,7 @@ bool PFunctionHandler::MapsAreValid()
success = false; success = false;
if (!success) if (!success)
cout << endl << "invalid MAP found ..."; std::cout << std::endl << "invalid MAP found ...";
return success; return success;
} }

View File

@@ -5,12 +5,10 @@
Author: Andreas Suter Author: Andreas Suter
e-mail: andreas.suter@psi.ch e-mail: andreas.suter@psi.ch
$Id$
***************************************************************************/ ***************************************************************************/
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Andreas Suter * * Copyright (C) 2007-2026 by Andreas Suter *
* andreas.suter@psi.c * * andreas.suter@psi.c *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
@@ -35,7 +33,6 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
using namespace std;
#include "PFunctionGrammar.h" #include "PFunctionGrammar.h"
#include "PFunction.h" #include "PFunction.h"
@@ -44,7 +41,7 @@ class PFunctionHandler
{ {
public: public:
PFunctionHandler(char *fln, bool debug); PFunctionHandler(char *fln, bool debug);
PFunctionHandler(vector<string> lines); PFunctionHandler(std::vector<std::string> lines);
virtual ~PFunctionHandler(); virtual ~PFunctionHandler();
virtual bool IsValid() { return fValid; } virtual bool IsValid() { return fValid; }
@@ -57,13 +54,13 @@ class PFunctionHandler
bool fDebug; bool fDebug;
bool fValid; bool fValid;
string fFileName; std::string fFileName;
vector<double> fParam; std::vector<double> fParam;
vector<int> fMap; std::vector<int> fMap;
vector<string> fLines; std::vector<std::string> fLines;
vector<PFunction> fFuncs; std::vector<PFunction> fFuncs;
virtual bool ReadFile(); virtual bool ReadFile();
virtual bool MapsAreValid(); virtual bool MapsAreValid();

View File

@@ -17,17 +17,21 @@
PAR 1.0 2.1 3.5 -0.87 0.87 PAR 1.0 2.1 3.5 -0.87 0.87
MAP 2 1 4 5 MAP 2 1 4 5
FUNCTIONS FUNCTIONS
#fun0 = cos(par1) fun0 = cos(par1)
#fun1 = sin(par3/(par1+map2)) fun1 = sin(par3/(par1+map2))
#fun0 = 1.2+pi #fun0 = 1.2+pi
#fun1 = gamma_mu #fun1 = gamma_mu
#fun2 = -par1*(sin(par2)*cos(par3)+((map1))) fun2 = -par1*(sin(par2)*cos(par3)+((map1)))
#fun1 = cos(par1) #fun1 = cos(par1)
#fun0 = par1 + map3 * cos(cos(par2 - map1)) #fun0 = par1 + map3 * cos(cos(par2 - map1))
#fun8 = -par1*log(sin(par1)) + exp(-1.0*map2) #fun8 = -par1*log(sin(par1)) + exp(-1.0*map2)
#fun1 = par1 + map1 * (0.01355+par1*(2.1 - (-2.3 / 3.4))) #fun1 = par1 + map1 * (0.01355+par1*(2.1 - (-2.3 / 3.4)))
#fun2 = par1 * par2 - map3 #fun2 = par1 * par2 - map3
fun3 = -3.2 + (par2-par1)/(map2+map3) #fun3 = -3.2 + (par2-par1)/(map2+map3)
#fun7 = 1.2 #fun7 = 1.2
#fun1 = sin(cos(par1))*exp(-1.0*map2)+map4*par2
# Test unary map syntax - final test
fun3 = exp(-map2)
#fun2 = cos(-1.0*map1) + sin(-par1)
END END
#---------------------------------------------- #----------------------------------------------

View File

@@ -2,44 +2,43 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
using namespace std;
#include "PFunctionHandler.h" #include "PFunctionHandler.h"
//----------------------------------------------------- //-----------------------------------------------------
void syntax() void syntax()
{ {
cout << endl << "spirit_fcn_test [--file <filename> [--debug]] | [--help]"; std::cout << std::endl << "spirit_fcn_test [--file <filename> [--debug]] | [--help]";
cout << endl << " without arguments: interactive mode"; std::cout << std::endl << " without arguments: interactive mode";
cout << endl << " --file <filename>: function block etc. from file"; std::cout << std::endl << " --file <filename>: function block etc. from file";
cout << endl << " --help: this help"; std::cout << std::endl << " --help: this help";
cout << endl << " --debug: will print the ast tree only (no evaluatio)"; std::cout << std::endl << " --debug: will print the ast tree only (no evaluation)";
cout << endl << endl; std::cout << std::endl << std::endl;
} }
//----------------------------------------------------- //-----------------------------------------------------
void handle_input(vector<string> &lines) void handle_input(std::vector<std::string> &lines)
{ {
cout << endl << "will handle input ..."; std::cout << std::endl << "will handle input ...";
cout << endl << "you should provide a PAR, a MAP, and a FUNCTION block"; std::cout << std::endl << "you should provide a PAR, a MAP, and a FUNCTION block";
cout << endl << " Map block:"; std::cout << std::endl << " Map block:";
cout << endl << " MAP <map1> <map2> ... <mapM>"; std::cout << std::endl << " MAP <map1> <map2> ... <mapM>";
cout << endl << " Parameter block:"; std::cout << std::endl << " Parameter block:";
cout << endl << " PAR <par1> <par2> ... <parN>"; std::cout << std::endl << " PAR <par1> <par2> ... <parN>";
cout << endl << " Function Block:"; std::cout << std::endl << " Function Block:";
cout << endl << " FUNCTION"; std::cout << std::endl << " FUNCTION";
cout << endl << " fun1 = <function1>"; std::cout << std::endl << " fun1 = <function1>";
cout << endl << " fun2 = <function2>"; std::cout << std::endl << " fun2 = <function2>";
cout << endl << " ..."; std::cout << std::endl << " ...";
cout << endl << " funX = <functionX>"; std::cout << std::endl << " funX = <functionX>";
cout << endl << " END"; std::cout << std::endl << " END";
cout << endl << "to get out of the input handle type '.q'"; std::cout << std::endl << "to get out of the input handle type '.q'";
cout << endl; std::cout << std::endl;
bool done = false; bool done = false;
char str[128]; char str[128];
do { do {
cout << ">> "; std::cout << ">> ";
cin.getline(str, sizeof(str)); std::cin.getline(str, sizeof(str));
if (!strcmp(str, ".q")) if (!strcmp(str, ".q"))
done = true; done = true;
else else
@@ -76,39 +75,33 @@ int main(int argc, char *argv[])
} }
} }
PFunctionHandler *fcnHandler = 0; std::unique_ptr<PFunctionHandler> fcnHandler;
if (inputFile) { if (inputFile) {
fcnHandler = new PFunctionHandler(argv[2], debug); fcnHandler = std::make_unique<PFunctionHandler>(argv[2], debug);
} else { } else {
vector<string> lines; std::vector<std::string> lines;
handle_input(lines); handle_input(lines);
fcnHandler = new PFunctionHandler(lines); fcnHandler = std::make_unique<PFunctionHandler>(lines);
} }
if (fcnHandler == 0) { if (fcnHandler == 0) {
cout << endl << "Couldn't invoke function handler, sorry ..." << endl; std::cout << std::endl << "Couldn't invoke function handler, sorry ..." << std::endl;
return 0; return 0;
} }
bool go_on = fcnHandler->IsValid(); bool go_on = fcnHandler->IsValid();
if (go_on) { if (go_on) {
cout << endl << "will do the parsing ..."; std::cout << std::endl << "will do the parsing ...";
if (fcnHandler->DoParse()) { if (fcnHandler->DoParse()) {
if (!debug) { if (!debug) {
cout << endl << "will do the evaluation ..."; std::cout << std::endl << "will do the evaluation ...";
for (unsigned int i=0; i<fcnHandler->GetNoOfFuncs(); i++) for (unsigned int i=0; i<fcnHandler->GetNoOfFuncs(); i++)
cout << endl << "FUN" << fcnHandler->GetFuncNo(i) << " = " << fcnHandler->Eval(fcnHandler->GetFuncNo(i)); std::cout << std::endl << "FUN" << fcnHandler->GetFuncNo(i) << " = " << fcnHandler->Eval(fcnHandler->GetFuncNo(i));
} }
} }
} }
// clean up
if (fcnHandler) {
delete fcnHandler;
fcnHandler = 0;
}
return 1; return 1;
} }

View File

@@ -1,33 +0,0 @@
#-------------------------------------------------
# spirit_fcn_test.mak
#-------------------------------------------------
# Paths
STD_INC = "C:\Program Files\Microsoft Visual Studio 9.0\VC\include"
BOOST_INC = "D:\boost_1_43_0\boost_1_43_0"
LIB_PATH_1 = "C:\Program Files\Microsoft Visual Studio 9.0\VC\lib"
LIB_PATH_2 = "C:\Program Files\Microsoft SDKs\Windows\v6.0a\Lib"
LIB_PATH_3 = "D:\boost_1_43_0\boost_1_43_0\bin.v2\libs"
# Compiler etc
CC = cl
LINK32 = link
# Options
CXXFLAGS = /c /W3 /O2 /nologo /EHsc /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /I$(STD_INC) /I$(BOOST_INC)
LINK32_FLAGS = /nologo /subsystem:console /incremental:no /machine:I386
fln = spirit_fcn_test
OBJ = $(fln).obj PFunction.obj PFunctionHandler.obj
$(fln): $(OBJ)
$(LINK32) $(LINK32_FLAGS) /LIBPATH:$(LIB_PATH_1) /LIBPATH:$(LIB_PATH_2) /LIBPATH:$(LIB_PATH_3) $(OBJ) /out:$(fln).exe
.cpp.obj:
$(CC) $(CXXFLAGS) $<
clean:
@del /f *.obj

View File

@@ -1,24 +0,0 @@
#------------------------------------------------------
# spirit_fcn_test.pro
# qmake file for spirit_fcn_test
#
# Andreas Suter, 2007/12/10
#
# $Id$
#
#------------------------------------------------------
MAKEFILE = Makefile
CONFIG += warn_on debug
HEADERS = PFunctionGrammar.h \
PFunction.h \
PFunctionHandler.h
SOURCES = spirit_fcn_test.cpp \
PFunction.cpp \
PFunctionHandler.cpp
TARGET=spirit_fcn_test