Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
376 views
in Technique[技术] by (71.8m points)

c++ - Boost spirit compile issue

Hi I am very new to boost spirit library. Can you please let me know why below code is not compile?

When I add "scientificNumber" rule to my grammar it dont compile. What can be the reason? I have added "scientificNumber" rule to make it possible to parse scientific notaion like "12E10". I dont know if this was the right way to do it.

    namespace qi    = boost::spirit::qi;
    namespace phx   = boost::phoenix;

    typedef boost::function<double()> Value;

    #define BINARY_FUNCTOR(name, op)                        
    struct name                                             
    {                                                       
        name(Value x, Value y): x_(x), y_(y) {}               
        double operator()() { return x_() op y_(); }          
        Value x_, y_;                                         
    }; 

    BINARY_FUNCTOR(ADD, +)
    BINARY_FUNCTOR(SUB, -)
    BINARY_FUNCTOR(MUL, *)
    BINARY_FUNCTOR(DIV, /)

    struct LIT
    {
        LIT(double x): x_(x) {}
        double operator()() { return x_; }
        double x_;
    };

    struct NEG
    {
        NEG(Value x): x_(x) {}
        double operator()() { return -x_(); }
        Value x_;
    };

    struct SQRT
    {
        SQRT(Value x): x_(x){}
        double operator()() {return sqrt(x_()); }
        Value x_;
    };

    struct SCIENTIFIC
    {
        SCIENTIFIC(std::wstring x): x_(x){}
        double operator()() {return boost::lexical_cast<double>(x_); }
        std::wstring x_;
    };


    // expression grammar definition
    template <typename It, typename Skipper=boost::spirit::qi::space_type>
    struct parser : boost::spirit::qi::grammar<It, Value(),  Skipper>
    {
        parser() : parser::base_type(expression)
        {
            using namespace qi;
            expression =
                term                    [_val = _1]
                >> *( ('+' >> term  [_val = phx::construct<ADD>(_val, _1)])
                    | ('-' >> term  [_val = phx::construct<SUB>(_val, _1)])
                    );

            term =
                factor                [_val = _1]
                >> *( ('*' >> factor  [_val = phx::construct<MUL>(_val, _1)])
                    | ('/' >> factor  [_val = phx::construct<DIV>(_val, _1)])
                    );

            factor =
                double_               [_val = phx::construct<LIT>(_1)]
                |   scientificNumber  [_val = phx::construct<SCIENTIFIC>(_1)]
                |   '(' >> expression [_val = _1] >> ')'
                |   ('-' >> factor    [_val = phx::construct<NEG>(_1)])
                |   ('+' >> factor    [_val = _1])
                            |   (string("SQRT") >> '(' >> expression [_val = phx::construct<SQRT>(_1)] >> ')');

          scientificNumber = lexeme[+(boost::spirit::qi::digit) >> lit('E') >>  lit('-') >> +(boost::spirit::qi::digit)];


            BOOST_SPIRIT_DEBUG_NODE(expression);
            BOOST_SPIRIT_DEBUG_NODE(term);
            BOOST_SPIRIT_DEBUG_NODE(factor);
        }

      private:
        boost::spirit::qi::rule<It, std::wstring , Skipper> scientificNumber;
        qi::rule<It, Value(), Skipper> expression, term, factor;

    };



        int main()
        {

            std::wstring::const_iterator beginExpression(testExp.begin());
            std::wstring::const_iterator endExpression(testExp.end());
            typedef std::wstring::const_iterator It;
            parser<It , boost::spirit::qi::space_type> expressionParser;
            Value logicExpression;
   phrase_parse(beginExpression,endExpression,expressionParser,boost::spirit::qi::space,logicExpression);
       }

Can you please also let me know what is the boost::spirit::qi::grammar

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you just search for the first line that contains error, you'll see the following comment:

            // If you are seeing a compilation error here stating that the
            // fourth parameter can't be converted to a required target type
            // then you are probably trying to use a rule or a grammar with
            // an incompatible skipper type.
            if (f(first, last, context, skipper))

