add missing files.
This commit is contained in:
parent
d81a10e450
commit
5755331273
103
src/musredit_qt5/mupp/var/include/PAnnotation.hpp
Normal file
103
src/musredit_qt5/mupp/var/include/PAnnotation.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
/***************************************************************************
|
||||
|
||||
PAnnotation.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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 _PANNOTATION_HPP_
|
||||
#define _PANNOTATION_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include "PAst.hpp"
|
||||
|
||||
namespace mupp
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The annotation handler links the AST to a map of iterator positions
|
||||
// for the purpose of subsequent semantic error handling when the
|
||||
// program is being compiled.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct PAnnotation
|
||||
{
|
||||
template <typename, typename>
|
||||
struct result { typedef void type; };
|
||||
|
||||
std::vector<Iterator>& iters;
|
||||
PAnnotation(std::vector<Iterator>& iters) : iters(iters) {}
|
||||
|
||||
struct set_id
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
int id;
|
||||
set_id(int id) : id(id) {}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T& x) const
|
||||
{
|
||||
this->dispatch(x, boost::is_base_of<ast::tagged, T>());
|
||||
}
|
||||
|
||||
// This will catch all nodes except those inheriting from ast::tagged
|
||||
template <typename T>
|
||||
void dispatch(T& x, boost::mpl::false_) const
|
||||
{
|
||||
// (no-op) no need for tags
|
||||
}
|
||||
|
||||
// This will catch all nodes inheriting from ast::tagged
|
||||
template <typename T>
|
||||
void dispatch(T& x, boost::mpl::true_) const
|
||||
{
|
||||
x.id = id;
|
||||
}
|
||||
};
|
||||
|
||||
void operator()(ast::operand& ast, Iterator pos) const
|
||||
{
|
||||
int id = iters.size();
|
||||
iters.push_back(pos);
|
||||
boost::apply_visitor(set_id(id), ast);
|
||||
}
|
||||
|
||||
void operator()(ast::assignment& ast, Iterator pos) const
|
||||
{
|
||||
int id = iters.size();
|
||||
iters.push_back(pos);
|
||||
ast.lhs.id = id;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _PANNOTATION_HPP_
|
||||
|
113
src/musredit_qt5/mupp/var/include/PErrorHandler.hpp
Normal file
113
src/musredit_qt5/mupp/var/include/PErrorHandler.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
/***************************************************************************
|
||||
|
||||
PErrorHandler.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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 _PERROR_HANDLER_HPP_
|
||||
#define _PERROR_HANDLER_HPP_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace mupp
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The error handler
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct PErrorHandler
|
||||
{
|
||||
template <typename, typename, typename>
|
||||
struct result { typedef void type; };
|
||||
|
||||
PErrorHandler(Iterator first, Iterator last)
|
||||
: first(first), last(last) {}
|
||||
|
||||
template <typename Message, typename What>
|
||||
void operator()(
|
||||
Message const& message,
|
||||
What const& what,
|
||||
Iterator err_pos) const
|
||||
{
|
||||
int line;
|
||||
Iterator line_start = get_pos(err_pos, line);
|
||||
if (err_pos != last) {
|
||||
std::cout << message << what << ':' << std::endl;
|
||||
std::cout << get_line(line_start) << std::endl;
|
||||
for (; line_start != err_pos; ++line_start)
|
||||
std::cout << ' ';
|
||||
std::cout << "^~~" << std::endl;
|
||||
} else {
|
||||
std::cout << "**ERROR** Unexpected end of file. ";
|
||||
std::cout << message << what << " line " << line << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Iterator get_pos(Iterator err_pos, int& line) const
|
||||
{
|
||||
line = 1;
|
||||
Iterator i = first;
|
||||
Iterator line_start = first;
|
||||
while (i != err_pos) {
|
||||
bool eol = false;
|
||||
if (i != err_pos && *i == '\r') { // CR
|
||||
eol = true;
|
||||
line_start = ++i;
|
||||
}
|
||||
if (i != err_pos && *i == '\n') { // LF
|
||||
eol = true;
|
||||
line_start = ++i;
|
||||
}
|
||||
if (eol)
|
||||
++line;
|
||||
else
|
||||
++i;
|
||||
}
|
||||
return line_start;
|
||||
}
|
||||
|
||||
std::string get_line(Iterator err_pos) const
|
||||
{
|
||||
Iterator i = err_pos;
|
||||
// position i to the next EOL
|
||||
while (i != last && (*i != '\r' && *i != '\n'))
|
||||
++i;
|
||||
return std::string(err_pos, i);
|
||||
}
|
||||
|
||||
Iterator first;
|
||||
Iterator last;
|
||||
std::vector<Iterator> iters;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //_PERROR_HANDLER_HPP_
|
||||
|
83
src/musredit_qt5/mupp/var/include/PExpression.hpp
Normal file
83
src/musredit_qt5/mupp/var/include/PExpression.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
|
||||
PExpression.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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 _PEXPRESSION_HPP_
|
||||
#define _PEXPRESSION_HPP_
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Spirit v2.5 allows you to suppress automatic generation
|
||||
// of predefined terminals to speed up complation. With
|
||||
// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
|
||||
// responsible in creating instances of the terminals that
|
||||
// you need (e.g. see qi::uint_type uint_ below).
|
||||
#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment this if you want to enable debugging
|
||||
// #define BOOST_SPIRIT_QI_DEBUG
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include "PAst.hpp"
|
||||
#include "PErrorHandler.hpp"
|
||||
#include "PSkipper.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace mupp { namespace parser
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The expression grammar
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct PExpression : qi::grammar<Iterator, ast::expression(), PSkipper<Iterator> >
|
||||
{
|
||||
PExpression(PErrorHandler<Iterator>& error_handler);
|
||||
|
||||
qi::symbols<char, ast::optoken> additive_op, multiplicative_op, unary_op;
|
||||
qi::symbols<char, ast::funid> fun_tok;
|
||||
|
||||
qi::rule<Iterator, ast::expression(), PSkipper<Iterator> > expr;
|
||||
qi::rule<Iterator, ast::expression(), PSkipper<Iterator> > additive_expr;
|
||||
qi::rule<Iterator, ast::expression(), PSkipper<Iterator> > multiplicative_expr;
|
||||
qi::rule<Iterator, ast::operand(), PSkipper<Iterator> > unary_expr;
|
||||
qi::rule<Iterator, ast::operand(), PSkipper<Iterator> > primary_expr;
|
||||
qi::rule<Iterator, std::string(), PSkipper<Iterator> > identifier;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // _PEXPRESSION_HPP_
|
||||
|
||||
|
155
src/musredit_qt5/mupp/var/include/PExpressionDef.hpp
Normal file
155
src/musredit_qt5/mupp/var/include/PExpressionDef.hpp
Normal file
@ -0,0 +1,155 @@
|
||||
/***************************************************************************
|
||||
|
||||
PExpressionDef.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PExpression.hpp"
|
||||
#include "PErrorHandler.hpp"
|
||||
#include "PAnnotation.hpp"
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
|
||||
namespace mupp { namespace parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
PExpression<Iterator>::PExpression(PErrorHandler<Iterator>& error_handler)
|
||||
: PExpression::base_type(expr)
|
||||
{
|
||||
qi::_1_type _1;
|
||||
qi::_2_type _2;
|
||||
qi::_3_type _3;
|
||||
qi::_4_type _4;
|
||||
|
||||
qi::char_type char_;
|
||||
qi::double_type double_;
|
||||
qi::_val_type _val;
|
||||
qi::raw_type raw;
|
||||
qi::lexeme_type lexeme;
|
||||
qi::alpha_type alpha;
|
||||
qi::alnum_type alnum;
|
||||
|
||||
using qi::on_error;
|
||||
using qi::on_success;
|
||||
using qi::fail;
|
||||
using boost::phoenix::function;
|
||||
|
||||
typedef function<mupp::PErrorHandler<Iterator> > error_handler_function;
|
||||
typedef function<mupp::PAnnotation<Iterator> > annotation_function;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Tokens
|
||||
additive_op.add
|
||||
("+", ast::op_plus)
|
||||
("-", ast::op_minus)
|
||||
;
|
||||
|
||||
multiplicative_op.add
|
||||
("*", ast::op_times)
|
||||
("/", ast::op_divide)
|
||||
;
|
||||
|
||||
unary_op.add
|
||||
("+", ast::op_positive)
|
||||
("-", ast::op_negative)
|
||||
;
|
||||
|
||||
fun_tok.add
|
||||
("max", ast::fun_max)
|
||||
("min", ast::fun_min)
|
||||
("abs", ast::fun_abs)
|
||||
("sin", ast::fun_sin)
|
||||
("cos", ast::fun_cos)
|
||||
("tan", ast::fun_tan)
|
||||
("exp", ast::fun_exp)
|
||||
("log", ast::fun_log)
|
||||
("ln", ast::fun_ln)
|
||||
;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Grammar
|
||||
expr =
|
||||
additive_expr.alias()
|
||||
;
|
||||
|
||||
additive_expr =
|
||||
multiplicative_expr
|
||||
>> *(additive_op > multiplicative_expr)
|
||||
;
|
||||
|
||||
multiplicative_expr =
|
||||
unary_expr
|
||||
>> *(multiplicative_op > unary_expr)
|
||||
;
|
||||
|
||||
unary_expr =
|
||||
primary_expr
|
||||
| (unary_op > primary_expr)
|
||||
;
|
||||
|
||||
primary_expr =
|
||||
double_
|
||||
| identifier
|
||||
| fun_tok > '(' > expr > ')'
|
||||
| "pow(" > expr > ',' > expr > ')'
|
||||
| '(' > expr > ')'
|
||||
;
|
||||
|
||||
identifier =
|
||||
raw[lexeme['$' >> *(alnum | '_')]]
|
||||
;
|
||||
|
||||
// name all the rules
|
||||
additive_expr.name("additive_expr");
|
||||
multiplicative_expr.name("multiplicative_expr");
|
||||
unary_expr.name("unary_expr");
|
||||
primary_expr.name("primary_expr");
|
||||
identifier.name("identifier");
|
||||
|
||||
// Debugging and error handling and reporting support.
|
||||
BOOST_SPIRIT_DEBUG_NODES(
|
||||
(expr)
|
||||
(additive_expr)
|
||||
(multiplicative_expr)
|
||||
(unary_expr)
|
||||
(primary_expr)
|
||||
(identifier)
|
||||
);
|
||||
|
||||
// Error handling: on error in expr, call error_handler.
|
||||
on_error<fail>(expr,
|
||||
error_handler_function(error_handler)(
|
||||
"**ERROR** Expecting ", _4, _3));
|
||||
|
||||
// Annotation: on success in primary_expr, call annotation.
|
||||
on_success(primary_expr,
|
||||
annotation_function(error_handler.iters)(_val, _1));
|
||||
}
|
||||
}}
|
||||
|
||||
|
159
src/musredit_qt5/mupp/var/include/PProgram.hpp
Normal file
159
src/musredit_qt5/mupp/var/include/PProgram.hpp
Normal file
@ -0,0 +1,159 @@
|
||||
/***************************************************************************
|
||||
|
||||
PProgram.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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 _PPROGRAM_HPP_
|
||||
#define _PPROGRAM_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "PAst.hpp"
|
||||
#include "PErrorHandler.hpp"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
|
||||
namespace mupp { namespace prog {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Variable Handler
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class PVarHandler
|
||||
{
|
||||
public:
|
||||
PVarHandler() : fName("") {}
|
||||
|
||||
void SetName(std::string name) { fName = name; }
|
||||
void SetValue(std::vector<double> &dval) { fValue = dval; }
|
||||
void SetValue(double dval, unsigned idx);
|
||||
void SetError(std::vector<double> &dval) { fError = dval; }
|
||||
void SetError(double dval, unsigned idx);
|
||||
|
||||
std::string GetName() { return fName; }
|
||||
unsigned int GetSize() { return (fValue.size() == fError.size()) ? fValue.size() : 0; }
|
||||
std::vector<double> GetValue() { return fValue; }
|
||||
double GetValue(unsigned int idx) { return (idx < fValue.size()) ? fValue[idx] : 0; }
|
||||
std::vector<double> GetError() { return fError; }
|
||||
double GetError(unsigned int idx) { return (idx < fError.size()) ? fError[idx] : 0; }
|
||||
|
||||
private:
|
||||
std::string fName;
|
||||
std::vector<double> fValue;
|
||||
std::vector<double> fError;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Program Semantic Analysis
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct PProgram
|
||||
{
|
||||
typedef bool result_type;
|
||||
|
||||
template <typename PErrorHandler>
|
||||
PProgram(PErrorHandler& error_handler_)
|
||||
{
|
||||
using namespace boost::phoenix::arg_names;
|
||||
namespace phx = boost::phoenix;
|
||||
using boost::phoenix::function;
|
||||
error_handler = function<PErrorHandler>(error_handler_)(
|
||||
"**ERROR** ", _2, phx::cref(error_handler_.iters)[_1]);
|
||||
}
|
||||
|
||||
bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
|
||||
bool operator()(double x);
|
||||
bool operator()(ast::assignment const &x);
|
||||
bool operator()(ast::expression const &x);
|
||||
bool operator()(ast::function const &x);
|
||||
bool operator()(ast::operation const &x);
|
||||
bool operator()(ast::power const &x);
|
||||
bool operator()(ast::statement const &x);
|
||||
bool operator()(ast::statement_list const &x);
|
||||
bool operator()(ast::unary const &x);
|
||||
bool operator()(ast::variable const &x);
|
||||
bool operator()(ast::variable_declaration const &x);
|
||||
|
||||
void add_predef_var_values(const std::string &name,
|
||||
std::vector<double> &val,
|
||||
std::vector<double> &err);
|
||||
|
||||
void add_var(std::string const& name);
|
||||
bool find_var(std::string const &name);
|
||||
bool find_var(std::string const &name, unsigned int &idx);
|
||||
std::string pos_to_var(std::string const &name, bool &ok);
|
||||
|
||||
std::vector<PVarHandler> getVars() { return fVariable; }
|
||||
|
||||
private:
|
||||
std::vector<PVarHandler> fVariable;
|
||||
std::map<int, std::string> fVarPos;
|
||||
|
||||
boost::function<
|
||||
void(int tag, std::string const& what)>
|
||||
error_handler;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Program Evaluation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct PProgEval
|
||||
{
|
||||
typedef std::vector<double> result_type;
|
||||
|
||||
PProgEval(std::vector<PVarHandler> var) : fVariable(var) {}
|
||||
|
||||
std::vector<double> operator()(ast::nil);
|
||||
std::vector<double> operator()(double x);
|
||||
std::vector<double> operator()(ast::assignment const &x);
|
||||
std::vector<double> operator()(ast::expression const &x);
|
||||
std::vector<double> operator()(ast::function const &x);
|
||||
std::vector<double> operator()(ast::operation const &x, std::vector<double> lhs);
|
||||
std::vector<double> operator()(ast::power const &x);
|
||||
std::vector<double> operator()(ast::statement const &x);
|
||||
std::vector<double> operator()(ast::statement_list const &x);
|
||||
std::vector<double> operator()(ast::unary const &x);
|
||||
std::vector<double> operator()(ast::variable const &x);
|
||||
std::vector<double> operator()(ast::variable_declaration const &x);
|
||||
|
||||
PVarHandler getVar(const std::string name, bool &ok);
|
||||
void print_result();
|
||||
|
||||
private:
|
||||
std::vector<PVarHandler> fVariable;
|
||||
|
||||
unsigned int find_var(std::string const &name);
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // _PPROGRAM_HPP_
|
73
src/musredit_qt5/mupp/var/include/PSkipper.hpp
Normal file
73
src/musredit_qt5/mupp/var/include/PSkipper.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
/***************************************************************************
|
||||
|
||||
PSkipper.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on a mini_c,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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 _PSKIPPER_HPP_
|
||||
#define _PSKIPPER_HPP_
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
namespace mupp { namespace parser
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The skipper grammar
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct PSkipper : qi::grammar<Iterator>
|
||||
{
|
||||
PSkipper() : PSkipper::base_type(start)
|
||||
{
|
||||
qi::char_type char_;
|
||||
qi::lit_type lit;
|
||||
qi::eol_type eol;
|
||||
ascii::space_type space;
|
||||
ascii::print_type print;
|
||||
|
||||
single_line_comment = (lit('%') | lit('#') | lit("//")) >> *print >> eol;
|
||||
|
||||
start =
|
||||
space // tab/space/cr/lf
|
||||
| "/*" >> *(char_ - "*/") >> "*/" // C-style comments
|
||||
| single_line_comment
|
||||
;
|
||||
}
|
||||
|
||||
qi::rule<Iterator> single_line_comment;
|
||||
qi::rule<Iterator> start;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // _PSKIPPER_HPP_
|
||||
|
||||
|
58
src/musredit_qt5/mupp/var/include/PStatement.hpp
Normal file
58
src/musredit_qt5/mupp/var/include/PStatement.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/***************************************************************************
|
||||
|
||||
PStatement.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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 _PSTATEMENT_HPP_
|
||||
#define _PSTATEMENT_HPP_
|
||||
|
||||
#include "PExpression.hpp"
|
||||
|
||||
namespace mupp { namespace parser
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The statement grammar
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename Iterator>
|
||||
struct PStatement : qi::grammar<Iterator, ast::statement_list(), PSkipper<Iterator> >
|
||||
{
|
||||
PStatement(PErrorHandler<Iterator>& error_handler);
|
||||
|
||||
PExpression<Iterator> expr;
|
||||
qi::rule<Iterator, ast::statement_list(), PSkipper<Iterator> > statement_list;
|
||||
qi::rule<Iterator, ast::variable_declaration(), PSkipper<Iterator> > variable_declaration;
|
||||
qi::rule<Iterator, ast::assignment(), PSkipper<Iterator> > assignment;
|
||||
qi::rule<Iterator, std::string(), PSkipper<Iterator> > identifier;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // _PSTATEMENT_HPP_
|
||||
|
||||
|
107
src/musredit_qt5/mupp/var/include/PStatementDef.hpp
Normal file
107
src/musredit_qt5/mupp/var/include/PStatementDef.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
/***************************************************************************
|
||||
|
||||
PStatementDef.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PStatement.hpp"
|
||||
#include "PErrorHandler.hpp"
|
||||
#include "PAnnotation.hpp"
|
||||
|
||||
namespace mupp { namespace parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
PStatement<Iterator>::PStatement(PErrorHandler<Iterator>& error_handler)
|
||||
: PStatement::base_type(statement_list), expr(error_handler)
|
||||
{
|
||||
qi::_1_type _1;
|
||||
qi::_2_type _2;
|
||||
qi::_3_type _3;
|
||||
qi::_4_type _4;
|
||||
|
||||
qi::_val_type _val;
|
||||
qi::raw_type raw;
|
||||
qi::lexeme_type lexeme;
|
||||
qi::alpha_type alpha;
|
||||
qi::alnum_type alnum;
|
||||
|
||||
using qi::on_error;
|
||||
using qi::on_success;
|
||||
using qi::fail;
|
||||
using boost::phoenix::function;
|
||||
|
||||
typedef function<mupp::PErrorHandler<Iterator> > error_handler_function;
|
||||
typedef function<mupp::PAnnotation<Iterator> > annotation_function;
|
||||
|
||||
statement_list =
|
||||
+(variable_declaration | assignment)
|
||||
;
|
||||
|
||||
identifier =
|
||||
raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
|
||||
;
|
||||
|
||||
variable_declaration =
|
||||
lexeme["var" >> !(alnum | '_')] // make sure we have whole words
|
||||
> identifier
|
||||
> -('=' > expr)
|
||||
;
|
||||
|
||||
assignment =
|
||||
identifier
|
||||
> '='
|
||||
> expr
|
||||
;
|
||||
|
||||
// name all the rules
|
||||
statement_list.name("statement_list");
|
||||
identifier.name("identifier");
|
||||
variable_declaration.name("variable_declaration");
|
||||
assignment.name("assignment");
|
||||
|
||||
// Debugging and error handling and reporting support.
|
||||
BOOST_SPIRIT_DEBUG_NODES(
|
||||
(statement_list)
|
||||
(identifier)
|
||||
(variable_declaration)
|
||||
(assignment)
|
||||
);
|
||||
|
||||
// Error handling: on error in statement_list, call error_handler.
|
||||
on_error<fail>(statement_list,
|
||||
error_handler_function(error_handler)(
|
||||
"**ERROR** Expecting ", _4, _3));
|
||||
|
||||
// Annotation: on success in assignment, call annotation.
|
||||
on_success(assignment,
|
||||
annotation_function(error_handler.iters)(_val, _1));
|
||||
}
|
||||
}}
|
||||
|
||||
|
40
src/musredit_qt5/mupp/var/src/PExpression.cpp
Normal file
40
src/musredit_qt5/mupp/var/src/PExpression.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/***************************************************************************
|
||||
|
||||
PExpression.hpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4345)
|
||||
#endif
|
||||
|
||||
#include "PExpressionDef.hpp"
|
||||
|
||||
typedef std::string::const_iterator iterator_type;
|
||||
template struct mupp::parser::PExpression<iterator_type>;
|
661
src/musredit_qt5/mupp/var/src/PProgram.cpp
Normal file
661
src/musredit_qt5/mupp/var/src/PProgram.cpp
Normal file
@ -0,0 +1,661 @@
|
||||
/***************************************************************************
|
||||
|
||||
PProgram.cpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PProgram.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <set>
|
||||
|
||||
namespace mupp { namespace prog {
|
||||
void PVarHandler::SetValue(double dval, unsigned idx)
|
||||
{
|
||||
if (idx >= fValue.size()) {
|
||||
std::cerr << "**ERROR** SetValue: idx=" << idx << " is out-of-range." << std::endl;
|
||||
return;
|
||||
}
|
||||
fValue[idx] = dval;
|
||||
}
|
||||
|
||||
void PVarHandler::SetError(double dval, unsigned idx)
|
||||
{
|
||||
if (idx >= fError.size()) {
|
||||
std::cerr << "**ERROR** SetError: idx=" << idx << " is out-of-range." << std::endl;
|
||||
return;
|
||||
}
|
||||
fError[idx] = dval;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(double x)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::assignment const &x)
|
||||
{
|
||||
// check that the variable exists
|
||||
if (!find_var(x.lhs.name)) {
|
||||
error_handler(0, "Undeclared variable: " + x.lhs.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(*this)(x.rhs)) {
|
||||
std::cout << "**SEM ERROR** in var assignment of var: " << x.lhs.name << std::endl;
|
||||
std::cout << " rhs is missing or has an error." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::expression const &x)
|
||||
{
|
||||
if (!boost::apply_visitor(*this, x.first))
|
||||
return false;
|
||||
|
||||
BOOST_FOREACH(ast::operation const& oper, x.rest) {
|
||||
if (!(*this)(oper))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::function const &x)
|
||||
{
|
||||
switch (x.func_id) {
|
||||
case ast::fun_max:
|
||||
case ast::fun_min:
|
||||
case ast::fun_abs:
|
||||
case ast::fun_sin:
|
||||
case ast::fun_cos:
|
||||
case ast::fun_tan:
|
||||
case ast::fun_exp:
|
||||
case ast::fun_log:
|
||||
case ast::fun_ln:
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(*this)(x.arg)) {
|
||||
std::cout << "**SEM ERROR** in function: arg is missing or has an error." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::operation const &x)
|
||||
{
|
||||
if (!boost::apply_visitor(*this, x.operand_))
|
||||
return false;
|
||||
|
||||
switch (x.operator_) {
|
||||
case ast::op_plus:
|
||||
break;
|
||||
case ast::op_minus:
|
||||
break;
|
||||
case ast::op_times:
|
||||
break;
|
||||
case ast::op_divide:
|
||||
break;
|
||||
case ast::op_positive:
|
||||
break;
|
||||
case ast::op_negative:
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::power const &x)
|
||||
{
|
||||
if (!(*this)(x.base)) {
|
||||
std::cout << "**SEM ERROR** in power: base argument is missing or has an error." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(*this)(x.pow)) {
|
||||
std::cout << "**SEM ERROR** in power: power argument is missing or has an error." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::statement const &x)
|
||||
{
|
||||
return boost::apply_visitor(*this, x);
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::statement_list const &x)
|
||||
{
|
||||
BOOST_FOREACH(ast::statement const& s, x) {
|
||||
if (!(*this)(s))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::unary const &x)
|
||||
{
|
||||
if (!boost::apply_visitor(*this, x.operand_))
|
||||
return false;
|
||||
|
||||
switch (x.operator_) {
|
||||
case ast::op_negative:
|
||||
break;
|
||||
case ast::op_positive:
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::variable const &x)
|
||||
{
|
||||
bool ok(false);
|
||||
std::string var_name;
|
||||
|
||||
var_name = pos_to_var(x.name, ok);
|
||||
if (!ok) {
|
||||
error_handler(0, "Position variable out-of-range: " + x.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!find_var(var_name)) {
|
||||
error_handler(0, "Undeclared variable: " + var_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PProgram::operator()(ast::variable_declaration const &x)
|
||||
{
|
||||
if (find_var(x.lhs.name)) {
|
||||
error_handler(0, "Duplicate variable: " + x.lhs.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x.rhs) { // if there's a RHS initializer
|
||||
bool r = (*this)(*x.rhs);
|
||||
if (r) { // don't add the variable if the RHS fails
|
||||
add_var(x.lhs.name);
|
||||
} else {
|
||||
std::cout << "**SEM ERROR** rhs of var decl, name: " << x.lhs.name << ", failed" << std::endl;
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
add_var(x.lhs.name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PProgram::add_predef_var_values(const std::string &name,
|
||||
std::vector<double> &val,
|
||||
std::vector<double> &err)
|
||||
{
|
||||
unsigned int idx;
|
||||
if (!find_var(name, idx)) {
|
||||
std::cerr << "**ERROR** couldn't find pre-def variable : " << name << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
fVariable[idx].SetValue(val);
|
||||
fVariable[idx].SetError(err);
|
||||
}
|
||||
|
||||
void PProgram::add_var(std::string const& name)
|
||||
{
|
||||
PVarHandler var;
|
||||
var.SetName(name);
|
||||
fVariable.push_back(var);
|
||||
// add map var <-> pos
|
||||
std::size_t n = fVarPos.size();
|
||||
fVarPos[n] = name;
|
||||
}
|
||||
|
||||
bool PProgram::find_var(std::string const &name)
|
||||
{
|
||||
unsigned int idx;
|
||||
return find_var(name, idx);
|
||||
}
|
||||
|
||||
bool PProgram::find_var(std::string const &name, unsigned int &idx)
|
||||
{
|
||||
bool result=false;
|
||||
|
||||
// remove leading '$' of identifier
|
||||
std::string id("");
|
||||
if (name[0] == '$')
|
||||
id = name.substr(1);
|
||||
else
|
||||
id = name;
|
||||
|
||||
for (unsigned int i=0; i<fVariable.size(); i++) {
|
||||
if (id == fVariable[i].GetName()) {
|
||||
idx = i;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string PProgram::pos_to_var(std::string const &name, bool &ok)
|
||||
{
|
||||
std::string result("??");
|
||||
ok = true;
|
||||
|
||||
// remove leading '$' if present
|
||||
if (name[0] == '$')
|
||||
result = name.substr(1);
|
||||
else
|
||||
result = name;
|
||||
|
||||
// check if number
|
||||
char *p;
|
||||
int num = strtol(result.c_str(), &p, 10);
|
||||
if (*p == 0) {
|
||||
if (num >= fVarPos.size())
|
||||
ok = false;
|
||||
else
|
||||
result = fVarPos[num];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::nil)
|
||||
{
|
||||
std::vector<double> result;
|
||||
result.resize(fVariable[0].GetSize());
|
||||
|
||||
for (unsigned int i=0; i<result.size(); i++)
|
||||
result[i] = 0.0;
|
||||
|
||||
BOOST_ASSERT(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(double x)
|
||||
{
|
||||
std::vector<double> result;
|
||||
result.resize(fVariable[0].GetSize());
|
||||
|
||||
for (unsigned int i=0; i<result.size(); i++)
|
||||
result[i] = x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::assignment const &x)
|
||||
{
|
||||
std::vector<double> result;
|
||||
result.resize(fVariable[0].GetSize());
|
||||
|
||||
result = (*this)(x.rhs);
|
||||
|
||||
// keep all data under <varName> not <varName>Err.
|
||||
// <varName>Err data go to <varName> error, whereas
|
||||
// <varName> data go to <varName> value
|
||||
std::string name = x.lhs.name;
|
||||
bool errorVal(false);
|
||||
|
||||
// check for error variable
|
||||
std::size_t pos = name.find("Err");
|
||||
if (pos != std::string::npos) { // it is an error variable
|
||||
name = name.substr(0, pos);
|
||||
errorVal = true;
|
||||
}
|
||||
|
||||
unsigned int idx = find_var(name);
|
||||
if (errorVal)
|
||||
fVariable[idx].SetError(result);
|
||||
else
|
||||
fVariable[idx].SetValue(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::expression const &x)
|
||||
{
|
||||
std::vector<double> vec = boost::apply_visitor(*this, x.first);
|
||||
|
||||
BOOST_FOREACH(ast::operation const& oper, x.rest) {
|
||||
vec = (*this)(oper, vec);
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::function const &x)
|
||||
{
|
||||
std::vector<double> vec = (*this)(x.arg);
|
||||
|
||||
double dval;
|
||||
switch(x.func_id) {
|
||||
case ast::fun_max:
|
||||
dval = -1.0e10;
|
||||
for (unsigned int i=0; i<vec.size(); i++) {
|
||||
if (vec[i] > dval)
|
||||
dval = vec[i];
|
||||
}
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = dval;
|
||||
break;
|
||||
case ast::fun_min:
|
||||
dval = 1.0e10;
|
||||
for (unsigned int i=0; i<vec.size(); i++) {
|
||||
if (vec[i] < dval)
|
||||
dval = vec[i];
|
||||
}
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = dval;
|
||||
break;
|
||||
case ast::fun_abs:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = fabs(vec[i]);
|
||||
break;
|
||||
case ast::fun_sin:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = sin(vec[i]);
|
||||
break;
|
||||
case ast::fun_cos:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = cos(vec[i]);
|
||||
break;
|
||||
case ast::fun_tan:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = tan(vec[i]);
|
||||
break;
|
||||
case ast::fun_exp:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = exp(vec[i]);
|
||||
break;
|
||||
case ast::fun_log:
|
||||
for (unsigned int i=0; i<vec.size(); i++) {
|
||||
if (vec[i] <= 0.0) {
|
||||
BOOST_ASSERT(0);
|
||||
break;
|
||||
} else {
|
||||
vec[i] = log10(vec[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ast::fun_ln:
|
||||
for (unsigned int i=0; i<vec.size(); i++) {
|
||||
if (vec[i] <= 0.0) {
|
||||
BOOST_ASSERT(0);
|
||||
break;
|
||||
} else {
|
||||
vec[i] = log(vec[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::operation const &x, std::vector<double> lhs)
|
||||
{
|
||||
std::vector<double> rhs = boost::apply_visitor(*this, x.operand_);
|
||||
|
||||
// make sure both vectors have the same size
|
||||
if (lhs.size() != rhs.size()) {
|
||||
BOOST_ASSERT(0);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
switch (x.operator_) {
|
||||
case ast::op_plus:
|
||||
for (unsigned int i=0; i<lhs.size(); i++)
|
||||
lhs[i] = lhs[i] + rhs[i];
|
||||
break;
|
||||
case ast::op_minus:
|
||||
for (unsigned int i=0; i<lhs.size(); i++)
|
||||
lhs[i] = lhs[i] - rhs[i];
|
||||
break;
|
||||
case ast::op_times:
|
||||
for (unsigned int i=0; i<lhs.size(); i++)
|
||||
lhs[i] = lhs[i] * rhs[i];
|
||||
break;
|
||||
case ast::op_divide:
|
||||
for (unsigned int i=0; i<lhs.size(); i++) {
|
||||
if (rhs[i] == 0.0) {
|
||||
BOOST_ASSERT(0);
|
||||
return lhs;
|
||||
} else {
|
||||
lhs[i] = lhs[i] / rhs[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::power const &x)
|
||||
{
|
||||
std::vector<double> baseV = (*this)(x.base);
|
||||
std::vector<double> powV = (*this)(x.pow);
|
||||
|
||||
if (baseV.size() != powV.size()) {
|
||||
BOOST_ASSERT(0);
|
||||
return baseV;
|
||||
}
|
||||
|
||||
std::vector<double> result;
|
||||
result.resize(baseV.size());
|
||||
for (unsigned int i=0; i<baseV.size(); i++)
|
||||
result[i] = pow(baseV[i], powV[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::statement const &x)
|
||||
{
|
||||
// as35: not-yet-implemented
|
||||
std::vector<double> result;
|
||||
result.resize(fVariable[0].GetSize());
|
||||
|
||||
for (unsigned int i=0; i<result.size(); i++)
|
||||
result[i] = 0.0;
|
||||
|
||||
boost::apply_visitor(*this, x);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::statement_list const &x)
|
||||
{
|
||||
// as35: not-yet-implemented
|
||||
std::vector<double> result;
|
||||
result.resize(fVariable[0].GetSize());
|
||||
|
||||
for (unsigned int i=0; i<result.size(); i++)
|
||||
result[i] = 0.0;
|
||||
|
||||
BOOST_FOREACH(ast::statement const& s, x) {
|
||||
(*this)(s);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::unary const &x)
|
||||
{
|
||||
std::vector<double> vec = boost::apply_visitor(*this, x.operand_);
|
||||
|
||||
if (x.operator_ == ast::op_negative) {
|
||||
for (unsigned int i=0; i<vec.size(); i++) {
|
||||
vec[i] *= -1.0;
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::variable const &x)
|
||||
{
|
||||
std::string name = x.name;
|
||||
bool errorVal(false);
|
||||
|
||||
// check for injected error variable
|
||||
std::size_t pos = name.find("Err");
|
||||
if (pos != std::string::npos) { // it is an error variable
|
||||
name = name.substr(0, pos);
|
||||
errorVal = true;
|
||||
}
|
||||
|
||||
unsigned idx = find_var(name);
|
||||
|
||||
if (errorVal)
|
||||
return fVariable[idx].GetError();
|
||||
else
|
||||
return fVariable[idx].GetValue();
|
||||
}
|
||||
|
||||
std::vector<double> PProgEval::operator()(ast::variable_declaration const &x)
|
||||
{
|
||||
std::vector<double> result;
|
||||
result.resize(fVariable[0].GetSize());
|
||||
|
||||
// keep all data under <varName> not <varName>Err.
|
||||
// <varName>Err data go to <varName> error, whereas
|
||||
// <varName> data go to <varName> value
|
||||
std::string name = x.lhs.name;
|
||||
bool errorVal(false);
|
||||
|
||||
// check for error variable
|
||||
std::size_t pos = name.find("Err");
|
||||
if (pos != std::string::npos) { // it is an error variable
|
||||
name = name.substr(0, pos);
|
||||
errorVal = true;
|
||||
}
|
||||
|
||||
unsigned int idx = find_var(name);
|
||||
|
||||
if (x.rhs) { // if there's a RHS initializer
|
||||
result = (*this)(*x.rhs);
|
||||
} else {
|
||||
// injected variable content
|
||||
if (errorVal)
|
||||
result = fVariable[idx].GetError();
|
||||
else
|
||||
result = fVariable[idx].GetValue();
|
||||
}
|
||||
|
||||
if (errorVal)
|
||||
fVariable[idx].SetError(result);
|
||||
else
|
||||
fVariable[idx].SetValue(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int PProgEval::find_var(std::string const &name)
|
||||
{
|
||||
// remove leading '$' of identifier
|
||||
std::string id("");
|
||||
if (name[0] == '$')
|
||||
id = name.substr(1);
|
||||
else
|
||||
id = name;
|
||||
|
||||
unsigned idx = 0;
|
||||
for (unsigned int i=0; i<fVariable.size(); i++) {
|
||||
if (id == fVariable[i].GetName()) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
PVarHandler PProgEval::getVar(const std::string name, bool &ok)
|
||||
{
|
||||
PVarHandler var = fVariable[0];
|
||||
ok = false;
|
||||
|
||||
for (unsigned int i=0; i<fVariable.size(); i++) {
|
||||
if (fVariable[i].GetName() == name) {
|
||||
var = fVariable[i];
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
void PProgEval::print_result()
|
||||
{
|
||||
std::vector<double> val, err;
|
||||
for (unsigned int i=0; i<fVariable.size(); i++) {
|
||||
if (!strstr(fVariable[i].GetName().c_str(), "Err")) {
|
||||
std::cout << "+++++" << std::endl;
|
||||
std::cout << "var Name: " << fVariable[i].GetName() << std::endl;
|
||||
val = fVariable[i].GetValue();
|
||||
err = fVariable[i].GetError();
|
||||
for (unsigned int j=0; j<val.size(); j++) {
|
||||
if (j<err.size())
|
||||
std::cout << " " << j << ": " << val[j] << " +- " << err[j] << std::endl;
|
||||
else
|
||||
std::cout << " " << j << ": " << val[j] << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "+++++" << std::endl;
|
||||
}
|
||||
}}
|
40
src/musredit_qt5/mupp/var/src/PStatement.cpp
Normal file
40
src/musredit_qt5/mupp/var/src/PStatement.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/***************************************************************************
|
||||
|
||||
PStatement.cpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
Based on Joel de Guzman example on calc7,
|
||||
see https://github.com/boostorg/spirit
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2020 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. *
|
||||
***************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4345)
|
||||
#endif
|
||||
|
||||
#include "PStatementDef.hpp"
|
||||
|
||||
typedef std::string::const_iterator iterator_type;
|
||||
template struct mupp::parser::PStatement<iterator_type>;
|
Loading…
x
Reference in New Issue
Block a user