add first Qt6 version of musredit, mupp, etc.
This commit is contained in:
1
src/musredit_qt6/mupp/var/CMakeLists.txt
Normal file
1
src/musredit_qt6/mupp/var/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_subdirectory(src)
|
||||
103
src/musredit_qt6/mupp/var/include/PAnnotation.hpp
Normal file
103
src/musredit_qt6/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_
|
||||
|
||||
204
src/musredit_qt6/mupp/var/include/PAst.hpp
Normal file
204
src/musredit_qt6/mupp/var/include/PAst.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/***************************************************************************
|
||||
|
||||
PAst.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 _PAST_HPP_
|
||||
#define _PAST_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 mupp { namespace ast
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The AST
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct tagged
|
||||
{
|
||||
int id; // Used to annotate the AST with the iterator position.
|
||||
// This id is used as a key to a map<int, Iterator>
|
||||
// (not really part of the AST.)
|
||||
};
|
||||
|
||||
enum optoken
|
||||
{
|
||||
op_plus,
|
||||
op_minus,
|
||||
op_times,
|
||||
op_divide,
|
||||
op_positive,
|
||||
op_negative,
|
||||
};
|
||||
|
||||
enum funid
|
||||
{
|
||||
fun_max,
|
||||
fun_min,
|
||||
fun_abs,
|
||||
fun_sin,
|
||||
fun_cos,
|
||||
fun_tan,
|
||||
fun_sinh,
|
||||
fun_cosh,
|
||||
fun_tanh,
|
||||
fun_asin,
|
||||
fun_acos,
|
||||
fun_atan,
|
||||
fun_exp,
|
||||
fun_log,
|
||||
fun_ln,
|
||||
fun_sqrt
|
||||
};
|
||||
|
||||
struct nil {};
|
||||
struct unary;
|
||||
struct expression;
|
||||
struct function;
|
||||
struct power;
|
||||
|
||||
struct variable : tagged
|
||||
{
|
||||
variable(std::string const& name = "") : name(name) {}
|
||||
std::string name;
|
||||
};
|
||||
|
||||
typedef boost::variant<
|
||||
nil
|
||||
, double
|
||||
, variable
|
||||
, boost::recursive_wrapper<function>
|
||||
, boost::recursive_wrapper<power>
|
||||
, boost::recursive_wrapper<unary>
|
||||
, boost::recursive_wrapper<expression>
|
||||
>
|
||||
operand;
|
||||
|
||||
struct unary
|
||||
{
|
||||
optoken operator_;
|
||||
operand operand_;
|
||||
};
|
||||
|
||||
struct operation
|
||||
{
|
||||
optoken operator_;
|
||||
operand operand_;
|
||||
};
|
||||
|
||||
struct expression
|
||||
{
|
||||
operand first;
|
||||
std::list<operation> rest;
|
||||
};
|
||||
|
||||
struct function
|
||||
{
|
||||
funid func_id;
|
||||
expression arg;
|
||||
};
|
||||
|
||||
struct power
|
||||
{
|
||||
expression base;
|
||||
expression pow;
|
||||
};
|
||||
|
||||
struct assignment
|
||||
{
|
||||
variable lhs;
|
||||
expression rhs;
|
||||
};
|
||||
|
||||
struct variable_declaration
|
||||
{
|
||||
variable lhs;
|
||||
boost::optional<expression> rhs;
|
||||
};
|
||||
|
||||
typedef boost::variant<
|
||||
variable_declaration
|
||||
, assignment>
|
||||
statement;
|
||||
|
||||
typedef std::list<statement> statement_list;
|
||||
|
||||
// print functions for debugging
|
||||
inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
|
||||
inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
|
||||
}}
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::unary,
|
||||
(mupp::ast::optoken, operator_)
|
||||
(mupp::ast::operand, operand_)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::operation,
|
||||
(mupp::ast::optoken, operator_)
|
||||
(mupp::ast::operand, operand_)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::expression,
|
||||
(mupp::ast::operand, first)
|
||||
(std::list<mupp::ast::operation>, rest)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::function,
|
||||
(mupp::ast::funid, func_id)
|
||||
(mupp::ast::expression, arg)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::power,
|
||||
(mupp::ast::expression, base)
|
||||
(mupp::ast::expression, pow)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::variable_declaration,
|
||||
(mupp::ast::variable, lhs)
|
||||
(boost::optional<mupp::ast::expression>, rhs)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mupp::ast::assignment,
|
||||
(mupp::ast::variable, lhs)
|
||||
(mupp::ast::expression, rhs)
|
||||
)
|
||||
|
||||
#endif // _PAST_HPP_
|
||||
118
src/musredit_qt6/mupp/var/include/PErrorHandler.hpp
Normal file
118
src/musredit_qt6/mupp/var/include/PErrorHandler.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/***************************************************************************
|
||||
|
||||
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 <fstream>
|
||||
#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);
|
||||
const char *homeStr = getenv("HOME");
|
||||
char fln[1024];
|
||||
sprintf(fln, "%s/.musrfit/mupp/mupp_err.log", homeStr);
|
||||
std::ofstream fout(fln, std::ofstream::app);
|
||||
if (err_pos != last) {
|
||||
fout << message << what << ':' << std::endl;
|
||||
fout << get_line(line_start) << std::endl;
|
||||
for (; line_start != err_pos; ++line_start)
|
||||
fout << ' ';
|
||||
fout << "^~~" << std::endl;
|
||||
} else {
|
||||
fout << "**ERROR** Unexpected end of file. ";
|
||||
fout << 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_qt6/mupp/var/include/PExpression.hpp
Normal file
83
src/musredit_qt6/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_
|
||||
|
||||
|
||||
162
src/musredit_qt6/mupp/var/include/PExpressionDef.hpp
Normal file
162
src/musredit_qt6/mupp/var/include/PExpressionDef.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/***************************************************************************
|
||||
|
||||
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)
|
||||
("sinh", ast::fun_sinh)
|
||||
("cosh", ast::fun_cosh)
|
||||
("tanh", ast::fun_tanh)
|
||||
("asin", ast::fun_asin)
|
||||
("acos", ast::fun_acos)
|
||||
("atan", ast::fun_atan)
|
||||
("exp", ast::fun_exp)
|
||||
("log", ast::fun_log)
|
||||
("ln", ast::fun_ln)
|
||||
("sqrt", ast::fun_sqrt)
|
||||
;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// 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_qt6/mupp/var/include/PProgram.hpp
Normal file
159
src/musredit_qt6/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_qt6/mupp/var/include/PSkipper.hpp
Normal file
73
src/musredit_qt6/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_qt6/mupp/var/include/PStatement.hpp
Normal file
58
src/musredit_qt6/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_qt6/mupp/var/include/PStatementDef.hpp
Normal file
107
src/musredit_qt6/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));
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
69
src/musredit_qt6/mupp/var/include/PVarHandler.h
Normal file
69
src/musredit_qt6/mupp/var/include/PVarHandler.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/***************************************************************************
|
||||
|
||||
PVarHandler.h
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-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 _PVARHANDLER_H_
|
||||
#define _PVARHANDLER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "Pmupp.h"
|
||||
#include "PAst.hpp"
|
||||
#include "PProgram.hpp"
|
||||
|
||||
class PVarHandler {
|
||||
public:
|
||||
PVarHandler();
|
||||
PVarHandler(PmuppCollection *coll, std::string parse_str, std::string var_name="");
|
||||
|
||||
bool isValid() { return fIsValid; }
|
||||
QString getCollName() { return fColl->GetName(); }
|
||||
QString getVarName() { return QString(fVarName.c_str()); }
|
||||
std::vector<double> getValues();
|
||||
std::vector<double> getErrors();
|
||||
|
||||
private:
|
||||
PmuppCollection *fColl; ///< collection needed for parsing and evaluation
|
||||
std::string fParseStr; ///< the variable input to be parsed
|
||||
std::string fVarName; ///< variable name
|
||||
mupp::prog::PVarHandler fVar; ///< values of the evaluation
|
||||
|
||||
bool fIsValid;
|
||||
mupp::ast::statement_list fAst; ///< the AST
|
||||
|
||||
void injectPredefVariables();
|
||||
|
||||
std::string getVarName(int idx);
|
||||
std::vector<double> getData(int idx);
|
||||
std::vector<double> getDataErr(int idx);
|
||||
};
|
||||
|
||||
#endif //_PVARHANDLER_H_
|
||||
7
src/musredit_qt6/mupp/var/src/CMakeLists.txt
Normal file
7
src/musredit_qt6/mupp/var/src/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
target_sources(mupp
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/PVarHandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/PExpression.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/PProgram.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/PStatement.cpp
|
||||
)
|
||||
40
src/musredit_qt6/mupp/var/src/PExpression.cpp
Normal file
40
src/musredit_qt6/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>;
|
||||
702
src/musredit_qt6/mupp/var/src/PProgram.cpp
Normal file
702
src/musredit_qt6/mupp/var/src/PProgram.cpp
Normal file
@@ -0,0 +1,702 @@
|
||||
/***************************************************************************
|
||||
|
||||
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_sinh:
|
||||
case ast::fun_cosh:
|
||||
case ast::fun_tanh:
|
||||
case ast::fun_asin:
|
||||
case ast::fun_acos:
|
||||
case ast::fun_atan:
|
||||
case ast::fun_exp:
|
||||
case ast::fun_log:
|
||||
case ast::fun_ln:
|
||||
case ast::fun_sqrt:
|
||||
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_sinh:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = sinh(vec[i]);
|
||||
break;
|
||||
case ast::fun_cosh:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = cosh(vec[i]);
|
||||
break;
|
||||
case ast::fun_tanh:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = tanh(vec[i]);
|
||||
break;
|
||||
case ast::fun_asin:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = asin(vec[i]);
|
||||
break;
|
||||
case ast::fun_acos:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = acos(vec[i]);
|
||||
break;
|
||||
case ast::fun_atan:
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
vec[i] = atan(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;
|
||||
case ast::fun_sqrt:
|
||||
for (unsigned int i=0; i<vec.size(); i++) {
|
||||
if (vec[i] <= 0.0) {
|
||||
BOOST_ASSERT(0);
|
||||
break;
|
||||
} else {
|
||||
vec[i] = sqrt(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_qt6/mupp/var/src/PStatement.cpp
Normal file
40
src/musredit_qt6/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>;
|
||||
212
src/musredit_qt6/mupp/var/src/PVarHandler.cpp
Normal file
212
src/musredit_qt6/mupp/var/src/PVarHandler.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/***************************************************************************
|
||||
|
||||
PVarHandler.cpp
|
||||
|
||||
Author: Andreas Suter
|
||||
e-mail: andreas.suter@psi.ch
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-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 <iostream>
|
||||
|
||||
#include "PVarHandler.h"
|
||||
|
||||
#include "PSkipper.hpp"
|
||||
#include "PErrorHandler.hpp"
|
||||
#include "PStatement.hpp"
|
||||
#include "PProgram.hpp"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::PVarHandler
|
||||
*/
|
||||
PVarHandler::PVarHandler() :
|
||||
fColl(nullptr), fParseStr(""), fVarName(""), fIsValid(false)
|
||||
{
|
||||
// nothing to be done here
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::PVarHandler
|
||||
*/
|
||||
PVarHandler::PVarHandler(PmuppCollection *coll, std::string parse_str, std::string var_name) :
|
||||
fColl(coll), fParseStr(parse_str), fVarName(var_name), fIsValid(false)
|
||||
{
|
||||
injectPredefVariables();
|
||||
|
||||
typedef std::string::const_iterator iterator_type;
|
||||
iterator_type iter = fParseStr.begin();
|
||||
iterator_type end = fParseStr.end();
|
||||
|
||||
mupp::PErrorHandler<iterator_type> error_handler(iter, end); // the error handler
|
||||
mupp::parser::PStatement<iterator_type> parser(error_handler); // the parser
|
||||
mupp::prog::PProgram prog(error_handler); // our compiler, and exec
|
||||
mupp::parser::PSkipper<iterator_type> skipper; // the skipper parser
|
||||
|
||||
// perform the parsing
|
||||
bool success = phrase_parse(iter, end, parser, skipper, fAst);
|
||||
if (success && iter == end) {
|
||||
if (prog(fAst)) { // semantic analysis
|
||||
std::vector<double> data, dataErr;
|
||||
for (unsigned int i=0; i<fColl->GetRun(0).GetNoOfParam(); i++) {
|
||||
data = getData(i);
|
||||
dataErr = getDataErr(i);
|
||||
prog.add_predef_var_values(getVarName(i), data, dataErr);
|
||||
}
|
||||
if (!fVarName.empty()) {
|
||||
mupp::prog::PProgEval eval(prog.getVars()); // setup evaluation stage
|
||||
eval(fAst); // evaluate stuff
|
||||
|
||||
// keep data
|
||||
bool ok;
|
||||
fVar = eval.getVar(fVarName, ok);
|
||||
if (!ok) {
|
||||
std::cerr << "**ERROR** evalution failed..." << std::endl;
|
||||
fIsValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
fIsValid = true;
|
||||
} else {
|
||||
std::cerr << "**ERROR** parsing failed..." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::getValues
|
||||
* @return
|
||||
*/
|
||||
std::vector<double> PVarHandler::getValues()
|
||||
{
|
||||
std::vector<double> data;
|
||||
if (fIsValid)
|
||||
data = fVar.GetValue();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::getErrors
|
||||
* @return
|
||||
*/
|
||||
std::vector<double> PVarHandler::getErrors()
|
||||
{
|
||||
std::vector<double> data;
|
||||
if (fIsValid)
|
||||
data = fVar.GetError();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::injectPredefVariables
|
||||
*/
|
||||
void PVarHandler::injectPredefVariables()
|
||||
{
|
||||
mupp::ast::statement var_stat;
|
||||
mupp::ast::variable_declaration var;
|
||||
|
||||
std::string varName, errVarName;
|
||||
PmuppRun run = fColl->GetRun(0);
|
||||
for (int i=0; i<run.GetNoOfParam(); i++) {
|
||||
varName = run.GetParam(i).GetName().toLatin1().data();
|
||||
errVarName = varName + "Err";
|
||||
// inject err_name
|
||||
var.lhs.name = errVarName;
|
||||
var_stat = var;
|
||||
fAst.push_front(var_stat);
|
||||
// inject var_name
|
||||
var.lhs.name = varName;
|
||||
var_stat = var;
|
||||
fAst.push_front(var_stat);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::getVarName
|
||||
* @param idx
|
||||
* @return
|
||||
*/
|
||||
std::string PVarHandler::getVarName(int idx)
|
||||
{
|
||||
std::string name("??");
|
||||
|
||||
// make sure idx is in range
|
||||
if (idx >= fColl->GetRun(0).GetNoOfParam())
|
||||
return name;
|
||||
|
||||
return fColl->GetRun(0).GetParam(idx).GetName().toLatin1().data();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::getData
|
||||
* @param idx
|
||||
* @return
|
||||
*/
|
||||
std::vector<double> PVarHandler::getData(int idx)
|
||||
{
|
||||
std::vector<double> data;
|
||||
|
||||
// make sure idx is in range
|
||||
if (idx >= fColl->GetRun(0).GetNoOfParam())
|
||||
return data;
|
||||
|
||||
double dval;
|
||||
for (int i=0; i<fColl->GetNoOfRuns(); i++) {
|
||||
dval = fColl->GetRun(i).GetParam(idx).GetValue();
|
||||
data.push_back(dval);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PVarHandler::getDataErr
|
||||
* @param idx
|
||||
* @return
|
||||
*/
|
||||
std::vector<double> PVarHandler::getDataErr(int idx)
|
||||
{
|
||||
std::vector<double> err;
|
||||
|
||||
// make sure idx is in range
|
||||
if (idx >= fColl->GetRun(0).GetNoOfParam())
|
||||
return err;
|
||||
|
||||
double dvalPos, dvalNeg;
|
||||
for (int i=0; i<fColl->GetNoOfRuns(); i++) {
|
||||
dvalPos = fColl->GetRun(i).GetParam(idx).GetPosErr();
|
||||
dvalNeg = fColl->GetRun(i).GetParam(idx).GetNegErr();
|
||||
dvalPos = sqrt(fabs(dvalPos*dvalNeg)); // geometric mean of pos/neg error
|
||||
err.push_back(dvalPos);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
Reference in New Issue
Block a user