This is bingo: it tells you exactly what is wrong. It thinks std::wstring is the skipper.

qi::rule<It, std::wstring, Skipper> scientificNumber; // huh?

As per the documentation, you need to spell the attribute type as the return type of a function signature:

qi::rule<It, std::wstring(), Skipper> scientificNumber;

Now, it compiles and runs, see below, printing the output:

Success: true   Value: 2.7e-09

IMPORTANT

However, using lexical_cast inside Boost Spirit to... parse a number (!?!) is a travesty. You could just have tested the original thing: it works with just the LIT (qi::double_) parser just as well. See http://ideone.com/mI1ESI

Again, see the documentation here: link

Full Code

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/lexical_cast.hpp>

namespace qi    = boost::spirit::qi;
namespace phx   = boost::phoenix;

typedef boost::function<double()> Value;

#define BINARY_FUNCTOR(name, op)                        
    struct name                                         
    {                                                   
        name(Value x, Value y): x_(x), y_(y) {}         
        double operator()() { return x_() op y_(); }    
        Value x_, y_;                                   
    };

BINARY_FUNCTOR(ADD, +)
BINARY_FUNCTOR(SUB, -)
BINARY_FUNCTOR(MUL, *)
BINARY_FUNCTOR(DIV, /)

struct LIT
{
    LIT(double x): x_(x) {}
    double operator()()
    {
        return x_;
    }
    double x_;
};

struct NEG
{
    NEG(Value x): x_(x) {}
    double operator()()
    {
        return -x_();
    }
    Value x_;
};

struct SQRT
{
    SQRT(Value x): x_(x) {}
    double operator()()
    {
        return sqrt(x_());
    }
    Value x_;
};

struct SCIENTIFIC
{
    SCIENTIFIC(std::wstring x): x_(x) {}
    double operator()()
    {
        return boost::lexical_cast<double>(x_);
    }
    std::wstring x_;
};


// expression grammar definition
template <typename It, typename Skipper=qi::space_type>
struct parser : qi::grammar<It, Value(),  Skipper>
{
    parser() : parser::base_type(expression)
    {
        using namespace qi;
        expression =
            term                    [_val = _1]
            >> *(('+' >> term       [_val = phx::construct<ADD>(_val, _1)])
                    | ('-' >> term  [_val = phx::construct<SUB>(_val, _1)])
                );
        term =
            factor                  [_val = _1]
            >> *(('*' >> factor     [_val = phx::construct<MUL>(_val, _1)])
                 | ('/' >> factor   [_val = phx::construct<DIV>(_val, _1)])
                );
        factor =
            double_                 [_val = phx::construct<LIT>(_1)]
            |   scientificNumber    [_val = phx::construct<SCIENTIFIC>(_1)]
            | '(' >> expression [_val = _1] >> ')'
            | ('-' >> factor        [_val = phx::construct<NEG>(_1)])
            | ('+' >> factor        [_val = _1])
            | (string("SQRT") >> '(' >> expression [_val = phx::construct<SQRT>(_1)] >> ')');

        scientificNumber = lexeme[+(qi::digit) >> lit('E') >>  lit('-') >> +(qi::digit)];

        BOOST_SPIRIT_DEBUG_NODE(expression);
        BOOST_SPIRIT_DEBUG_NODE(term);
        BOOST_SPIRIT_DEBUG_NODE(factor);
    }

    private:
    qi::rule<It, std::wstring(), Skipper> scientificNumber;
    qi::rule<It, Value(), Skipper> expression, term, factor;

};



int main()
{
    const std::wstring testExp = L"3E-10*(12-3)";

    typedef std::wstring::const_iterator It;
    It f(testExp.begin()), e(testExp.end());
    parser<It, qi::space_type> expressionParser;

    Value logicExpression;
    bool ok = phrase_parse(f,e,expressionParser,qi::space,logicExpression);

    std::cout << "Success: " << std::boolalpha << ok << "Value: " << logicExpression() << '
';
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...