test spirit parser moved from classic to X3.
This commit is contained in:
73
src/tests/spirit/CMakeLists.txt
Normal file
73
src/tests/spirit/CMakeLists.txt
Normal 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
@@ -1,17 +1,17 @@
|
||||
/***************************************************************************
|
||||
|
||||
PFunction.h
|
||||
PFunction.h - Test version (simplified, no PMetaData)
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
$Id$
|
||||
Modernized test version using Boost.Spirit X3 and visitor pattern.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Andreas Suter *
|
||||
* andreas.suter@psi.c *
|
||||
* 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 *
|
||||
@@ -35,91 +35,54 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#if BOOST_VERSION >= 103800
|
||||
# include <boost/spirit/include/classic_ast.hpp>
|
||||
using namespace BOOST_SPIRIT_CLASSIC_NS;
|
||||
#else
|
||||
# include <boost/spirit/tree/ast.hpp>
|
||||
using namespace boost::spirit;
|
||||
#endif
|
||||
|
||||
#include "PFunctionGrammar.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#define OP_ADD 0
|
||||
#define OP_SUB 1
|
||||
#define OP_MUL 2
|
||||
#define OP_DIV 3
|
||||
|
||||
#define FUN_COS 0
|
||||
#define FUN_SIN 1
|
||||
#define FUN_TAN 2
|
||||
#define FUN_COSH 3
|
||||
#define FUN_SINH 4
|
||||
#define FUN_TANH 5
|
||||
#define FUN_ACOS 6
|
||||
#define FUN_ASIN 7
|
||||
#define FUN_ATAN 8
|
||||
#define FUN_ACOSH 9
|
||||
#define FUN_ASINH 10
|
||||
#define FUN_ATANH 11
|
||||
#define FUN_LOG 12
|
||||
#define FUN_LN 13
|
||||
#define FUN_EXP 14
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
typedef struct func_tree_node {
|
||||
int fID; ///< tag showing what tree element this is
|
||||
int fOperatorTag; ///< tag for '+', '-', '*', '/'
|
||||
int fFunctionTag; ///< tag got "cos", "sin", ...
|
||||
int fIvalue; ///< for parameter numbers and maps
|
||||
bool fSign; ///< for sign. true = '-', false = '+'
|
||||
double fDvalue; ///< for numbers
|
||||
vector<func_tree_node> children; ///< holding sub-tree
|
||||
} PFuncTreeNode;
|
||||
#include "PFunctionAst.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Test version of PFunction class - simplified without PMetaData.
|
||||
*
|
||||
* This test version uses the same X3 grammar and AST but with a simpler
|
||||
* interface for testing purposes. It does not support metadata (field,
|
||||
* energy, temperature).
|
||||
*/
|
||||
class PFunction {
|
||||
public:
|
||||
PFunction(tree_parse_info<> info, vector<double> param, vector<int> map, bool debug);
|
||||
PFunction(const std::string& input, std::vector<double> param, std::vector<int> map, bool debug = false);
|
||||
virtual ~PFunction();
|
||||
|
||||
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;
|
||||
|
||||
musrfit::ast::expression fAst;
|
||||
std::vector<double> fParam;
|
||||
std::vector<int> fMap;
|
||||
bool fValid;
|
||||
int fFuncNo;
|
||||
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;
|
||||
// Simplified evaluation visitor (no metadata support)
|
||||
class EvalVisitor : public boost::static_visitor<double> {
|
||||
public:
|
||||
EvalVisitor(const std::vector<int>& map, const std::vector<double>& param)
|
||||
: fMap(map), fParam(param) {}
|
||||
|
||||
double operator()(const musrfit::ast::nil&) const;
|
||||
double operator()(double val) const;
|
||||
double operator()(const musrfit::ast::constant& c) const;
|
||||
double operator()(const musrfit::ast::parameter& p) const;
|
||||
double operator()(const musrfit::ast::map_ref& m) const;
|
||||
double operator()(const musrfit::ast::function_call& f) const;
|
||||
double operator()(const musrfit::ast::power_call& p) const;
|
||||
double operator()(const musrfit::ast::expression& e) const;
|
||||
|
||||
private:
|
||||
const std::vector<int>& fMap;
|
||||
const std::vector<double>& fParam;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // _PFUNCTION_H_
|
||||
|
||||
306
src/tests/spirit/PFunctionAst.h
Normal file
306
src/tests/spirit/PFunctionAst.h
Normal 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_
|
||||
@@ -1,17 +1,18 @@
|
||||
/***************************************************************************
|
||||
|
||||
PFunctionGrammer.h
|
||||
PFunctionGrammar.h
|
||||
|
||||
Author: Andreas Suter
|
||||
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 *
|
||||
@@ -32,133 +33,164 @@
|
||||
#ifndef _PFUNCTIONGRAMMAR_H_
|
||||
#define _PFUNCTIONGRAMMAR_H_
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
//#define BOOST_SPIRIT_DEBUG
|
||||
|
||||
// Check Boost version - require 1.61+ for Spirit X3
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/spirit/version.hpp>
|
||||
|
||||
#if BOOST_VERSION >= 103800
|
||||
# include <boost/spirit/include/classic_core.hpp>
|
||||
# include <boost/spirit/include/classic_ast.hpp>
|
||||
using namespace BOOST_SPIRIT_CLASSIC_NS;
|
||||
#else
|
||||
# include <boost/spirit/core.hpp>
|
||||
# include <boost/spirit/tree/ast.hpp>
|
||||
using namespace boost::spirit;
|
||||
#if BOOST_VERSION < 106100
|
||||
# error "Boost version 1.61.0 or higher is required for Spirit X3. Please upgrade Boost."
|
||||
#endif
|
||||
|
||||
typedef char const* iterator_t;
|
||||
typedef tree_match<iterator_t> parse_tree_match_t;
|
||||
typedef parse_tree_match_t::tree_iterator iter_t;
|
||||
#include "PFunctionAst.h"
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct PFunctionGrammar : public grammar<PFunctionGrammar>
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
namespace musrfit { namespace grammar
|
||||
{
|
||||
static const int realID = 1;
|
||||
static const int constPiID = 2;
|
||||
static const int constGammaMuID = 3;
|
||||
static const int funLabelID = 4;
|
||||
static const int parameterID = 5;
|
||||
static const int mapID = 6;
|
||||
static const int functionID = 7;
|
||||
static const int factorID = 8;
|
||||
static const int termID = 9;
|
||||
static const int expressionID = 10;
|
||||
static const int assignmentID = 11;
|
||||
using x3::int_;
|
||||
using x3::double_;
|
||||
using x3::lit;
|
||||
using x3::lexeme;
|
||||
using x3::attr;
|
||||
|
||||
template <typename ScannerT>
|
||||
struct definition
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Symbol tables - using inline to avoid multiple definition errors
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct additive_op_ : x3::symbols<ast::optoken>
|
||||
{
|
||||
additive_op_()
|
||||
{
|
||||
definition(PFunctionGrammar const& /*self*/)
|
||||
{
|
||||
// Start grammar definition
|
||||
real = leaf_node_d[ real_p ];
|
||||
add("+", ast::op_plus)("-", ast::op_minus);
|
||||
}
|
||||
};
|
||||
|
||||
const_pi = leaf_node_d[ str_p("PI") ];
|
||||
inline additive_op_ additive_op;
|
||||
|
||||
const_gamma_mu = leaf_node_d[ str_p("GAMMA_MU") ];
|
||||
struct multiplicative_op_ : x3::symbols<ast::optoken>
|
||||
{
|
||||
multiplicative_op_()
|
||||
{
|
||||
add("*", ast::op_times)("/", ast::op_divide);
|
||||
}
|
||||
};
|
||||
|
||||
fun_label = leaf_node_d[ ( lexeme_d[ "FUN" >> +digit_p ] ) ];
|
||||
inline multiplicative_op_ multiplicative_op;
|
||||
|
||||
parameter = leaf_node_d[ ( lexeme_d[ "PAR" >> +digit_p ] ) |
|
||||
( lexeme_d[ "-PAR" >> +digit_p ] ) ];
|
||||
struct fun_tok_ : x3::symbols<ast::funid>
|
||||
{
|
||||
fun_tok_()
|
||||
{
|
||||
add
|
||||
("COS", ast::fun_cos)
|
||||
("SIN", ast::fun_sin)
|
||||
("TAN", ast::fun_tan)
|
||||
("COSH", ast::fun_cosh)
|
||||
("SINH", ast::fun_sinh)
|
||||
("TANH", ast::fun_tanh)
|
||||
("ACOS", ast::fun_acos)
|
||||
("ASIN", ast::fun_asin)
|
||||
("ATAN", ast::fun_atan)
|
||||
("ACOSH", ast::fun_acosh)
|
||||
("ASINH", ast::fun_asinh)
|
||||
("ATANH", ast::fun_atanh)
|
||||
("LOG", ast::fun_log)
|
||||
("LN", ast::fun_ln)
|
||||
("EXP", ast::fun_exp)
|
||||
("SQRT", ast::fun_sqrt);
|
||||
}
|
||||
};
|
||||
|
||||
map = leaf_node_d[ ( lexeme_d[ "MAP" >> +digit_p ] ) ];
|
||||
inline fun_tok_ fun_tok;
|
||||
|
||||
function = lexeme_d[ root_node_d[ str_p("COS") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
| lexeme_d[ root_node_d[ str_p("SIN") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
| lexeme_d[ root_node_d[ str_p("TAN") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
| lexeme_d[ root_node_d[ str_p("COSH") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
| lexeme_d[ root_node_d[ str_p("SINH") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
| lexeme_d[ root_node_d[ str_p("TANH") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
| 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(')')
|
||||
| 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(')')
|
||||
| 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(')')
|
||||
| lexeme_d[ root_node_d[ str_p("EXP") ] >> ch_p('(') ] >> expression >> ch_p(')')
|
||||
;
|
||||
struct const_tok_ : x3::symbols<ast::constant::type>
|
||||
{
|
||||
const_tok_()
|
||||
{
|
||||
add("PI", ast::constant::pi)("GAMMA_MU", ast::constant::gamma_mu);
|
||||
}
|
||||
};
|
||||
|
||||
factor = real
|
||||
| const_pi
|
||||
| const_gamma_mu
|
||||
| parameter
|
||||
| map
|
||||
| function
|
||||
| inner_node_d[ch_p('(') >> expression >> ch_p(')')]
|
||||
;
|
||||
inline const_tok_ const_tok;
|
||||
|
||||
term = factor >>
|
||||
*( (root_node_d[ch_p('*')] >> factor)
|
||||
| (root_node_d[ch_p('/')] >> factor)
|
||||
);
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Rules
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
expression = term >>
|
||||
*( (root_node_d[ch_p('+')] >> term)
|
||||
| (root_node_d[ch_p('-')] >> term)
|
||||
);
|
||||
x3::rule<class assignment, ast::assignment> const assignment = "assignment";
|
||||
x3::rule<class expression, ast::expression> const expression = "expression";
|
||||
x3::rule<class term, ast::expression> const term = "term";
|
||||
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";
|
||||
x3::rule<class map_ref, ast::map_ref> const map = "map";
|
||||
x3::rule<class function_call, ast::function_call> const function = "function";
|
||||
x3::rule<class power_call, ast::power_call> const power = "power";
|
||||
|
||||
assignment = (fun_label >> ch_p('=') >> expression);
|
||||
// End grammar definition
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Rule definitions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// turn on the debugging info.
|
||||
BOOST_SPIRIT_DEBUG_RULE(real);
|
||||
BOOST_SPIRIT_DEBUG_RULE(const_pi);
|
||||
BOOST_SPIRIT_DEBUG_RULE(const_gamma_mu);
|
||||
BOOST_SPIRIT_DEBUG_RULE(fun_label);
|
||||
BOOST_SPIRIT_DEBUG_RULE(parameter);
|
||||
BOOST_SPIRIT_DEBUG_RULE(map);
|
||||
BOOST_SPIRIT_DEBUG_RULE(function);
|
||||
BOOST_SPIRIT_DEBUG_RULE(factor);
|
||||
BOOST_SPIRIT_DEBUG_RULE(term);
|
||||
BOOST_SPIRIT_DEBUG_RULE(expression);
|
||||
BOOST_SPIRIT_DEBUG_RULE(assignment);
|
||||
}
|
||||
auto const assignment_def =
|
||||
lit("FUN") >> int_ >> '=' >> expression;
|
||||
|
||||
rule<ScannerT, parser_context<>, parser_tag<assignmentID> > assignment;
|
||||
rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression;
|
||||
rule<ScannerT, parser_context<>, parser_tag<termID> > term;
|
||||
rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
|
||||
rule<ScannerT, parser_context<>, parser_tag<functionID> > function;
|
||||
rule<ScannerT, parser_context<>, parser_tag<mapID> > map;
|
||||
rule<ScannerT, parser_context<>, parser_tag<parameterID> > parameter;
|
||||
rule<ScannerT, parser_context<>, parser_tag<funLabelID> > fun_label;
|
||||
rule<ScannerT, parser_context<>, parser_tag<constGammaMuID> > const_gamma_mu;
|
||||
rule<ScannerT, parser_context<>, parser_tag<constPiID> > const_pi;
|
||||
rule<ScannerT, parser_context<>, parser_tag<realID> > real;
|
||||
auto const expression_def =
|
||||
term >> *(additive_op >> term);
|
||||
|
||||
rule<ScannerT, parser_context<>, parser_tag<assignmentID> > const&
|
||||
start() const { return assignment; }
|
||||
};
|
||||
};
|
||||
auto const term_def =
|
||||
factor >> *(multiplicative_op >> factor);
|
||||
|
||||
auto const factor_def =
|
||||
double_
|
||||
| constant
|
||||
| parameter
|
||||
| map
|
||||
| function
|
||||
| power
|
||||
| ('(' >> expression >> ')');
|
||||
|
||||
auto const constant_def =
|
||||
(const_tok >> attr(false) >> attr(0))
|
||||
| (lit("B") >> attr(ast::constant::field) >> attr(false) >> attr(0))
|
||||
| (lit("-B") >> attr(ast::constant::field) >> attr(true) >> attr(0))
|
||||
| (lit("EN") >> attr(ast::constant::energy) >> attr(false) >> attr(0))
|
||||
| (lit("-EN") >> attr(ast::constant::energy) >> attr(true) >> attr(0))
|
||||
| (lit('T') >> attr(ast::constant::temp) >> attr(false) >> int_)
|
||||
| (lit("-T") >> attr(ast::constant::temp) >> attr(true) >> int_);
|
||||
|
||||
auto const parameter_def =
|
||||
(lexeme[lit("-PAR") >> int_] >> attr(true))
|
||||
| (lit("PAR") >> int_ >> attr(false));
|
||||
|
||||
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_
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
@@ -51,8 +50,8 @@ PFunctionHandler::PFunctionHandler(char *fln, bool debug) : fDebug(debug), fFile
|
||||
{
|
||||
fValid = true;
|
||||
|
||||
cout << endl << "in PFunctionHandler(char *fln)";
|
||||
cout << endl << "fFileName = " << fFileName;
|
||||
std::cout << std::endl << "in PFunctionHandler(char *fln)";
|
||||
std::cout << std::endl << "fFileName = " << fFileName;
|
||||
|
||||
fValid = ReadFile();
|
||||
if (fValid)
|
||||
@@ -67,12 +66,12 @@ PFunctionHandler::PFunctionHandler(char *fln, bool debug) : fDebug(debug), fFile
|
||||
*
|
||||
* \param lines
|
||||
*/
|
||||
PFunctionHandler::PFunctionHandler(vector<string> lines)
|
||||
PFunctionHandler::PFunctionHandler(std::vector<std::string> lines)
|
||||
{
|
||||
fValid = true;
|
||||
fFileName = "";
|
||||
|
||||
cout << endl << "in PFunctionHandler(vector<string> lines)";
|
||||
std::cout << std::endl << "in PFunctionHandler(std::vector<std::string> lines)";
|
||||
|
||||
if (lines.size() == 0) {
|
||||
fValid = false;
|
||||
@@ -90,43 +89,43 @@ PFunctionHandler::PFunctionHandler(vector<string> lines)
|
||||
continue;
|
||||
boost::to_upper(lines[i]);
|
||||
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",
|
||||
&dval[0], &dval[1], &dval[2], &dval[3], &dval[4],
|
||||
&dval[5], &dval[6], &dval[7], &dval[8], &dval[9]);
|
||||
cout << endl << "status=" << status;
|
||||
std::cout << std::endl << "status=" << status;
|
||||
if (status < 0) {
|
||||
done = true;
|
||||
fValid = false;
|
||||
cout << endl << "invalid PAR line, sorry ...";
|
||||
std::cout << std::endl << "invalid PAR line, sorry ...";
|
||||
} else { // fill par
|
||||
cout << endl << "PAR line, status = " << status;
|
||||
std::cout << std::endl << "PAR line, status = " << status;
|
||||
for (int i=0; i<status; 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++)
|
||||
cout << endl << "Par" << i+1 << " = " << fParam[i];
|
||||
cout << endl;
|
||||
std::cout << std::endl << "Par" << i+1 << " = " << fParam[i];
|
||||
std::cout << std::endl;
|
||||
}
|
||||
} 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",
|
||||
&val[0], &val[1], &val[2], &val[3], &val[4],
|
||||
&val[5], &val[6], &val[7], &val[8], &val[9]);
|
||||
if (status < 0) {
|
||||
done = true;
|
||||
fValid = false;
|
||||
cout << endl << "invalid MAP line, sorry ...";
|
||||
std::cout << std::endl << "invalid MAP line, sorry ...";
|
||||
} else { // fill map
|
||||
cout << endl << "MAP line, status = " << status;
|
||||
std::cout << std::endl << "MAP line, status = " << status;
|
||||
for (int i=0; i<status; i++)
|
||||
fMap.push_back(val[i]);
|
||||
}
|
||||
} else if (lines[i].find("FUNCTIONS") == 0) {
|
||||
cout << endl << "the functions block start ...";
|
||||
std::cout << std::endl << "the functions block start ...";
|
||||
inFcnBlock = true;
|
||||
} 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;
|
||||
} else if (inFcnBlock) {
|
||||
fLines.push_back(lines[i]);
|
||||
@@ -136,20 +135,20 @@ PFunctionHandler::PFunctionHandler(vector<string> lines)
|
||||
// check if all blocks are given
|
||||
if ((fMap.size() == 0) || (fParam.size() == 0) || (fLines.size() == 0)) {
|
||||
if (fMap.size() == 0)
|
||||
cout << endl << "MAP block is missing ...";
|
||||
std::cout << std::endl << "MAP block is missing ...";
|
||||
if (fParam.size() == 0)
|
||||
cout << endl << "PAR block is missing ...";
|
||||
std::cout << std::endl << "PAR block is missing ...";
|
||||
if (fLines.size() == 0)
|
||||
cout << endl << "FUNCTION block is missing ...";
|
||||
std::cout << std::endl << "FUNCTION block is missing ...";
|
||||
fValid = false;
|
||||
}
|
||||
|
||||
fValid = MapsAreValid();
|
||||
|
||||
if (fValid) {
|
||||
cout << endl << "Functions: ";
|
||||
std::cout << std::endl << "Functions: ";
|
||||
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()
|
||||
{
|
||||
cout << endl << "in ~PFunctionHandler()" << endl << endl;
|
||||
std::cout << std::endl << "in ~PFunctionHandler()" << std::endl << std::endl;
|
||||
fParam.clear();
|
||||
fMap.clear();
|
||||
fLines.clear();
|
||||
@@ -179,22 +178,25 @@ PFunctionHandler::~PFunctionHandler()
|
||||
*/
|
||||
bool PFunctionHandler::DoParse()
|
||||
{
|
||||
cout << endl << "in PFunctionHandler::DoParse() ...";
|
||||
std::cout << std::endl << "in PFunctionHandler::DoParse() ...";
|
||||
|
||||
bool success = true;
|
||||
PFunctionGrammar function;
|
||||
|
||||
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) {
|
||||
cout << endl << "parse successfull ..." << endl;
|
||||
PFunction func(info, fParam, fMap, fDebug);
|
||||
// Use new Qi-based PFunction constructor
|
||||
PFunction func(line, fParam, fMap, fDebug);
|
||||
|
||||
if (func.IsValid()) {
|
||||
std::cout << std::endl << "parse successfull ..." << std::endl;
|
||||
fFuncs.push_back(func);
|
||||
} else {
|
||||
cout << endl << "parse failed ... (" << i << ")" << endl;
|
||||
std::cout << std::endl << "parse failed ... (" << i << ")" << std::endl;
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
@@ -205,8 +207,8 @@ bool PFunctionHandler::DoParse()
|
||||
if (success) {
|
||||
for (unsigned int i=0; i<fFuncs.size(); i++) {
|
||||
if (!fFuncs[i].IsValid()) {
|
||||
cout << endl << "**ERROR**: function fun" << fFuncs[i].GetFuncNo();
|
||||
cout << " has a problem with either parameter or map out of range!";
|
||||
std::cout << std::endl << "**ERROR**: function fun" << fFuncs[i].GetFuncNo();
|
||||
std::cout << " has a problem with either parameter or map out of range!";
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
@@ -218,8 +220,8 @@ bool PFunctionHandler::DoParse()
|
||||
for (unsigned int i=0; i<fFuncs.size(); i++) {
|
||||
for (unsigned int j=i+1; j<fFuncs.size(); j++) {
|
||||
if (fFuncs[i].GetFuncNo() == fFuncs[j].GetFuncNo()) {
|
||||
cout << endl << "**ERROR**: function number " << fFuncs[i].GetFuncNo();
|
||||
cout << " is at least twice present! Fix this first.";
|
||||
std::cout << std::endl << "**ERROR**: function number " << fFuncs[i].GetFuncNo();
|
||||
std::cout << " is at least twice present! Fix this first.";
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
@@ -228,7 +230,7 @@ bool PFunctionHandler::DoParse()
|
||||
|
||||
if (success) {
|
||||
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;
|
||||
@@ -245,13 +247,10 @@ bool PFunctionHandler::DoParse()
|
||||
double PFunctionHandler::Eval(int i)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
cout << endl << "PFunctionHandler::Eval: GetFuncIndex("<<i<<") = " << GetFuncIndex(i);
|
||||
cout << endl;
|
||||
|
||||
return fFuncs[GetFuncIndex(i)].Eval();
|
||||
}
|
||||
|
||||
@@ -280,24 +279,24 @@ unsigned int PFunctionHandler::GetFuncNo(unsigned int i)
|
||||
*/
|
||||
bool PFunctionHandler::ReadFile()
|
||||
{
|
||||
cout << endl << "in ~PFunctionHandler::ReadFile()";
|
||||
std::cout << std::endl << "in ~PFunctionHandler::ReadFile()";
|
||||
|
||||
if (fFileName.length() == 0) {
|
||||
cout << endl << "PFunctionHandler::ReadFile(): **ERROR**";
|
||||
cout << endl << " no file name given :-(. Will quit";
|
||||
std::cout << std::endl << "PFunctionHandler::ReadFile(): **ERROR**";
|
||||
std::cout << std::endl << " no file name given :-(. Will quit";
|
||||
return false;
|
||||
}
|
||||
|
||||
ifstream f;
|
||||
f.open(fFileName.c_str(), ifstream::in);
|
||||
std::ifstream f;
|
||||
f.open(fFileName.c_str(), std::ifstream::in);
|
||||
|
||||
if (!f.is_open()) {
|
||||
cout << endl << "PFunctionHandler::ReadFile(): **ERROR**";
|
||||
cout << endl << " File '" << fFileName.c_str() << "' couldn't being opened.";
|
||||
std::cout << std::endl << "PFunctionHandler::ReadFile(): **ERROR**";
|
||||
std::cout << std::endl << " File '" << fFileName.c_str() << "' couldn't being opened.";
|
||||
return false;
|
||||
}
|
||||
|
||||
string line;
|
||||
std::string line;
|
||||
char c_line[128];
|
||||
bool done = false;
|
||||
bool success = true;
|
||||
@@ -314,41 +313,41 @@ bool PFunctionHandler::ReadFile()
|
||||
continue;
|
||||
boost::to_upper(line);
|
||||
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",
|
||||
&dval[0], &dval[1], &dval[2], &dval[3], &dval[4],
|
||||
&dval[5], &dval[6], &dval[7], &dval[8], &dval[9]);
|
||||
if (status < 0) {
|
||||
done = true;
|
||||
success = false;
|
||||
cout << endl << "invalid PAR line, sorry ...";
|
||||
std::cout << std::endl << "invalid PAR line, sorry ...";
|
||||
} else { // fill map
|
||||
cout << endl << "PAR line, status = " << status;
|
||||
std::cout << std::endl << "PAR line, status = " << status;
|
||||
for (int i=0; i<status; i++)
|
||||
fParam.push_back(dval[i]);
|
||||
for (unsigned int i=0; i<fParam.size(); i++)
|
||||
cout << endl << "Par" << i+1 << " = " << fParam[i];
|
||||
cout << endl;
|
||||
std::cout << std::endl << "Par" << i+1 << " = " << fParam[i];
|
||||
std::cout << std::endl;
|
||||
}
|
||||
} 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",
|
||||
&val[0], &val[1], &val[2], &val[3], &val[4],
|
||||
&val[5], &val[6], &val[7], &val[8], &val[9]);
|
||||
if (status < 0) {
|
||||
done = true;
|
||||
success = false;
|
||||
cout << endl << "invalid MAP line, sorry ...";
|
||||
std::cout << std::endl << "invalid MAP line, sorry ...";
|
||||
} else { // fill map
|
||||
cout << endl << "MAP line, status = " << status;
|
||||
std::cout << std::endl << "MAP line, status = " << status;
|
||||
for (int i=0; i<status; i++)
|
||||
fMap.push_back(val[i]);
|
||||
}
|
||||
} else if (line.find("FUNCTIONS") == 0) {
|
||||
cout << endl << "the functions block start ...";
|
||||
std::cout << std::endl << "the functions block start ...";
|
||||
inFcnBlock = true;
|
||||
} 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;
|
||||
} else if (inFcnBlock) {
|
||||
fLines.push_back(line);
|
||||
@@ -361,18 +360,18 @@ bool PFunctionHandler::ReadFile()
|
||||
// check if all blocks are given
|
||||
if ((fMap.size() == 0) || (fParam.size() == 0) || (fLines.size() == 0)) {
|
||||
if (fMap.size() == 0)
|
||||
cout << endl << "MAP block is missing ...";
|
||||
std::cout << std::endl << "MAP block is missing ...";
|
||||
if (fParam.size() == 0)
|
||||
cout << endl << "PAR block is missing ...";
|
||||
std::cout << std::endl << "PAR block is missing ...";
|
||||
if (fLines.size() == 0)
|
||||
cout << endl << "FUNCTION block is missing ...";
|
||||
std::cout << std::endl << "FUNCTION block is missing ...";
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
cout << endl << "Functions: ";
|
||||
std::cout << std::endl << "Functions: ";
|
||||
for (unsigned int i=0; i<fLines.size(); i++)
|
||||
cout << endl << fLines[i];
|
||||
std::cout << std::endl << fLines[i];
|
||||
}
|
||||
|
||||
return success;
|
||||
@@ -395,7 +394,7 @@ bool PFunctionHandler::MapsAreValid()
|
||||
success = false;
|
||||
|
||||
if (!success)
|
||||
cout << endl << "invalid MAP found ...";
|
||||
std::cout << std::endl << "invalid MAP found ...";
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
$Id$
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.c *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,7 +33,6 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "PFunctionGrammar.h"
|
||||
#include "PFunction.h"
|
||||
@@ -44,7 +41,7 @@ class PFunctionHandler
|
||||
{
|
||||
public:
|
||||
PFunctionHandler(char *fln, bool debug);
|
||||
PFunctionHandler(vector<string> lines);
|
||||
PFunctionHandler(std::vector<std::string> lines);
|
||||
virtual ~PFunctionHandler();
|
||||
|
||||
virtual bool IsValid() { return fValid; }
|
||||
@@ -57,13 +54,13 @@ class PFunctionHandler
|
||||
bool fDebug;
|
||||
bool fValid;
|
||||
|
||||
string fFileName;
|
||||
std::string fFileName;
|
||||
|
||||
vector<double> fParam;
|
||||
vector<int> fMap;
|
||||
vector<string> fLines;
|
||||
std::vector<double> fParam;
|
||||
std::vector<int> fMap;
|
||||
std::vector<std::string> fLines;
|
||||
|
||||
vector<PFunction> fFuncs;
|
||||
std::vector<PFunction> fFuncs;
|
||||
|
||||
virtual bool ReadFile();
|
||||
virtual bool MapsAreValid();
|
||||
|
||||
@@ -17,17 +17,21 @@
|
||||
PAR 1.0 2.1 3.5 -0.87 0.87
|
||||
MAP 2 1 4 5
|
||||
FUNCTIONS
|
||||
#fun0 = cos(par1)
|
||||
#fun1 = sin(par3/(par1+map2))
|
||||
fun0 = cos(par1)
|
||||
fun1 = sin(par3/(par1+map2))
|
||||
#fun0 = 1.2+pi
|
||||
#fun1 = gamma_mu
|
||||
#fun2 = -par1*(sin(par2)*cos(par3)+((map1)))
|
||||
fun2 = -par1*(sin(par2)*cos(par3)+((map1)))
|
||||
#fun1 = cos(par1)
|
||||
#fun0 = par1 + map3 * cos(cos(par2 - map1))
|
||||
#fun8 = -par1*log(sin(par1)) + exp(-1.0*map2)
|
||||
#fun1 = par1 + map1 * (0.01355+par1*(2.1 - (-2.3 / 3.4)))
|
||||
#fun2 = par1 * par2 - map3
|
||||
fun3 = -3.2 + (par2-par1)/(map2+map3)
|
||||
#fun3 = -3.2 + (par2-par1)/(map2+map3)
|
||||
#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
|
||||
#----------------------------------------------
|
||||
|
||||
@@ -2,44 +2,43 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include "PFunctionHandler.h"
|
||||
|
||||
//-----------------------------------------------------
|
||||
void syntax()
|
||||
{
|
||||
cout << endl << "spirit_fcn_test [--file <filename> [--debug]] | [--help]";
|
||||
cout << endl << " without arguments: interactive mode";
|
||||
cout << endl << " --file <filename>: function block etc. from file";
|
||||
cout << endl << " --help: this help";
|
||||
cout << endl << " --debug: will print the ast tree only (no evaluatio)";
|
||||
cout << endl << endl;
|
||||
std::cout << std::endl << "spirit_fcn_test [--file <filename> [--debug]] | [--help]";
|
||||
std::cout << std::endl << " without arguments: interactive mode";
|
||||
std::cout << std::endl << " --file <filename>: function block etc. from file";
|
||||
std::cout << std::endl << " --help: this help";
|
||||
std::cout << std::endl << " --debug: will print the ast tree only (no evaluation)";
|
||||
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 ...";
|
||||
cout << endl << "you should provide a PAR, a MAP, and a FUNCTION block";
|
||||
cout << endl << " Map block:";
|
||||
cout << endl << " MAP <map1> <map2> ... <mapM>";
|
||||
cout << endl << " Parameter block:";
|
||||
cout << endl << " PAR <par1> <par2> ... <parN>";
|
||||
cout << endl << " Function Block:";
|
||||
cout << endl << " FUNCTION";
|
||||
cout << endl << " fun1 = <function1>";
|
||||
cout << endl << " fun2 = <function2>";
|
||||
cout << endl << " ...";
|
||||
cout << endl << " funX = <functionX>";
|
||||
cout << endl << " END";
|
||||
cout << endl << "to get out of the input handle type '.q'";
|
||||
cout << endl;
|
||||
std::cout << std::endl << "will handle input ...";
|
||||
std::cout << std::endl << "you should provide a PAR, a MAP, and a FUNCTION block";
|
||||
std::cout << std::endl << " Map block:";
|
||||
std::cout << std::endl << " MAP <map1> <map2> ... <mapM>";
|
||||
std::cout << std::endl << " Parameter block:";
|
||||
std::cout << std::endl << " PAR <par1> <par2> ... <parN>";
|
||||
std::cout << std::endl << " Function Block:";
|
||||
std::cout << std::endl << " FUNCTION";
|
||||
std::cout << std::endl << " fun1 = <function1>";
|
||||
std::cout << std::endl << " fun2 = <function2>";
|
||||
std::cout << std::endl << " ...";
|
||||
std::cout << std::endl << " funX = <functionX>";
|
||||
std::cout << std::endl << " END";
|
||||
std::cout << std::endl << "to get out of the input handle type '.q'";
|
||||
std::cout << std::endl;
|
||||
bool done = false;
|
||||
char str[128];
|
||||
do {
|
||||
cout << ">> ";
|
||||
cin.getline(str, sizeof(str));
|
||||
std::cout << ">> ";
|
||||
std::cin.getline(str, sizeof(str));
|
||||
if (!strcmp(str, ".q"))
|
||||
done = true;
|
||||
else
|
||||
@@ -76,39 +75,33 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
PFunctionHandler *fcnHandler = 0;
|
||||
std::unique_ptr<PFunctionHandler> fcnHandler;
|
||||
|
||||
if (inputFile) {
|
||||
fcnHandler = new PFunctionHandler(argv[2], debug);
|
||||
fcnHandler = std::make_unique<PFunctionHandler>(argv[2], debug);
|
||||
} else {
|
||||
vector<string> lines;
|
||||
std::vector<std::string> lines;
|
||||
handle_input(lines);
|
||||
fcnHandler = new PFunctionHandler(lines);
|
||||
fcnHandler = std::make_unique<PFunctionHandler>(lines);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool go_on = fcnHandler->IsValid();
|
||||
|
||||
if (go_on) {
|
||||
cout << endl << "will do the parsing ...";
|
||||
std::cout << std::endl << "will do the parsing ...";
|
||||
if (fcnHandler->DoParse()) {
|
||||
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++)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user