具有已定义函数的Boost :: Spirit表达式解析器

问题描述 投票:1回答:2

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

我想补充一些:

(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) const{printUnique("!",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 =>即时通讯工作

成功。 spect =>光谱工作

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

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

c++ boost boost-spirit
2个回答
2
投票

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

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

那是因为

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

不做你想做的事。它将1解析为整数,然后将其放入char的容器中(std :: string是一个容器)。要简单地解析一个数字,只解析int_并将其视为字符串,请考虑raw[]

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

现在它打印:

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

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

  • 一元运算符是一元的,不是唯一的
  • 一元运算符是运算符,而不是表达式子类型或标识符
  • 如果你想要函数来获取参数列表,为什么没有这样的规则
  • 如果“definedParams”是参数 - 那么它和变量之间有什么区别?

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

更高级/相关:


0
投票

根据这些建议,我添加了参数和函数的规则。对于函数I build 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) const{printUnique("!",u.oper1);}
     void operator()(const unop<op_plusSign>& u) const{printUnique("",u.oper1);}
     void operator()(const unop<op_minusSign>& u) const{printUnique("-",u.oper1);}
     void operator()(const unop<op_const>& u) const{printUnique("",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 => $ imf 成功。 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))

© www.soinside.com 2019 - 2024. All rights reserved.