Boost::Spirit 表达式解析器,带有定义的函数

Posted

技术标签:

【中文标题】Boost::Spirit 表达式解析器,带有定义的函数【英文标题】:Boost::Spirit expression parser with defined functions 【发布时间】:2019-03-29 14:03:28 【问题描述】:

我正在尝试解析一些表达式。我从llonesmiz 和Sehe 的令人印象深刻的答案开始

我想补充一些:

(1) 定义的参数。这些婴儿车由另一个班级作为地图提供。他们可能没有参数(整数)一或二:

imf ---> $imf imf(1) ---> $imf(1) imf(1,2) ---> $imf(1,2)

我正在尝试获取参数名称“imf”,然后是它的参数(如果它们存在)(1),(2,2)......

(2) 由另一个类作为映射给出的定义函数。他们可能有一个、两个或三个参数:

cos(1) ---> cos(1) cross(imf(1),1) ---> cross($imf(1),1) fun3(1,2,1) ---> fun3(1,2,1)

custom_fold_directive.hpp

namespace custom
    
        namespace tag
        
            struct fold  BOOST_SPIRIT_IS_TAG() ;
        

        template <typename Exposed, typename Expr>
        boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>
        fold(Expr const& expr)
        
            return boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>(expr);
        

    

    namespace boost  namespace spirit 
    
        template <typename Expr, typename Exposed>
        struct use_directive<qi::domain
              , tag::stateful_tag<Expr, custom::tag::fold, Exposed> >
          : mpl::true_ ;
    

    namespace custom
    
        template <typename Exposed, typename InitialParser, typename RepeatingParser>
        struct fold_directive
        
            fold_directive(InitialParser const& initial, RepeatingParser const& repeating):initial(initial),repeating(repeating)

            template <typename Context, typename Iterator>
            struct attribute
            
                typedef typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type type;//This works in this case but is not generic
            ;

            template <typename Iterator, typename Context
              , typename Skipper, typename Attribute>
            bool parse(Iterator& first, Iterator const& last
              , Context& context, Skipper const& skipper, Attribute& attr_) const
            
                Iterator start = first;

                typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type initial_attr;


                if (!initial.parse(first, last, context, skipper, initial_attr))
                
                    first=start;
                    return false;
                

                typename boost::spirit::traits::attribute_of<RepeatingParser,Context,Iterator>::type repeating_attr;

                if(!repeating.parse(first, last, context, skipper, repeating_attr))
                
                    boost::spirit::traits::assign_to(initial_attr, attr_);
                    return true;
                
                Exposed current_attr(initial_attr,repeating_attr);

                while(repeating.parse(first, last, context, skipper, repeating_attr))
                
                    boost::spirit::traits::assign_to(Exposed(current_attr,repeating_attr),current_attr);
                
                boost::spirit::traits::assign_to(current_attr,attr_);
                return true;
            

            template <typename Context>
            boost::spirit::info what(Context& context) const
            
                return boost::spirit::info("fold");
            

            InitialParser initial;
            RepeatingParser repeating;
        ;
    

    namespace boost  namespace spirit  namespace qi
    
        template <typename Expr, typename Exposed, typename Subject, typename Modifiers>
        struct make_directive<
            tag::stateful_tag<Expr, custom::tag::fold, Exposed>, Subject, Modifiers>
        
            typedef custom::fold_directive<Exposed, Expr, Subject> result_type;

            template <typename Terminal>
            result_type operator()(Terminal const& term, Subject const& subject, Modifiers const&) const
            
                typedef tag::stateful_tag<
                    Expr, custom::tag::fold, Exposed> tag_type;
                using spirit::detail::get_stateful_data;

                return result_type(get_stateful_data<tag_type>::call(term),subject);
            
        ;
    

main.cpp

//#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include "custom_fold_directive.hpp"

namespace qi = boost::spirit::qi;

// DEFINING TYPES
struct op_not ;
struct op_or ;
struct op_and ;
struct op_equal ;
struct op_unequal ;
struct op_sum ;
struct op_difference ;
struct op_factor ;
struct op_division ;
struct op_component;

