Compilation error with a boost::spirit parser

前端 未结 1 1353
时光说笑
时光说笑 2020-12-21 17:52

I have a strange problem with a calculator made using boost::spirit. This calculator is supposed to take a string as argument representing a series of arithmetical expressio

相关标签:
1条回答
  • 2020-12-21 18:46

    I'm pretty sure you might have been rearranging stuff in your rules. In fact, the %= auto-rule expression assignments won't work because the synthesized type of the parser expression doesn't resemble an int.

    Basically, you'd change

    factor %= (simple >> '*' >> factor)[ _val = _1 * _2 ]
        |  (simple >> '/' >> factor)[ _val = _1 / _2 ]
        |  (simple >> '%' >> factor)[ _val = _1 % _2 ]
        |   simple;
    
    expr   %= (factor >> '+' >> expr)[ _val = _1 + _2 ]
        |  (factor >> '-' >> expr)[ _val = _1 - _2 ]
        |   factor;
    

    into

    factor  = (simple >> '*' >> factor)[ _val = _1 * _2 ]
            | (simple >> '/' >> factor)[ _val = _1 / _2 ]
            | (simple >> '%' >> factor)[ _val = _1 % _2 ]
            | (simple) [_val = _1 ];
    
    expr    = (factor >> '+' >> expr)[ _val = _1 + _2 ]
            | (factor >> '-' >> expr)[ _val = _1 - _2 ]
            | (factor) [_val = _1 ];
    

    I have fixed up some small issues and created a SSCCE of your post that works, as far as I can tell 1:

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace sp = boost::spirit;
    namespace qi    = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace karma = boost::spirit::karma;
    namespace phx   = boost::phoenix;
    
    namespace Damaris {
    
        template <typename Iterator, typename SymTable>
        struct Calc : qi::grammar<Iterator, std::vector<int>(), ascii::space_type>
        {
            qi::rule<Iterator, std::vector<int>(), ascii::space_type> start;
            qi::rule<Iterator, int(), ascii::space_type> expr;
            qi::rule<Iterator, int(), ascii::space_type> qmark;
            qi::rule<Iterator, int(), ascii::space_type> factor;
            qi::rule<Iterator, int(), ascii::space_type> simple;
            qi::rule<Iterator, std::string(), ascii::space_type> identifier;
            qi::rule<Iterator, int(SymTable), ascii::space_type> value;
    
            Calc(SymTable &sym) : Calc::base_type(start)
            {
                using namespace qi;
    
                identifier = lexeme[( alpha | '_') >> *( alnum | '_')];
    
                value   = identifier[ _val = _r1[_1] ];
    
                simple  = ('(' >> expr >> ')')
                        | int_
                        | value(boost::phoenix::ref(sym));
    
                factor  = (simple >> '*' >> factor)[ _val = _1 * _2 ]
                        | (simple >> '/' >> factor)[ _val = _1 / _2 ]
                        | (simple >> '%' >> factor)[ _val = _1 % _2 ]
                        | (simple) [_val = _1 ];
    
                expr    = (factor >> '+' >> expr)[ _val = _1 + _2 ]
                        | (factor >> '-' >> expr)[ _val = _1 - _2 ]
                        | (factor) [_val = _1 ];
    
                qmark   = char_('?')[ _val = -1 ];
    
                start   = qmark 
                    | (expr % ',');
    
                BOOST_SPIRIT_DEBUG_NODE(start);
                BOOST_SPIRIT_DEBUG_NODE(qmark);
                BOOST_SPIRIT_DEBUG_NODE(expr);
                BOOST_SPIRIT_DEBUG_NODE(factor);
                BOOST_SPIRIT_DEBUG_NODE(simple);
                BOOST_SPIRIT_DEBUG_NODE(value);
                BOOST_SPIRIT_DEBUG_NODE(identifier);
            }
        };
    
    }
    
    int main(int argc, const char *argv[])
    {
        typedef std::map<std::string, int> SymTable;
        SymTable symbols;
        Damaris::Calc<std::string::const_iterator, SymTable> calc(symbols);
    
        symbols["TheAnswerToLifeUniverse"] = 100;
        symbols["Everything"] = -58;
    
        std::string input = "3*4+5/4, TheAnswerToLifeUniverse + Everything";
        std::string::const_iterator f(input.begin()), l(input.end());
        std::vector<int> data;
    
        if (qi::phrase_parse(f,l,calc,ascii::space,data))
            std::cout << "output: " << karma::format(karma::int_ % ", " << karma::eol, data);
        else
            std::cout << "problem: '" << std::string(f,l) << "'\n";
    
        return 0;
    }
    

    Output:

    output: 13, 42
    

    1 gcc 4.6.1, boost 1_48

    0 讨论(0)
提交回复
热议问题