2014-12-12 3 views
0

Я делаю простой лексер/парсер с boost :: spirit.C++ boost :: spirit lexer regex

Это лексер:

template <typename Lexer> 
struct word_count_tokens : lex::lexer<Lexer> 
{ 
    word_count_tokens() 
    {                                                  
     this->self.add_pattern 
      ("WORD", "[a-z]+") 
      ("NAME_CONTENT", "[a-z]+") 
      ; 

     word = "{WORD}"; 
     name = ".name"; 
     name_content = "{NAME_CONTENT}"; 

     this->self.add 
      (word)                                       
      (name)                                        
      (name_content)                                      
      ('\n')                                      
      (' ') 
      ('"') 
      (".", IDANY)                                 
      ; 
    }                                  
    lex::token_def<std::string> word; 
    lex::token_def<std::string> name; 
    lex::token_def<std::string> name_content; 
}; 

я определил два идентичных модели: СЛОВО и NAME_CONTENT.

Это грамматика:

template <typename Iterator> 
struct word_count_grammar : qi::grammar<Iterator> 
{ 
    template <typename TokenDef> 
    word_count_grammar(TokenDef const& tok) 
    : word_count_grammar::base_type(start) 
{ 
using boost::phoenix::ref; 
using boost::phoenix::size; 

start = tok.name >> lit(' ') >> lit('"') >> tok.word >> lit('"'); 
} 

qi::rule<Iterator> start; 
}; 

Этот код работает с tok.word в грамматике, но если я заменю tok.word на tok.name_content он не работает. Но tok.word == tok.name_content.

В чем проблема с этим кодом?

PS: что я хочу, чтобы разобрать это что-то вроде: .name "this is my name"

ответ

3

Update Oh, кстати проблема есть вы можете иметь только один маркер матч - они сопоставляются в порядке. Вы/можете/обходите это, используя лексерские состояния. Но я не рекомендую это больше, чем при использовании лексера здесь в первую очередь


Мое предложение было бы использовать ци непосредственно:

qi::lexeme[".name"] >> qi::lexeme['"' >> *~qi::char_('"') >> '"'] 

Воспоминание о LeXeR лексем моделей является одним из чрезвычайно путают требования к побегу.

я мог бы попытаться понять его позже - из любопытства только

Live On Coliru

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

namespace qi = boost::spirit::qi; 

int main() { 
    std::string const input(".name \"this is my name\""); 

    auto f(input.begin()), l(input.end()); 


    std::string parsed_name; 
    if (qi::phrase_parse(f,l, 
       qi::lexeme[".name"] >> qi::lexeme['"' >> *~qi::char_('"') >> '"'], 
       qi::space, 
       parsed_name)) 
    { 
     std::cout << "Parsed: '" << parsed_name << "'\n"; 
    } 
    else 
    { 
     std::cout << "Parsed failed\n"; 
    } 

    if (f!=l) 
     std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n"; 
} 

Печать

Parsed: 'this is my name' 
+0

Что вы имеете в виду под «только один символический матч "? Что делать, если я хочу, чтобы мое регулярное выражение с qi напрямую? Моим регулярным выражением является «[a-z] +», не так ли? –

+0

@ThibaultMartinez вы не можете (полезно) иметь два одинаковых шаблона, потому что один никогда не будет соответствовать. И наоборот, вы не можете юридически добавить один и тот же токен в несколько состояний, поэтому при использовании нескольких состояний это перестанет быть истинным. Не стесняйтесь просматривать [тег: boost-spirit-lex] ответы, как это сделать. Но это будет некрасиво, это будет не быстро, и удачи, если вам нужна информация о позиции источника для сообщений об ошибках и т. Д. – sehe

+0

Даже если я не использую его? Потому что я использую только один из них ... –

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