namespace Expression

typedef  std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;


/*
 * tree structure definition 
 */
typedef boost::variant<var,
    boost::recursive_wrapper<unop <op_not> >,
    boost::recursive_wrapper<binop<op_equal> >,
    boost::recursive_wrapper<binop<op_unequal> >,
    boost::recursive_wrapper<binop<op_and> >,
    boost::recursive_wrapper<binop<op_or> >,
    boost::recursive_wrapper<binop<op_difference> >,
    boost::recursive_wrapper<binop<op_sum> >,
    boost::recursive_wrapper<binop<op_factor> >,
    boost::recursive_wrapper<binop<op_division> >,
    boost::recursive_wrapper<binop<op_component> >
> expressionContainer;


template <typename tag> struct binop

    explicit binop(const expressionContainer& l
        , const expressionContainer& r)
        : oper1(l), oper2(r)  
    expressionContainer oper1, oper2;
;

template <typename tag> struct comop

    explicit comop(const expressionContainer& l
        , const expressionContainer& r)
        : oper1(l), oper2(r)  
    expressionContainer oper1, oper2;
;

template <typename tag> struct unop

    explicit unop(const expressionContainer& o) : oper1(o)  
    expressionContainer oper1;

;

struct printer : boost::static_visitor<void>

    printer(std::ostream& os) : _os(os) 
    std::ostream& _os;

    //
    void operator()(const var& v) const  _os << v;

    // Logical
    void operator()(const binop<op_and>& b) const  print(" & ", b.oper1, b.oper2); 
    void operator()(const binop<op_or >& b) const  print(" || ", b.oper1, b.oper2); 
    void operator()(const binop<op_equal>& b) const  print(" == ", b.oper1, b.oper2); 
    void operator()(const binop<op_unequal>& b) const  print(" != ", b.oper1, b.oper2); 


    //Math operators
    void operator()(const binop<op_difference>& b) const  print("-", b.oper1, b.oper2); 
    void operator()(const binop<op_sum>& b) const  print("+", b.oper1, b.oper2); 
    void operator()(const binop<op_factor>& b) const  print("*", b.oper1, b.oper2); 
    void operator()(const binop<op_division>& b) const  print("/", b.oper1, b.oper2); 

    void operator()(const binop<op_component>& b) const  print(",", b.oper1, b.oper2); 

    //unique operators 
     void operator()(const unop<op_not>& u) constprintUnique("!",u.oper1);



     //Printer 
    void print(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
    
        _os << "(";
            boost::apply_visitor(*this, l);
            _os << op;
            boost::apply_visitor(*this, r);
        _os << ")";
    

    void printUnique(const std::string& op, const expressionContainer& l) const
    
            _os << op;
            boost::apply_visitor(*this, l);
    
      void printPower(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
    
            boost::apply_visitor(*this, l);
            _os << op;
            boost::apply_visitor(*this, r);
    
          void printOutSide(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
    
        _os << op;
        _os << "(";
            boost::apply_visitor(*this, l);
        _os << ",";
            boost::apply_visitor(*this, r);
        _os << ")";
    
          /**
           *            void printConst( const expressionContainer& l) const
     
            std::map<std::string, std::string> consts;
            consts["@pi"] = "3.14";
            consts["@ro"]="1.5";
            std::string key="@"+l.
            boost::apply_visitor(*this, consts(key));         
    
           * @param l
           */


;

std::ostream& operator<<(std::ostream& os, const expressionContainer& e)
 boost::apply_visitor(printer(os), e); return os; 



    /*
     * EXPRESSION PARSER DEFINITION 
     */
template <typename It, typename Skipper = boost::spirit::standard_wide::space_type>
struct parserExpression : qi::grammar<It, Expression::expressionContainer(), Skipper>

    parserExpression() : parserExpression::base_type(expr_)
    
        using namespace qi;
        using namespace Expression;
        using custom::fold;

        expr_ = or_.alias();

        // Logical Operators
        or_ = fold<binop<op_or> >(and_.alias())[orOperator_ >> and_];
        and_ = fold<binop<op_and> >(equal_.alias())[andOperator_ >> equal_];
        equal_ = fold<binop<op_equal> >(unequal_.alias())[equalOperator_ >> unequal_]; 
        unequal_ = fold<binop<op_unequal> >(sum_.alias())[unequalOperator_ >>sum_];


        // Numerical Operators
        sum_ = fold<binop<op_sum> >(difference_.alias())[sumOperator_ >> difference_];
        difference_ = fold<binop<op_difference> >(factor_.alias())[differenceOperator_ >> factor_];
        factor_ = fold<binop<op_factor> >(division_.alias())[factorOperator_ >> division_]; 
        division_ = fold<binop<op_division> >(not_.alias())[divisionOperator_ >> not_];


        // UNARY OPERATION
        not_ = (notOperator_ > param_) [_val = boost::phoenix::construct<Expression::unop <op_not>>(_1)] | param_[_val=_1];  
        param_ = (definedParams ) [_val =_1] |  component_[_val = _1];
        component_=definedParams >> '(' >> args_[_val=_1] >>')'| simple[_val = _1];
        simple = (('(' > expr_ > ')') | var_);


        var_ %= qi::raw[+qi::double_];
        args_%=qi::raw[+qi::int_ % ','];
        notOperator_        = qi::char_('!');
        andOperator_        = qi::string("&&");
        orOperator_         = qi::string("||");
        xorOperator_        = qi::char_("^");
        equalOperator_      = qi::string("==");
        unequalOperator_    = qi::string("!=");
        sumOperator_        = qi::char_("+");
        differenceOperator_ = qi::char_("-");
        factorOperator_     = qi::char_("*");
        divisionOperator_   = qi::char_("/");
        greaterOperator_   = qi::char_(">");
        greaterOrEqualOperator_   = qi::string(">=");
        lowerOrEqualOperator_   = qi::string("<=");
        lowerOperator_   = qi::char_("<");
        componentOperator_=qi::char_(",");

        // Defined Function 
        std::map<std::string, std::string> functions;
        functions["fun1"] = "cos";
        functions["fun2"] = "sin";
        for(auto const&x:functions)
        definedFunctions.add (x.first, x.second) ;
        
        //defined parameters 
        std::map<std::string, std::string> paramsList;
        paramsList["imf"] = "imf";
        paramsList["spect"] = "spectro";
        for(auto const&x:paramsList)
        definedParams.add (x.first, x.second) ;
        



        BOOST_SPIRIT_DEBUG_NODES((expr_)(or_)(xor_)(and_)(equal_)(unequal_)(greaterOrEqual_)(lowerOrEqual_)(lower_)(sum_)
                (difference_)(factor_)(division_)(simple)(notOperator_)(andOperator_)(orOperator_)(xorOperator_)(equalOperator_)(unequalOperator_)
                (sumOperator_)(differenceOperator_)(factorOperator_)(divisionOperator_)(greater_)(lower_));

    

private:
    qi::rule<It, Expression::var(), Skipper> var_, args_;
    qi::rule<It, Expression::expressionContainer(), Skipper> not_
        , and_
        , xor_
        , or_
        , equal_
        , unequal_
        , sum_
        , difference_
        , factor_
        , division_
        , simple
        , expr_
        ,plusSign_
        ,minusSign_
       ,greater_
       ,greaterOrEqual_
       ,lowerOrEqual_
       ,lower_
       ,functions_
       ,param_
       ,component_;

    qi::rule<It, Skipper> notOperator_
        , andOperator_
        , orOperator_
        , xorOperator_
        , equalOperator_
        , unequalOperator_
        , sumOperator_
        , differenceOperator_
        , factorOperator_
        , divisionOperator_
        , greaterOperator_ 
        , greaterOrEqualOperator_ 
        ,lowerOrEqualOperator_
        ,lowerOperator_ 
        ,componentOperator_;
        qi::symbols<char, std::string> definedFunctions;
        qi::symbols<char, std::string> definedParams;
;





void parse(const std::string& str)

    std::string::const_iterator iter = str.begin(), end = str.end();

    parserExpression<std::string::const_iterator,qi::space_type> parser;
    Expression::expressionContainer expr;

    bool result = qi::phrase_parse(iter,end,parser,qi::space, expr);

    if(result && iter==end)
    
        std::cout << "Success." << std::endl;
        std::cout << str << " => " << expr << std::endl;
    
    else
    
        std::cout << "Failure." << std::endl;
    


int main()

    parse("imf");
    parse("spect");
    parse("imf(1)");
    parse("spect(1,2)");

成功。 imf => imf 工作正常

成功。 spect => 光谱有效

imf(1) => 失败。预期 imf(1)

spect(1,2) => 失败。预期光谱(1,2)

【问题讨论】:

【参考方案1】:

(1) 的输出不为空。它是 ASCII 0x01:

00000000: 2831 2920 3d3e 2001 0a                   (1) => ..

那是因为

var_ %= qi::lexeme[+qi::int_];

没有做你想做的事。它将1 解析为一个整数,然后将其放入char 的容器中(std::string 是一个容器)。简单解析一个数字,只解析int_,把is当作一个字符串,考虑raw[]

var_ = qi::raw[qi::int_];

现在打印出来了:

Success.
(1) => 1
Success.
1+1 => (1+1)

关于其余部分,我完全不清楚您要如何解析事物。我怀疑你自己也不清楚:

一元运算符是一元,不是唯一的 一元运算符是运算符,而不是表达式子类型或标识符 如果你想让函数接受参数列表,为什么没有规则这样说 如果“definedParams”是参数 - 那和变量有什​​么区别?

为了获得灵感,请查看这些已经使用参数进行解析器函数调用的答案:

Spirit qi parsing to an Abstract Syntax Tree for nested functions

便于比较:Boost::spirit how to parse and call c++ function-like expressions 的此答案即时解释已解析的表达式(这模仿了在您自己的解析器中使用 [std::cout &lt;&lt; "Parse multiplication: " &lt;&lt; (qi::_1 * qi::_2)] 的方法)

那里的另一个答案 (Boost::spirit how to parse and call c++ function-like expressions) 实现了目标,但使用了专用的 AST 表示和单独的解释阶段。

稍微高级/相关:

也定义函数detecting function call with regex Implementing operator precedence with boost spirit 高级:How to provider user with autocomplete suggestions for given boost::spirit grammar?

【讨论】:

+1 来自我,但这里不使用qi::int_ 是一种邪恶吗?它会在不适合 int 的数字上失败,并且由于溢出/下溢检查,它会有点慢。 @NikitaKniazev 你的猜测和我的一样好。语法由OP提出。对我来说改变它似乎没有用。所以,这绝对不是“恶”。这似乎是一种代码气味。就像我说的,“我怀疑 [OP] 也不清楚” :)【参考方案2】:

根据 sehe 的建议,我添加了参数和函数的规则。对于函数,我根据参数的数量构建了 3 个列表“qi::symbols”。 解析器工作正常。

custom_fold_directive.hpp

namespace custom

    namespace tag
    
        struct fold  BOOST_SPIRIT_IS_TAG() ;
    

    template <typename Exposed, typename Expr>
    boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>
    fold(Expr const& expr)
    
        return boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>(expr);
    



namespace boost  namespace spirit 

    template <typename Expr, typename Exposed>
    struct use_directive<qi::domain
          , tag::stateful_tag<Expr, custom::tag::fold, Exposed> >
      : mpl::true_ ;


namespace custom

    template <typename Exposed, typename InitialParser, typename RepeatingParser>
    struct fold_directive
    
        fold_directive(InitialParser const& initial, RepeatingParser const& repeating):initial(initial),repeating(repeating)

        template <typename Context, typename Iterator>
        struct attribute
        
            typedef typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type type;//This works in this case but is not generic
        ;

        template <typename Iterator, typename Context
          , typename Skipper, typename Attribute>
        bool parse(Iterator& first, Iterator const& last
          , Context& context, Skipper const& skipper, Attribute& attr_) const
        
            Iterator start = first;

            typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type initial_attr;


            if (!initial.parse(first, last, context, skipper, initial_attr))
            
                first=start;
                return false;
            

            typename boost::spirit::traits::attribute_of<RepeatingParser,Context,Iterator>::type repeating_attr;

            if(!repeating.parse(first, last, context, skipper, repeating_attr))
            
                boost::spirit::traits::assign_to(initial_attr, attr_);
                return true;
            
            Exposed current_attr(initial_attr,repeating_attr);

            while(repeating.parse(first, last, context, skipper, repeating_attr))
            
                boost::spirit::traits::assign_to(Exposed(current_attr,repeating_attr),current_attr);
            
            boost::spirit::traits::assign_to(current_attr,attr_);
            return true;
        

        template <typename Context>
        boost::spirit::info what(Context& context) const
        
            return boost::spirit::info("fold");
        

        InitialParser initial;
        RepeatingParser repeating;
    ;


namespace boost  namespace spirit  namespace qi

    template <typename Expr, typename Exposed, typename Subject, typename Modifiers>
    struct make_directive<
        tag::stateful_tag<Expr, custom::tag::fold, Exposed>, Subject, Modifiers>
    
        typedef custom::fold_directive<Exposed, Expr, Subject> result_type;

        template <typename Terminal>
        result_type operator()(Terminal const& term, Subject const& subject, Modifiers const&) const
        
            typedef tag::stateful_tag<
                Expr, custom::tag::fold, Exposed> tag_type;
            using spirit::detail::get_stateful_data;

            return result_type(get_stateful_data<tag_type>::call(term),subject);
        
    ;

main.cpp

#include <boost/mpl/list.hpp>

//#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include "custom_fold_directive.hpp"

namespace qi = boost::spirit::qi;

// Expression::triop <fun_generic>

// DEFINING TYPES
struct op_not ;
struct op_or ;
struct op_and ;
struct op_xor ;
struct op_equal ;
struct op_unequal ;
struct op_sum ;
struct op_difference ;
struct op_factor ;
struct op_division ;
struct op_power;
struct op_powerTen;
struct op_plusSign ;
struct op_minusSign ;
struct op_const ;
struct fun_three;
struct fun_two;
struct fun_one;

namespace Expression

typedef  std::string var;
template <typename tag> struct binop;
template <typename tag> struct unop;
template <typename tag> struct triop;
template <typename tag> struct forop;



/*
 * tree structure definition 
 */
typedef boost::variant<var,
    boost::recursive_wrapper<unop <op_not> >,
    boost::recursive_wrapper<binop<op_equal> >,
    boost::recursive_wrapper<binop<op_unequal> >,
    boost::recursive_wrapper<binop<op_and> >,
    boost::recursive_wrapper<binop<op_xor> >,
    boost::recursive_wrapper<binop<op_or> >,
    boost::recursive_wrapper<binop<op_difference> >,
    boost::recursive_wrapper<binop<op_sum> >,
    boost::recursive_wrapper<binop<op_factor> >,
    boost::recursive_wrapper<binop<op_division> >,
    boost::recursive_wrapper<binop<op_power> >, 
    boost::recursive_wrapper<binop<op_powerTen> >,
    boost::recursive_wrapper<unop<op_minusSign> >,
    boost::recursive_wrapper<unop<op_plusSign> >,
    boost::recursive_wrapper<unop<op_const> >,
    boost::recursive_wrapper<binop<fun_one> >,
    boost::recursive_wrapper<triop<fun_two> >,
    boost::recursive_wrapper<forop<fun_three> >
> expressionContainer;


template <typename tag> struct binop

    explicit binop(const expressionContainer& l
        , const expressionContainer& r)
        : oper1(l), oper2(r)  
    expressionContainer oper1, oper2;
;

template <typename tag> struct unop

    explicit unop(const expressionContainer& o) : oper1(o)  
    expressionContainer oper1;

;

template <typename tag> struct triop

    explicit triop(const expressionContainer& functionId,
            const expressionContainer& l
        , const expressionContainer& r)
        : oper1(functionId), oper2(l), oper3(r)  
expressionContainer oper1, oper2, oper3;
;

template <typename tag> struct forop

    explicit forop(const expressionContainer& functionId,
            const expressionContainer& l,
            const expressionContainer& m,
          const expressionContainer& r)
        : oper1(functionId), oper2(l), oper3(m),oper4(r)  
expressionContainer oper1, oper2, oper3,oper4;
;



struct printer : boost::static_visitor<void>

    printer(std::ostream& os) : _os(os) 
    std::ostream& _os;

        void operator()(const var& v) const  _os << v; 

    // Logical
    void operator()(const binop<op_and>& b) const  print(" & ", b.oper1, b.oper2); 
    void operator()(const binop<op_or >& b) const  print(" || ", b.oper1, b.oper2); 
    void operator()(const binop<op_xor>& b) const  print(" | ", b.oper1, b.oper2); 
    void operator()(const binop<op_equal>& b) const  print(" == ", b.oper1, b.oper2); 
    void operator()(const binop<op_unequal>& b) const  print(" != ", b.oper1, b.oper2); 

    //Math operators
    void operator()(const binop<op_difference>& b) const  print("-", b.oper1, b.oper2); 
    void operator()(const binop<op_sum>& b) const  print("+", b.oper1, b.oper2); 
    void operator()(const binop<op_factor>& b) const  print("*", b.oper1, b.oper2); 
    void operator()(const binop<op_division>& b) const  print("/", b.oper1, b.oper2); 

    //Power Math operators 
    void operator()(const binop<op_power>& b) const  print("pow", b.oper1, b.oper2); 
    void operator()(const binop<op_powerTen>& b) const  printPower("e", b.oper1, b.oper2); 

    //unique operators 
     void operator()(const unop<op_not>& u) constprintUnique("!",u.oper1);
     void operator()(const unop<op_plusSign>& u) constprintUnique("",u.oper1);
     void operator()(const unop<op_minusSign>& u) constprintUnique("-",u.oper1);
     void operator()(const unop<op_const>& u) constprintUnique("",u.oper1);

   // print Functions 
    void operator()(const forop<fun_three>& b) const  printFunctionThree(b.oper1, b.oper2, b.oper3,  b.oper4); 
    void operator()(const triop<fun_two>& b) const  printFunctionTwo(b.oper1, b.oper2, b.oper3); 
    void operator()(const binop<fun_one>& b) const  printFunctionOne(b.oper1, b.oper2); 





     //Printer 
    void print(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
    
        _os << "(";
            boost::apply_visitor(*this, l);
            _os << op;
            boost::apply_visitor(*this, r);
        _os << ")";
    

    void printUnique(const std::string& op, const expressionContainer& l) const
    
            _os << op;
            boost::apply_visitor(*this, l);
    
      void printPower(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
    
            boost::apply_visitor(*this, l);
            _os << op;
            boost::apply_visitor(*this, r);
    
          void printOutSide(const std::string& op, const expressionContainer& l, const expressionContainer& r) const
    
        _os << op;
        _os << "(";
            boost::apply_visitor(*this, l);
        _os << ",";
            boost::apply_visitor(*this, r);
        _os << ")";
    
  void printFunctionThree(const expressionContainer& functionId, const expressionContainer& l, const expressionContainer& m, const expressionContainer& r) const
    
        boost::apply_visitor(*this, functionId);
        _os << "(";
            boost::apply_visitor(*this, l);
            _os << ',';
            boost::apply_visitor(*this, m);
            _os << ',';
            boost::apply_visitor(*this, r);
        _os << ")";
    

    void printFunctionTwo(const expressionContainer& functionId, const expressionContainer& l, const expressionContainer& r) const
    
        boost::apply_visitor(*this, functionId);
        _os << "(";
            boost::apply_visitor(*this, l);
            _os << ',';
            boost::apply_visitor(*this, r);
        _os << ")";
    

        void printFunctionOne(const expressionContainer& functionId, const expressionContainer& l) const
    
        boost::apply_visitor(*this, functionId);
        _os << "(";
            boost::apply_visitor(*this, l);
        _os << ")";
    

;

std::ostream& operator<<(std::ostream& os, const expressionContainer& e)
 boost::apply_visitor(printer(os), e); return os; 



    /*
     * EXPRESSION PARSER DEFINITION 
     */
template <typename It, typename Skipper = boost::spirit::standard_wide::space_type>
struct parserExpression : qi::grammar<It, Expression::expressionContainer(), Skipper>

    parserExpression() : parserExpression::base_type(expr_)
    
        using namespace qi;
        using namespace Expression;
        using custom::fold;

        expr_ = or_.alias();

        // Logical Operators
        or_ = fold<binop<op_or> >(and_.alias())[orOperator_ >> and_];
        and_ = fold<binop<op_and> >(equal_.alias())[andOperator_ >> equal_];
        equal_ = fold<binop<op_equal> >(unequal_.alias())[equalOperator_ >> unequal_]; 
        unequal_ = fold<binop<op_unequal> >(sum_.alias())[unequalOperator_ >>sum_];


        // Numerical Operators
        sum_ = fold<binop<op_sum> >(difference_.alias())[sumOperator_ >> difference_];
        difference_ = fold<binop<op_difference> >(factor_.alias())[differenceOperator_ >> factor_];
        factor_ = fold<binop<op_factor> >(division_.alias())[factorOperator_ >> division_]; 
        division_ = fold<binop<op_division> >(functions_.alias())[divisionOperator_ >> functions_];
        functions_ = (threeArgsFunction>>"(">>funArgs_>>componentOperator_>>funArgs_>>componentOperator_>>funArgs_>>")")[_val= boost::phoenix::construct<Expression::forop <fun_three>>(_1,_2,_3,_4)] ||
                               (twoArgsFunction>>"(">>funArgs_>>componentOperator_>>funArgs_>>")")[_val= boost::phoenix::construct<Expression::triop <fun_two>>(_1,_2,_3)]||
                               (oneArgsFunction>>"(">>funArgs_>>")")[_val= boost::phoenix::construct<Expression::binop <fun_one>>(_1,_2)]|not_[_val=_1];

        // UNARY OPERATION
        not_ = (notOperator_ > param_) [_val = boost::phoenix::construct<Expression::unop <op_not>>(_1)] | param_[_val=_1]; 
        param_= (definedParams >>('(' >> (spectArgs_|vectorArgs_)>>')'))[_val='$'+_1+"("+qi::_2+")"] ||
                definedParams[_val='$'+_1]| simple[_val = _1];

        funArgs_=((expr_   |var_) |functions_);
        simple = (('(' > expr_ > ')') |  var_);



        var_ = (+qi::char_('0','9') >> -qi::char_('.') >> -(+qi::char_('0','9'))) | ((qi::char_('.') >> +qi::char_('0','9')));
        vectorArgs_%=qi::raw[qi::int_ > -(qi::char_(',')>>qi::int_) ];
        spectArgs_ %=qi::raw[(qi::int_>>qi::char_(',')>>'*')|(qi::char_('*')>>qi::char_(',')>>qi::int_)];
        notOperator_        = qi::char_('!');
        andOperator_        = qi::string("&&");
        orOperator_         = qi::string("||");
        xorOperator_        = qi::char_("^");
        equalOperator_      = qi::string("==");
        unequalOperator_    = qi::string("!=");
        sumOperator_        = qi::char_("+");
        differenceOperator_ = qi::char_("-");
        factorOperator_     = qi::char_("*");
        divisionOperator_   = qi::char_("/");
        greaterOperator_   = qi::char_(">");
        greaterOrEqualOperator_   = qi::string(">=");
        lowerOrEqualOperator_   = qi::string("<=");
        lowerOperator_   = qi::char_("<");
        componentOperator_=qi::char_(",");

        // Defined Function 
        std::map<std::string, std::string> oneFunctions;
        oneFunctions["fun1_1"] = "f11";
        oneFunctions["fun1_2"] = "f12";
        for(auto const&x:oneFunctions)
        oneArgsFunction.add (x.first, x.second) ;
        

        std::map<std::string, std::string> twoFunctions;
        twoFunctions["fun2_1"] = "f21";
        twoFunctions["fun2_2"] = "f22";
        for(auto const&x:twoFunctions)
        twoArgsFunction.add (x.first, x.second) ;
        

        std::map<std::string, std::string> threeFunctions;
        threeFunctions["fun3_1"] = "f31";
        threeFunctions["fun3_2"] = "f32";
        for(auto const&x:threeFunctions)
        threeArgsFunction.add (x.first, x.second) ;
        
        //defined parameters 
        std::map<std::string, std::string> paramsList;
        paramsList["imf"] = "imf";
        paramsList["param"] = "param";
        for(auto const&x:paramsList)
        definedParams.add (x.first, x.second) ;
        



        BOOST_SPIRIT_DEBUG_NODES((expr_)(or_)(xor_)(and_)(equal_)(unequal_)(sum_)(difference_)(factor_)(division_)
                (simple)(notOperator_)(andOperator_)(orOperator_)(xorOperator_)(equalOperator_)(unequalOperator_)
                (sumOperator_)(differenceOperator_)(factorOperator_)(divisionOperator_)(functions_));

    

private:
    qi::rule<It, Expression::var(), Skipper> var_,  vectorArgs_, spectArgs_;
    qi::rule<It, Expression::expressionContainer(), Skipper> not_
        , and_
        , xor_
        , or_
        , equal_
        , unequal_
        , sum_
        , difference_
        , factor_
        , division_
        , simple
        , expr_
        ,plusSign_
        ,minusSign_
       ,greater_
       ,greaterOrEqual_
       ,lowerOrEqual_
       ,lower_
       ,functions_
       ,param_
       ,funArgs_;

    qi::rule<It, Skipper> notOperator_
        , andOperator_
        , orOperator_
        , xorOperator_
        , equalOperator_
        , unequalOperator_
        , sumOperator_
        , differenceOperator_
        , factorOperator_
        , divisionOperator_
        , greaterOperator_ 
        , greaterOrEqualOperator_ 
        ,lowerOrEqualOperator_
        ,lowerOperator_ 
        ,componentOperator_;
        qi::symbols<char, std::string> twoArgsFunction;
        qi::symbols<char, std::string> oneArgsFunction;
        qi::symbols<char, std::string> threeArgsFunction;
        qi::symbols<char, std::string> definedParams;
;





void parse(const std::string& str)

    std::string::const_iterator iter = str.begin(), end = str.end();

    parserExpression<std::string::const_iterator,qi::space_type> parser;
    Expression::expressionContainer expr;

    bool result = qi::phrase_parse(iter,end,parser,qi::space, expr);

    if(result && iter==end)
    
        std::cout << "Success." << std::endl;
        std::cout << str << " => " << expr << std::endl;
    
    else
    
        std::cout << "Failure." << std::endl;
    


int main()

    parse("1");
    parse("1+1");
    parse("(1+1)");
    //
    parse("fun1_1((1))");
    //
    parse("fun2_1(1,2)");
    parse("fun2_1( (fun2_1(1,1)), (2))");
    //
    parse("fun3_1(fun1_1(1),fun2_1(2,3),imf(1,1))");



输出 成功。 1 => 1 成功。 国际货币基金组织 => 美元国际货币基金组织 成功。 imf(1) => $imf(1) 成功。 (1+1) => (1+1) 成功。 fun1_1((1)) => f11(1) 成功。 fun2_1(1,2) => f21(1,2) 成功。 fun2_1( (fun2_1(1,1)), (2)) => f21(f21(1,1),2) 成功。 fun3_1(fun1_1(1),fun2_1(2,3),imf(1,1)) => f31(f11(1),f21(2,3),$imf(1,1))

【讨论】:

以上是关于Boost::Spirit 表达式解析器,带有定义的函数的主要内容,如果未能解决你的问题,请参考以下文章

boost::spirit 算术公式解析器无法编译

boost::spirit 解析器的编译错误

Boost Spirit x3 -- 使用其他解析器参数化解析器

防止 Boost Spirit Symbol 解析器过早接受关键字

Boost Spirit X3:跳过啥都不做的解析器

Boost.Spirit.X3 中的船长