2013-05-13 1 views
2

Когда я пытаюсь скомпилировать код ниже (используя пример из boost\spirit\home\lex\argument.hpp: value_setter) Я получаю следующее сообщение об ошибке компилятора:не может скомпилировать повышение дух-пример для изменения значения маркеров с помощью Phoenix актера

c:\program files (x86)\boost\boost_1_50\boost\range\iterator.hpp(63) : error C2039: 'type' : is not a member of 'boost::mpl::eval_if_c<C,F1,F2>' 
with 
[ 
    C=true, 
    F1=boost::range_const_iterator<const char *>, 
    F2=boost::range_mutable_iterator<const char *const > 
] 
c:\program files (x86)\boost\boost_1_50\boost\range\iterator_range_core.hpp(56) : see reference to class template instantiation 'boost::range_iterator<C>' being compiled 
with 
[ 
    C=const char *const 
] 
... 

Без семантического действия, все прекрасно компилируется. Вот пример:

#include <boost/spirit/include/lex_lexertl.hpp> 
namespace lex = boost::spirit::lex; 

template <typename Lexer> 
struct my_tokens : lex::lexer<Lexer> 
{ 
    my_tokens() 
    { 
     identifier = "[a-zA-Z_][a-zA-Z0-9_]*"; 
     this->self = identifier [ lex::_val = "identifier" ] // problematic action 
        ; 
    } 
    lex::token_def<> identifier; 
}; 

int main() 
{ 
    typedef std::string::iterator base_iterator_type; 
    typedef 
     lex::lexertl::actor_lexer<lex::lexertl::token<base_iterator_type> > 
     lexer_type; 

    my_tokens<lexer_type> myLexer; 
    std::string str = "id1"; 
    base_iterator_type first = str.begin(); 
    bool r = lex::tokenize(first, str.end(), myLexer); 

    if (!r) { 
     std::string rest(first, str.end()); 
     std::cerr << "Lexical analysis failed\n" << "stopped at: \"" 
        << rest << "\"\n"; 
    } 
} 

Что происходит не так? Как установить/изменить значение токена?

ответ

3

Вашего token_def должен выставить ожидаемый тип атрибута (ошибка компиляции предлагает вам присваивает строку буквальной к iterator_range):

lex::token_def<std::string> identifier; 

Теперь совпасть тип в назначении

this->self = identifier [ lex::_val = std::string("identifier") ] 

Не забудьте обновить тип токена, чтобы отразить набор возможных типов атрибутов токена:

typedef 
    lex::lexertl::actor_lexer<lex::lexertl::token<base_iterator_type, 
     boost::mpl::vector<std::string> > > 
    lexer_type; 

Теперь он должен составить:

#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
namespace lex = boost::spirit::lex; 
namespace phx = boost::phoenix; 

template <typename Lexer> 
struct my_tokens : lex::lexer<Lexer> 
{ 
    my_tokens() 
    { 
     identifier = "[a-zA-Z_][a-zA-Z0-9_]*"; 
     this->self = identifier [ lex::_val = std::string("identifier") ] 
        ; 
    } 
    lex::token_def<std::string> identifier; 
}; 

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

    my_tokens<lexer_type> myLexer; 
    std::string str = "id1"; 
    base_iterator_type first = str.begin(); 
    bool r = lex::tokenize(first, str.end(), myLexer); 

    if (!r) { 
     std::string rest(first, str.end()); 
     std::cerr << "Lexical analysis failed\n" << "stopped at: \"" 
        << rest << "\"\n"; 
    } 
} 
+0

Возможность добавления типов атрибутов для определения маркеров типа сложно. Документация по этому вопросу довольно короткая. Это был ключевой момент, который мне не хватало. Спасибо, что указали! – coproc

+0

Возможно ли сформировать значение токена на основе совпадающих групп в регулярном выражении? Или, по крайней мере, получить доступ к ним? –

+0

Я закончил вопрос для этого отдельного вопроса: http://stackoverflow.com/questions/35476454/how-to-make-boost-spirit-lex-token-value-be-a-substring-of-matched-sequence- до –