I am trying to add the exponential operator to this boost::spirit calculator example, whose grammar is the one below. Note that expressions like "-2^2^3" must be parsed as "-(2^(2^3))" == -256.
expr = equality_expr.alias() ; equality_expr = relational_expr >> *(equality_op > relational_expr) ; relational_expr = logical_expr >> *(relational_op > logical_expr) ; logical_expr = additive_expr >> *(logical_op > additive_expr) ; 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 = uint_ | identifier | bool_ | '(' > expr > ')' ; identifier = !keywords >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]] ;
After having read the documentation, my understanding is that I have to insert the following exponential_expr rule to the grammar for it to parse exponential operations with the proper right-to-left associativity:
multiplicative_expr = exponential_expr >> *(multiplicative_op > exponential_expr) ; exponential_expr = unary_expr >> !(exponential_op >> exponential_expr) ;
Where the rules are:
qi::rule<Iterator, ast::expression(), ascii::space_type>
expr, equality_expr, relational_expr,
logical_expr, additive_expr, multiplicative_expr, exponential_expr
;
qi::rule<Iterator, ast::operand(), ascii::space_type>
unary_expr, primary_expr
;
qi::rule<Iterator, ast::function_call(), ascii::space_type >
function_call
;
qi::rule<Iterator, std::list<ast::expression>(), ascii::space_type >
argument_list
;
qi::rule<Iterator, std::string(), ascii::space_type>
identifier
;
qi::symbols<char, ast::optoken>
equality_op, relational_op, logical_op,
additive_op, multiplicative_op, unary_op, exponential_op
;
qi::symbols<char>
keywords
;
The problem I am having now is that the program fails to compile, as the AST (ast.hpp) must be also modified accordingly, but I don't exactly now how. Do you have any idea?
This is the compiler error:
calculator/ExpressionDef.hpp:114:9: required from 'calculator::parser::expression::expression(calculator::error_handler&) [with Iterator = __gnu_cxx::__normal_iterator >]' Expression.cpp:4:37: required from here /usr/include/boost/spirit/home/qi/detail/assign_to.hpp:152:13: error: no matching function for call to 'calculator::ast::expression::expression(const boost::variant, boost::recursive_wrapper, boost::recursive_wrapper >&)' /usr/include/boost/spirit/home/qi/detail/assign_to.hpp:152:13: note: candidates are: In file included from ./calculator/Expression.hpp:20:0, from calculator/ExpressionDef.hpp:1, from Expression.cpp:1: ./calculator/Ast.hpp:83:12: note: calculator::ast::expression::expression() ./calculator/Ast.hpp:83:12: note: candidate expects 0 arguments, 1 provided ./calculator/Ast.hpp:83:12: note: calculator::ast::expression::expression(const calculator::ast::expression&) ./calculator/Ast.hpp:83:12: note: no known conversion for argument 1 from 'const boost::variant, boost::recursive_wrapper, boost::recursive_wrapper >' to 'const calculator::ast::expression&' ./calculator/Ast.hpp:83:12: note: calculator::ast::expression::expression(calculator::ast::expression&&) ./calculator/Ast.hpp:83:12: note: no known conversion for argument 1 from 'const boost::variant, boost::recursive_wrapper, boost::recursive_wrapper >' to 'calculator::ast::expression&&'