2012-02-26 82 views
2

使用boost :: spirit制作的计算器有一个奇怪的问题。这个计算器应该把一个字符串作为参数来表示由逗号分隔的一系列算术表达式,如“a + 4 * 5,77,(b-c)* 4”。它也允许字符串“?”并在这种情况下返回包含-1的数组。该计算器使用SymTable进行初始化,SymTable是一个模板类参数,用于描述提供[string] - > int运算符的任何类(例如:地图),以解析变量的值。使用boost :: spirit解析器编译错误

下面的代码可以在我的Ubuntu 10.4上使用gcc 4.6.2和gcc 4.4,并且都可以提升1.47和1.48。它也曾在Cray Linux机器上使用gcc 4.5.3和boost 1.47。

#include <boost/bind.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 

namespace sp = boost::spirit; 
namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

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; 

     /** 
     * \brief Constructor. 
     * \param[in] sym : table of symboles. 
     */ 
     Calc(SymTable &sym) : Calc::base_type(start) 
     { 
       identifier = qi::lexeme[(qi::alpha | '_') >> *(qi::alnum | '_')]; 

       value = identifier[qi::_val = qi::labels::_r1[qi::_1]]; 

       simple = ('(' >> expr >> ')') 
         | qi::int_ 
         | value(boost::phoenix::ref(sym)); 

       factor %= (simple >> '*' >> factor)[qi::_val = qi::_1 * qi::_2] 
         | (simple >> '/' >> factor)[qi::_val = qi::_1/qi::_2] 
         | (simple >> '%' >> factor)[qi::_val = qi::_1 % qi::_2] 
         | simple; 

       expr %= (factor >> '+' >> expr)[qi::_val = qi::_1 + qi::_2] 
         | (factor >> '-' >> expr)[qi::_val = qi::_1 - qi::_2] 
         | factor; 

       qmark = qi::char_('?')[qi::_val = -1]; 

       start = qmark 
         | (expr % ','); 
     } 
}; 

} 

今天,我再次尝试编译克雷机上相同的代码(此后至今已进行了升级,我认为),我尝试用gcc 4.6.2和gcc 4.5.2,并都与提升1.48和1.49,而且我总是得到相同的编译错误,我不明白:

/nics/b/home/mdorier/damaris-0.4/common/Calc.hpp:74:3: instantiated from 'Damaris::Calc<Iterator, SymTable>::Calc(SymTable&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, SymTable = Damaris::ParameterSet]' 
/nics/b/home/mdorier/damaris-0.4/common/MetadataManager.cpp:45:79: instantiated from here 
/nics/b/home/mdorier/deploy/include/boost/spirit/home/qi/detail/assign_to.hpp:123:13: error: invalid static_cast from type 'const boost::fusion::vector2<int, int>' to type 'int' 

Calc.hpp中的第74行对应“factor = ...”行。 指示(MetadataManager.cpp:45)实例化线如下:

layoutInterp = new Calc<std::string::const_iterator,ParameterSet>(*parameters); 

与layoutInterp是类型计算值*的和参数为类型PARAMETERSET的*。

任何想法,这个错误来自哪里?谢谢

回答

4

我很确定你可能已经重新安排了规则中的内容。实际上,%=自动规则表达式分配将不起作用,因为解析器表达式的合成类型不像int

基本上,你会改变

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; 

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 ]; 

我有固定了一些小问题,并创建了您的职位,工作,的SSCCE据我可以告诉:

#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: 13, 42 

GCC 4.6.1,提高1_48

+0

包括[答到生命,宇宙和万物的终极问题(http://en.wikipedia.org/维基/ Phrases_from_The_Hitchhiker's_Guide_to_the_Galaxy#Answer_to_the_Ultimate_Question_of_Life.2C_the_Universe.2C_and_Everything_.2842.29) – sehe 2012-02-26 23:25:01