migrated spirit qi grammar to x3 of mupp variable handling.

This commit is contained in:
2025-12-30 11:02:46 +01:00
parent e4ff8ca7d5
commit 7ce0926fd9
10 changed files with 179 additions and 252 deletions

View File

@@ -9,8 +9,8 @@
see https://github.com/boostorg/spirit
This file contains the implementation (definition) of the PExpression
template grammar. It defines the actual grammar rules and their semantic
actions using Boost.Spirit Qi.
grammar. It defines the actual grammar rules and their semantic
actions using Boost.Spirit X3.
The grammar implements expression parsing with proper operator precedence:
- Primary expressions (literals, variables, functions)
@@ -46,93 +46,116 @@
#include "PExpression.hpp"
#include "PErrorHandler.hpp"
#include "PAnnotation.hpp"
#include <boost/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;
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
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;
using x3::char_;
using x3::double_;
using x3::raw;
using x3::lexeme;
using ascii::alpha;
using ascii::alnum;
///////////////////////////////////////////////////////////////////////
// Tokens
additive_op.add
("+", ast::op_plus)
("-", ast::op_minus)
;
// Symbol tables for operators and functions
///////////////////////////////////////////////////////////////////////
multiplicative_op.add
("*", ast::op_times)
("/", ast::op_divide)
;
inline struct additive_op_ : x3::symbols<ast::optoken>
{
additive_op_()
{
add
("+", ast::op_plus)
("-", ast::op_minus)
;
}
} additive_op;
unary_op.add
("+", ast::op_positive)
("-", ast::op_negative)
;
inline struct multiplicative_op_ : x3::symbols<ast::optoken>
{
multiplicative_op_()
{
add
("*", ast::op_times)
("/", ast::op_divide)
;
}
} multiplicative_op;
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)
;
inline struct unary_op_ : x3::symbols<ast::optoken>
{
unary_op_()
{
add
("+", ast::op_positive)
("-", ast::op_negative)
;
}
} unary_op;
inline struct fun_tok_ : x3::symbols<ast::funid>
{
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)
;
}
} fun_tok;
///////////////////////////////////////////////////////////////////////
// Rule definitions
///////////////////////////////////////////////////////////////////////
inline expr_type const expr = "expr";
inline additive_expr_type const additive_expr = "additive_expr";
inline multiplicative_expr_type const multiplicative_expr = "multiplicative_expr";
inline unary_expr_type const unary_expr = "unary_expr";
inline primary_expr_type const primary_expr = "primary_expr";
inline identifier_type const identifier = "identifier";
///////////////////////////////////////////////////////////////////////
// Grammar
expr =
additive_expr.alias()
///////////////////////////////////////////////////////////////////////
inline auto const expr_def =
additive_expr
;
additive_expr =
inline auto const additive_expr_def =
multiplicative_expr
>> *(additive_op > multiplicative_expr)
;
;
multiplicative_expr =
inline auto const multiplicative_expr_def =
unary_expr
>> *(multiplicative_op > unary_expr)
;
;
unary_expr =
inline auto const unary_expr_def =
primary_expr
| (unary_op > primary_expr)
;
primary_expr =
inline auto const primary_expr_def =
double_
| identifier
| fun_tok > '(' > expr > ')'
@@ -140,36 +163,13 @@ namespace mupp { namespace parser
| '(' > expr > ')'
;
identifier =
inline auto const identifier_def =
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");
BOOST_SPIRIT_DEFINE(expr, additive_expr, multiplicative_expr,
unary_expr, primary_expr, 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));
}
}}