833 lines
30 KiB
C++
833 lines
30 KiB
C++
/***************************************************************************
|
|
|
|
PFunction.cpp
|
|
|
|
Author: Andreas Suter
|
|
e-mail: andreas.suter@psi.ch
|
|
|
|
$Id$
|
|
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* Copyright (C) 2007 by Andreas Suter *
|
|
* andreas.suter@psi.c *
|
|
* *
|
|
* 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. *
|
|
***************************************************************************/
|
|
|
|
#include <cstdio>
|
|
#include <cmath>
|
|
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
#include <boost/algorithm/string/trim.hpp> // for stripping leading whitespace in std::string
|
|
|
|
#include <boost/math/special_functions/acosh.hpp>
|
|
#include <boost/math/special_functions/asinh.hpp>
|
|
#include <boost/math/special_functions/atanh.hpp>
|
|
|
|
#include "PFunction.h"
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
* info is an abstract syntax tree (AST) generate by the spirit parse library
|
|
* (see http://spirit.sourceforge.net/distrib/spirit_1_8_5/libs/spirit/doc/trees.html).
|
|
* It contains a single parsed msr-function in an ascii representation.
|
|
* Here it takes the from
|
|
* assignment (root node)
|
|
* |_ 'FUNx'
|
|
* |_ '='
|
|
* |_ expression
|
|
* |_ ...
|
|
*
|
|
* Since it would be inefficient to evaluate this AST directly it is transferred to
|
|
* a more efficient tree fFuncs here in the constructor.
|
|
*
|
|
* \param info AST parse tree holding a single parsed msr-function in an ascii representation
|
|
* \param param the parameter vector
|
|
* \param map the map vector
|
|
*/
|
|
PFunction::PFunction(tree_parse_info<> info, vector<double> param, vector<int> map, bool debug) :
|
|
fDebug(debug)
|
|
{
|
|
cout << endl << "in PFunction ...";
|
|
|
|
fInfo = info;
|
|
fParam = param;
|
|
fMap = map;
|
|
|
|
// init class variables
|
|
fValid = true;
|
|
fFuncNo = -1;
|
|
|
|
// print out ast tree
|
|
if (fDebug) {
|
|
PrintTree(info);
|
|
return;
|
|
}
|
|
|
|
// check parameter and map range
|
|
if (!CheckParameterAndMapRange()) {
|
|
fValid = false;
|
|
return;
|
|
}
|
|
|
|
// generate function evaluation tree
|
|
if (!GenerateFuncEvalTree()) {
|
|
fValid = false;
|
|
return;
|
|
}
|
|
|
|
EvaluateTree(info);
|
|
|
|
cout << endl << "fFuncString: '" << fFuncString << "'";
|
|
cout << endl;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Destructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*/
|
|
PFunction::~PFunction()
|
|
{
|
|
// cout << endl << "in ~PFunction ...";
|
|
fParam.clear();
|
|
fMap.clear();
|
|
|
|
CleanupFuncEvalTree();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// InitNode (protected)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
* \param node
|
|
*/
|
|
void PFunction::InitNode(PFuncTreeNode &node)
|
|
{
|
|
node.fID = 0;
|
|
node.fOperatorTag = 0;
|
|
node.fFunctionTag = 0;
|
|
node.fIvalue = 0;
|
|
node.fSign = false;
|
|
node.fDvalue = 0.0;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// CheckParameterRange (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
*/
|
|
bool PFunction::CheckParameterAndMapRange()
|
|
{
|
|
return CheckParameterAndMapInTree(fInfo.trees.begin());
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// CheckParameterAndMapInTree (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p> walk through the tree and check if the parameter found
|
|
* are within a valid range given by the size of fParam.
|
|
*
|
|
* \param i
|
|
*/
|
|
bool PFunction::CheckParameterAndMapInTree(iter_t const& i)
|
|
{
|
|
bool success = true;
|
|
int value;
|
|
|
|
if (i->value.id() == PFunctionGrammar::funLabelID) {
|
|
assert(i->children.size() == 0);
|
|
SetFuncNo(i);
|
|
} else if (i->value.id() == PFunctionGrammar::parameterID) {
|
|
assert(i->children.size() == 0);
|
|
string str(i->value.begin(), i->value.end());
|
|
boost::algorithm::trim(str);
|
|
cout << endl << "parameterID: value = '" << str << "'" << endl;
|
|
|
|
bool minus_sign_present = false;
|
|
if (str[0] == '-')
|
|
minus_sign_present = true;
|
|
cout << endl << ">> minus_sign_present = " << minus_sign_present;
|
|
if (minus_sign_present)
|
|
sscanf(str.c_str(), "-PAR%d", &value);
|
|
else
|
|
sscanf(str.c_str(), "PAR%d", &value);
|
|
cout << endl << ">> value = " << value << ", fParam.size() = " << fParam.size() << endl << "----";
|
|
if (value > (int)fParam.size()) { // parameter number found > number of parameters
|
|
cout << endl << "**ERROR**: found parameter " << str << " with only " << fParam.size() << " parameters present?!?";
|
|
fValid = false;
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::mapID) {
|
|
assert(i->children.size() == 0);
|
|
string str(i->value.begin(), i->value.end());
|
|
cout << endl << "mapID: value = " << str << endl;
|
|
sscanf(str.c_str(), "MAP%d", &value);
|
|
//cout << endl << ">> value = " << value << ", fParam.size() = " << fParam.size();
|
|
if (value > (int)fMap.size()) { // parameter number found > number of parameters
|
|
cout << endl << "**ERROR**: found map " << str << " with only " << fMap.size() << " maps present?!?";
|
|
fValid = false;
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::functionID) {
|
|
assert(i->children.size() == 3);
|
|
// i: '(', 'expression', ')'
|
|
success = CheckParameterAndMapInTree(i->children.begin()+1); // thats the real stuff
|
|
} else if (i->value.id() == PFunctionGrammar::factorID) {
|
|
// i: real | parameter | map | function | expression
|
|
assert(i->children.size() == 1);
|
|
success = CheckParameterAndMapInTree(i->children.begin());
|
|
} else if (i->value.id() == PFunctionGrammar::termID) {
|
|
// '*' or '/' i: lhs, rhs
|
|
assert(i->children.size() == 2);
|
|
success = CheckParameterAndMapInTree(i->children.begin());
|
|
success = CheckParameterAndMapInTree(i->children.begin()+1);
|
|
} else if (i->value.id() == PFunctionGrammar::expressionID) {
|
|
// '+' or '-' i: lhs, rhs
|
|
assert(i->children.size() == 2);
|
|
success = CheckParameterAndMapInTree(i->children.begin());
|
|
success = CheckParameterAndMapInTree(i->children.begin()+1);
|
|
} else if (i->value.id() == PFunctionGrammar::assignmentID) {
|
|
// i: 'FUNx', '=', 'expression'
|
|
assert(i->children.size() == 3);
|
|
success = CheckParameterAndMapInTree(i->children.begin()); // FUNx
|
|
success = CheckParameterAndMapInTree(i->children.begin()+2); // this is the real stuff
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// SetFuncNo (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
* \param i
|
|
*/
|
|
bool PFunction::SetFuncNo(iter_t const& i)
|
|
{
|
|
int funNo = -1;
|
|
int status;
|
|
bool success = true;
|
|
|
|
// get string from tree
|
|
string str(i->value.begin(), i->value.end());
|
|
|
|
// extract function number from string
|
|
status = sscanf(str.c_str(), "FUN%d", &funNo);
|
|
//cout << endl << "SetFuncNo: status = " << status << ", funNo = " << funNo;
|
|
if (status == 1) { // found 1 int
|
|
fFuncNo = funNo;
|
|
} else { // wrong string
|
|
success = false;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// GenerateFuncEvalTree (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
*/
|
|
bool PFunction::GenerateFuncEvalTree()
|
|
{
|
|
InitNode(fFunc);
|
|
FillFuncEvalTree(fInfo.trees.begin(), fFunc);
|
|
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// FillFuncEvalTree (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
*/
|
|
void PFunction::FillFuncEvalTree(iter_t const& i, PFuncTreeNode &node)
|
|
{
|
|
double dvalue;
|
|
int ivalue;
|
|
int status;
|
|
string str;
|
|
PFuncTreeNode child;
|
|
|
|
InitNode(child);
|
|
|
|
if (i->value.id() == PFunctionGrammar::realID) { // handle number
|
|
str = string(i->value.begin(), i->value.end()); // get string
|
|
status = sscanf(str.c_str(), "%lf", &dvalue); // convert string to double
|
|
node.fID = PFunctionGrammar::realID; // keep the ID
|
|
node.fDvalue = dvalue; // keep the value
|
|
cout << endl << ">> realID: value = " << dvalue;
|
|
} else if (i->value.id() == PFunctionGrammar::constPiID) { // handle constant pi
|
|
node.fID = PFunctionGrammar::constPiID; // keep the ID
|
|
node.fDvalue = 3.14159265358979323846; // keep the value
|
|
} else if (i->value.id() == PFunctionGrammar::constGammaMuID) { // handle constant gamma_mu
|
|
node.fID = PFunctionGrammar::constGammaMuID; // keep the ID
|
|
node.fDvalue = 0.0135538817; // keep the value
|
|
} else if (i->value.id() == PFunctionGrammar::parameterID) { // handle parameter number
|
|
str = string(i->value.begin(), i->value.end()); // get string
|
|
if (strstr(str.c_str(), "-")) {
|
|
node.fSign = true;
|
|
status = sscanf(str.c_str(), " -PAR%d", &ivalue); // convert string to parameter number
|
|
} else {
|
|
status = sscanf(str.c_str(), " PAR%d", &ivalue); // convert string to parameter number
|
|
}
|
|
node.fID = PFunctionGrammar::parameterID; // keep the ID
|
|
node.fIvalue = ivalue; // keep the value
|
|
cout << endl << ">> parameterID: value = " << ivalue;
|
|
} else if (i->value.id() == PFunctionGrammar::mapID) { // handle map number
|
|
str = string(i->value.begin(), i->value.end()); // get string
|
|
status = sscanf(str.c_str(), "MAP%d", &ivalue); // convert string to map number
|
|
node.fID = PFunctionGrammar::mapID; // keep the ID
|
|
node.fIvalue = ivalue; // keep the value
|
|
// cout << endl << ">> mapID: value = " << ivalue;
|
|
} else if (i->value.id() == PFunctionGrammar::functionID) { // handle function like cos ...
|
|
// keep the id
|
|
node.fID = PFunctionGrammar::functionID;
|
|
// keep function tag
|
|
// i: '(', 'expression', ')'
|
|
str = string(i->value.begin(), i->value.end()); // get string
|
|
// cout << endl << ">> functionID: value = " << str;
|
|
if (!strcmp(str.c_str(), "COS"))
|
|
node.fFunctionTag = FUN_COS;
|
|
else if (!strcmp(str.c_str(), "SIN"))
|
|
node.fFunctionTag = FUN_SIN;
|
|
else if (!strcmp(str.c_str(), "TAN"))
|
|
node.fFunctionTag = FUN_TAN;
|
|
else if (!strcmp(str.c_str(), "COSH"))
|
|
node.fFunctionTag = FUN_COSH;
|
|
else if (!strcmp(str.c_str(), "SINH"))
|
|
node.fFunctionTag = FUN_SINH;
|
|
else if (!strcmp(str.c_str(), "TANH"))
|
|
node.fFunctionTag = FUN_TANH;
|
|
else if (!strcmp(str.c_str(), "ACOS"))
|
|
node.fFunctionTag = FUN_ACOS;
|
|
else if (!strcmp(str.c_str(), "ASIN"))
|
|
node.fFunctionTag = FUN_ASIN;
|
|
else if (!strcmp(str.c_str(), "ATAN"))
|
|
node.fFunctionTag = FUN_ATAN;
|
|
else if (!strcmp(str.c_str(), "ACOSH"))
|
|
node.fFunctionTag = FUN_ACOSH;
|
|
else if (!strcmp(str.c_str(), "ASINH"))
|
|
node.fFunctionTag = FUN_ASINH;
|
|
else if (!strcmp(str.c_str(), "ATANH"))
|
|
node.fFunctionTag = FUN_ATANH;
|
|
else if (!strcmp(str.c_str(), "LOG"))
|
|
node.fFunctionTag = FUN_LOG;
|
|
else if (!strcmp(str.c_str(), "LN"))
|
|
node.fFunctionTag = FUN_LN;
|
|
else if (!strcmp(str.c_str(), "EXP"))
|
|
node.fFunctionTag = FUN_EXP;
|
|
else {
|
|
cout << endl << "**PANIC ERROR**: function " << str << " doesn't exist, but you never should have reached this point!";
|
|
assert(0);
|
|
}
|
|
// add node
|
|
node.children.push_back(child);
|
|
// i: '(', 'expression', ')'
|
|
FillFuncEvalTree(i->children.begin()+1, node.children[0]);
|
|
} else if (i->value.id() == PFunctionGrammar::factorID) {
|
|
// cout << endl << ">> factorID";
|
|
// keep the id
|
|
node.fID = PFunctionGrammar::factorID;
|
|
// add child lhs
|
|
node.children.push_back(child);
|
|
FillFuncEvalTree(i->children.begin(), node.children[0]);
|
|
} else if (i->value.id() == PFunctionGrammar::termID) {
|
|
// keep the id
|
|
node.fID = PFunctionGrammar::termID;
|
|
// keep operator tag
|
|
if (*i->value.begin() == '*')
|
|
node.fOperatorTag = OP_MUL;
|
|
else
|
|
node.fOperatorTag = OP_DIV;
|
|
/*
|
|
if (node.fOperatorTag == OP_MUL)
|
|
cout << endl << ">> termID: value = *";
|
|
else
|
|
cout << endl << ">> termID: value = /";
|
|
*/
|
|
// add child lhs
|
|
node.children.push_back(child);
|
|
FillFuncEvalTree(i->children.begin(), node.children[0]);
|
|
// add child rhs
|
|
node.children.push_back(child);
|
|
FillFuncEvalTree(i->children.begin()+1, node.children[1]);
|
|
} else if (i->value.id() == PFunctionGrammar::expressionID) { // handle expression
|
|
// keep the id
|
|
node.fID = PFunctionGrammar::expressionID;
|
|
// keep operator tag
|
|
if (*i->value.begin() == '+')
|
|
node.fOperatorTag = OP_ADD;
|
|
else
|
|
node.fOperatorTag = OP_SUB;
|
|
/*
|
|
if (node.fOperatorTag == OP_ADD)
|
|
cout << endl << ">> expressionID: value = +";
|
|
else
|
|
cout << endl << ">> expressionID: value = -";
|
|
*/
|
|
// add child lhs
|
|
node.children.push_back(child);
|
|
FillFuncEvalTree(i->children.begin(), node.children[0]);
|
|
// add child rhs
|
|
node.children.push_back(child);
|
|
FillFuncEvalTree(i->children.begin()+1, node.children[1]);
|
|
} else if (i->value.id() == PFunctionGrammar::assignmentID) {
|
|
// nothing to be done except to pass the next element in the ast
|
|
// i: 'funx', '=', 'expression'
|
|
FillFuncEvalTree(i->children.begin()+2, node);
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Eval (public)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
*/
|
|
double PFunction::Eval()
|
|
{
|
|
return EvalNode(fFunc);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// EvalNode (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
* \param node
|
|
*/
|
|
double PFunction::EvalNode(PFuncTreeNode &node)
|
|
{
|
|
if (node.fID == PFunctionGrammar::realID) {
|
|
return node.fDvalue;
|
|
} else if (node.fID == PFunctionGrammar::constPiID) {
|
|
return node.fDvalue;
|
|
} else if (node.fID == PFunctionGrammar::constGammaMuID) {
|
|
return node.fDvalue;
|
|
} else if (node.fID == PFunctionGrammar::parameterID) {
|
|
double dval;
|
|
if (node.fSign)
|
|
dval = -fParam[node.fIvalue-1];
|
|
else
|
|
dval = fParam[node.fIvalue-1];
|
|
return dval;
|
|
} else if (node.fID == PFunctionGrammar::mapID) {
|
|
return fParam[fMap[node.fIvalue-1]-1];
|
|
} else if (node.fID == PFunctionGrammar::functionID) {
|
|
if (node.fFunctionTag == FUN_COS) {
|
|
return cos(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_SIN) {
|
|
return sin(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_TAN) {
|
|
return tan(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_COSH) {
|
|
return cosh(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_SINH) {
|
|
return sinh(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_TANH) {
|
|
return tanh(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_ACOS) {
|
|
return acos(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_ASIN) {
|
|
return asin(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_ATAN) {
|
|
return atan(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_ACOSH) {
|
|
return boost::math::acosh(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_ASINH) {
|
|
return boost::math::asinh(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_ATANH) {
|
|
return boost::math::atanh(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_LOG) {
|
|
return log(EvalNode(node.children[0]))/log(10.0);
|
|
} else if (node.fFunctionTag == FUN_LN) {
|
|
return log(EvalNode(node.children[0]));
|
|
} else if (node.fFunctionTag == FUN_EXP) {
|
|
return exp(EvalNode(node.children[0]));
|
|
} else {
|
|
cout << endl << "**PANIC ERROR**: PFunction::EvalNode: node.fID == PFunctionGrammar::functionID: you never should have reached this point!" << endl;
|
|
assert(0);
|
|
}
|
|
} else if (node.fID == PFunctionGrammar::factorID) {
|
|
return EvalNode(node.children[0]);
|
|
} else if (node.fID == PFunctionGrammar::termID) {
|
|
if (node.fOperatorTag == OP_MUL) {
|
|
return EvalNode(node.children[0]) * EvalNode(node.children[1]);
|
|
} else {
|
|
double denominator = EvalNode(node.children[1]);
|
|
if (denominator == 0.0) {
|
|
cout << endl << "**PANIC ERROR**: PFunction::EvalNode: division by 0.0" << endl;
|
|
assert(0);
|
|
}
|
|
return EvalNode(node.children[0]) / denominator;
|
|
}
|
|
} else if (node.fID == PFunctionGrammar::expressionID) {
|
|
if (node.fOperatorTag == OP_ADD) {
|
|
return EvalNode(node.children[0]) + EvalNode(node.children[1]);
|
|
} else {
|
|
return EvalNode(node.children[0]) - EvalNode(node.children[1]);
|
|
}
|
|
} else {
|
|
cout << endl << "**PANIC ERROR**: PFunction::EvalNode: you never should have reached this point!" << endl;
|
|
assert(0);
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// CleanupFuncEvalTree (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
*/
|
|
void PFunction::CleanupFuncEvalTree()
|
|
{
|
|
// clean up all children
|
|
CleanupNode(fFunc);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// CleanupNode (protected)
|
|
//-------------------------------------------------------------
|
|
/**
|
|
* <p>
|
|
*
|
|
* \param node
|
|
*/
|
|
void PFunction::CleanupNode(PFuncTreeNode &node)
|
|
{
|
|
if (node.children.size() != 0) {
|
|
for (unsigned int i=0; i<node.children.size(); i++) {
|
|
CleanupNode(node.children[i]);
|
|
}
|
|
node.children.clear();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// EvaluateTree (protected)
|
|
//-------------------------------------------------------------
|
|
long PFunction::EvaluateTree(tree_parse_info<> info)
|
|
{
|
|
return EvalTreeExpression(info.trees.begin());
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// EvalTreeExpression (protected)
|
|
//-------------------------------------------------------------
|
|
long PFunction::EvalTreeExpression(iter_t const& i)
|
|
{
|
|
static int counter = 0;
|
|
static int termOp = 0;
|
|
|
|
cout << endl << counter <<": in EvalExpression. i->value = '" <<
|
|
string(i->value.begin(), i->value.end()) <<
|
|
"' i->children.size() = " << i->children.size() << endl;
|
|
|
|
if (i->value.id() == PFunctionGrammar::realID) {
|
|
assert(i->children.size() == 0);
|
|
cout << endl << "realID: children = " << i->children.size();
|
|
cout << endl << "realID: " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
if (*i->value.begin() == '-')
|
|
fFuncString += "(";
|
|
fFuncString += string(i->value.begin(), i->value.end());
|
|
if (*i->value.begin() == '-')
|
|
fFuncString += ")";
|
|
} else if (i->value.id() == PFunctionGrammar::constPiID) {
|
|
assert(i->children.size() == 0);
|
|
cout << endl << "constPiID: children = " << i->children.size();
|
|
cout << endl << "constPiID: " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
fFuncString += string(i->value.begin(), i->value.end());
|
|
} else if (i->value.id() == PFunctionGrammar::constGammaMuID) {
|
|
assert(i->children.size() == 0);
|
|
cout << endl << "constGammaMuID: children = " << i->children.size();
|
|
cout << endl << "constGammaMuID: " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
fFuncString += string(i->value.begin(), i->value.end());
|
|
} else if (i->value.id() == PFunctionGrammar::funLabelID) {
|
|
assert(i->children.size() == 0);
|
|
//SetFuncNo(i);
|
|
cout << endl << "funLabelID: children = " << i->children.size();
|
|
cout << endl << "funLabelID: value = " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
fFuncString += string(i->value.begin(), i->value.end()); // funx
|
|
} else if (i->value.id() == PFunctionGrammar::parameterID) {
|
|
assert(i->children.size() == 0);
|
|
cout << endl << "parameterID: children = " << i->children.size();
|
|
cout << endl << "parameterID: value = " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
fFuncString += string(i->value.begin(), i->value.end());
|
|
} else if (i->value.id() == PFunctionGrammar::mapID) {
|
|
assert(i->children.size() == 0);
|
|
cout << endl << "mapID: children = " << i->children.size();
|
|
cout << endl << "mapID: value = " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
fFuncString += string(i->value.begin(), i->value.end());
|
|
} else if (i->value.id() == PFunctionGrammar::functionID) {
|
|
assert(i->children.size() == 3);
|
|
cout << endl << "functionID: children = " << i->children.size();
|
|
cout << endl << "functionID: value = " << string(i->value.begin(), i->value.end());
|
|
cout << endl << "-----";
|
|
// '(', expression, ')'
|
|
counter++;
|
|
fFuncString += string(i->value.begin(), i->value.end());
|
|
fFuncString += "(";
|
|
EvalTreeExpression(i->children.begin()+1); // the real stuff
|
|
fFuncString += ")";
|
|
counter--;
|
|
} else if (i->value.id() == PFunctionGrammar::factorID) {
|
|
cout << endl << "factorID: children = " << i->children.size();
|
|
counter++;
|
|
return EvalTreeExpression(i->children.begin());
|
|
counter--;
|
|
} else if (i->value.id() == PFunctionGrammar::termID) {
|
|
cout << endl << "termID: children = " << i->children.size();
|
|
counter++;
|
|
termOp++;
|
|
if (*i->value.begin() == '*') {
|
|
cout << endl << "termID: '*'";
|
|
assert(i->children.size() == 2);
|
|
EvalTreeExpression(i->children.begin());
|
|
fFuncString += " * ";
|
|
EvalTreeExpression(i->children.begin()+1);
|
|
} else if (*i->value.begin() == '/') {
|
|
cout << endl << "termID: '/'";
|
|
assert(i->children.size() == 2);
|
|
EvalTreeExpression(i->children.begin());
|
|
fFuncString += " / ";
|
|
EvalTreeExpression(i->children.begin()+1);
|
|
} else {
|
|
assert(0);
|
|
}
|
|
termOp--;
|
|
counter--;
|
|
} else if (i->value.id() == PFunctionGrammar::expressionID) {
|
|
cout << endl << "expressionID: children = " << i->children.size();
|
|
if (termOp > 0)
|
|
fFuncString += "(";
|
|
if (*i->value.begin() == '+') {
|
|
cout << endl << "expressionID: '+'";
|
|
assert(i->children.size() == 2);
|
|
counter++;
|
|
EvalTreeExpression(i->children.begin());
|
|
fFuncString += " + ";
|
|
EvalTreeExpression(i->children.begin()+1);
|
|
counter--;
|
|
} else if (*i->value.begin() == '-') {
|
|
cout << endl << "expressionID: '-'";
|
|
assert(i->children.size() == 2);
|
|
counter++;
|
|
EvalTreeExpression(i->children.begin());
|
|
fFuncString += " - ";
|
|
EvalTreeExpression(i->children.begin()+1);
|
|
counter--;
|
|
} else {
|
|
assert(0);
|
|
}
|
|
if (termOp > 0)
|
|
fFuncString += ")";
|
|
} else if (i->value.id() == PFunctionGrammar::assignmentID) {
|
|
cout << endl << "assignmentID: children = " << i->children.size();
|
|
assert(i->children.size() == 3);
|
|
counter++;
|
|
EvalTreeExpression(i->children.begin());
|
|
EvalTreeExpression(i->children.begin()+1); // this is the string "="
|
|
EvalTreeExpression(i->children.begin()+2); // this is the real stuff
|
|
counter--;
|
|
} else if (*i->value.begin() == '=') {
|
|
cout << endl << "'=' in assignment";
|
|
fFuncString += " = ";
|
|
} else {
|
|
assert(0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// PrintTree (protected)
|
|
//-------------------------------------------------------------
|
|
long PFunction::PrintTree(tree_parse_info<> info)
|
|
{
|
|
cout << endl << "********************************************";
|
|
cout << endl << ">> PrintTree";
|
|
cout << endl << "********************************************";
|
|
long value = PrintTreeExpression(info.trees.begin());
|
|
cout << endl << "********************************************";
|
|
cout << endl;
|
|
return value;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// PrintTreeExpression (protected)
|
|
//-------------------------------------------------------------
|
|
long PFunction::PrintTreeExpression(iter_t const& i)
|
|
{
|
|
string str;
|
|
iter_t j;
|
|
|
|
if (i->value.id() == PFunctionGrammar::realID) {
|
|
if (i->children.size() == 0) {
|
|
str = string(i->value.begin(), i->value.end());
|
|
cout << endl << ">> " << str;
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::funLabelID) {
|
|
if (i->children.size() == 0) {
|
|
j = i->children.begin();
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << ">> " << str;
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::parameterID) {
|
|
if (i->children.size() == 0) {
|
|
str = string(i->value.begin(), i->value.end());
|
|
cout << endl << ">> " << str;
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::mapID) {
|
|
if (i->children.size() == 0) {
|
|
str = string(i->value.begin(), i->value.end());
|
|
cout << endl << ">> " << str;
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::functionID) {
|
|
// i: '(', 'expression', ')'
|
|
str = string(i->value.begin(), i->value.end());
|
|
cout << endl << ">> " << str;
|
|
if (i->children.size() == 3) {
|
|
j = i->children.begin();
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << ">> " << str;
|
|
PrintTreeExpression(i->children.begin()+1);
|
|
j = i->children.begin()+2;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << ">> " << str;
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::factorID) {
|
|
// i: real | parameter | map | function | expression
|
|
if (i->children.size() == 1) {
|
|
PrintTreeExpression(i->children.begin());
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::termID) {
|
|
// '*' or '/' i: lhs, rhs
|
|
str = string(i->value.begin(), i->value.end());
|
|
cout << endl << ">> " << str;
|
|
if (i->children.size() == 2) {
|
|
PrintTreeExpression(i->children.begin());
|
|
PrintTreeExpression(i->children.begin()+1);
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::expressionID) {
|
|
// '+' or '-' i: lhs, rhs
|
|
str = string(i->value.begin(), i->value.end());
|
|
cout << endl << ">> " << str;
|
|
if (i->children.size() == 2) {
|
|
PrintTreeExpression(i->children.begin());
|
|
PrintTreeExpression(i->children.begin()+1);
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else if (i->value.id() == PFunctionGrammar::assignmentID) {
|
|
// i: 'funx', '=', 'expression'
|
|
if (i->children.size() == 3) {
|
|
j = i->children.begin();
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << ">> " << str;
|
|
j = i->children.begin()+1;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << ">> " << str;
|
|
PrintTreeExpression(i->children.begin()+2);
|
|
} else {
|
|
for (unsigned int k=0; k<i->children.size(); k++) {
|
|
j = i->children.begin()+k;
|
|
str = string(j->value.begin(), j->value.end());
|
|
cout << endl << "!> " << str;
|
|
}
|
|
}
|
|
} else {
|
|
cout << endl << "this point should never have been reached :-(" << endl;
|
|
assert(0);
|
|
}
|
|
return 0;
|
|
}
|