2015-10-02 2 views
2

Я продолжаю изучать библиотеку Boost Spirit, и у меня есть проблема с примером, который я не мог скомпилировать. Источником примера вы можете ознакомиться здесь: source place. Также вы можете посмотреть этот код и скомпилировать результат на Coliru.Can`t compile boost spirit example4.cpp

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 

#include <iostream> 
#include <fstream> 
#include <string> 

using namespace boost::spirit; 
using boost::phoenix::val; 

/////////////////////////////////////////////////////////////////////////////// 
// Token definition 
/////////////////////////////////////////////////////////////////////////////// 
template <typename Lexer> 
struct example4_tokens : lex::lexer<Lexer> 
{ 
    example4_tokens() 
    { 
     identifier = "[a-zA-Z_][a-zA-Z0-9_]*"; 
     constant = "[0-9]+"; 
     if_ = "if"; 
     else_ = "else"; 
     while_ = "while"; 

     this->self = lex::token_def<>('(') | ')' | '{' | '}' | '=' | ';' | constant; 
     this->self += if_ | else_ | while_ | identifier; 

     this->self("WS") 
      = lex::token_def<>("[ \\t\\n]+") 
      | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/" 
      ; 
    } 

    lex::token_def<> if_, else_, while_; 
    lex::token_def<std::string> identifier; 
    lex::token_def<unsigned int> constant; 
//] 
}; 

template <typename Iterator, typename Lexer> 
struct example4_grammar 
    : qi::grammar<Iterator, qi::in_state_skipper<Lexer> > 
{ 
    template <typename TokenDef> 
    example4_grammar(TokenDef const& tok) 
     : example4_grammar::base_type(program) 
    { 
     using boost::spirit::_val; 

     program 
      = +block 
      ; 

     block 
      = '{' >> *statement >> '}' 
      ; 

     statement 
      = assignment 
      | if_stmt 
      | while_stmt 
      ; 

     assignment 
      = (tok.identifier >> '=' >> expression >> ';') 
       [ 
        std::cout << val("assignment statement to: ") << _1 << "\n" 
       ] 
      ; 

     if_stmt 
      = ( tok.if_ >> '(' >> expression >> ')' >> block 
        >> -(tok.else_ >> block) 
       ) 
       [ 
        std::cout << val("if expression: ") << _2 << "\n" 
       ] 
      ; 

     while_stmt 
      = (tok.while_ >> '(' >> expression >> ')' >> block) 
       [ 
        std::cout << val("while expression: ") << _2 << "\n" 
       ] 
      ; 

     expression 
      = tok.identifier [ _val = _1 ] 
      | tok.constant [ _val = _1 ] 
      ; 
    } 

    typedef boost::variant<unsigned int, std::string> expression_type; 

    qi::rule<Iterator, qi::in_state_skipper<Lexer> > program, block, statement; 
    qi::rule<Iterator, qi::in_state_skipper<Lexer> > assignment, if_stmt; 
    qi::rule<Iterator, qi::in_state_skipper<Lexer> > while_stmt; 

    qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> > expression; 
}; 

/////////////////////////////////////////////////////////////////////////////// 
int main() 
{ 
    typedef std::string::iterator base_iterator_type; 
    typedef lex::lexertl::token<base_iterator_type, boost::mpl::vector<unsigned int, std::string> > token_type; 
    typedef lex::lexertl::lexer<token_type> lexer_type; 

    typedef example4_tokens<lexer_type> example4_tokens; 
    typedef example4_tokens::iterator_type iterator_type; 
    typedef example4_grammar<iterator_type, example4_tokens::lexer_def> example4_grammar; 

    example4_tokens tokens;       // Our lexer 
    example4_grammar calc(tokens);     // Our parser 

    std::string str; 

    std::string::iterator it = str.begin(); 
    iterator_type iter = tokens.begin(it, str.end()); 
    iterator_type end = tokens.end(); 

    bool r = qi::phrase_parse(iter, end, calc, qi::in_state("WS")[tokens.self]); 

    if (r && iter == end) 
    { 
     std::cout << "-------------------------\n"; 
     std::cout << "Parsing succeeded\n"; 
     std::cout << "-------------------------\n"; 
    } 
    else 
    { 
     std::cout << "-------------------------\n"; 
     std::cout << "Parsing failed\n"; 
     std::cout << "-------------------------\n"; 
    } 

    std::cout << "Bye... :-) \n\n"; 
    return 0; 
} 

Когда я пытаюсь скомпилировать я получаю много ошибок, полный список на Coliru.

Что случилось с этим примером? Что и зачем нужно изменить, чтобы скомпилировать его? Как определить, что именно не скомпилирует процесс компиляции?

+3

Я не совсем уверен, но попробуйте добавить '#define BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT' Часть ошибки, которая на самом деле имеет значение, это' /usr/local/include/boost/variant/get.hpp:229:5: ошибка: статическое утверждение failed: boost :: variant не содержит указанного типа U, вызов boost :: get (const boost :: variant &) всегда будет бросать boost :: bad_get exception' – Fsmv

+0

Вы совершенно правы. Когда я добавлю это определение, пример может быть скомпилирован. – AeroSun

ответ

4

Как говорят Fsmv, есть необходимо добавить следующий определить:

#define BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT 

После этого примера может быть скомпилирован.

Смежные вопросы