Я делаю простой лексер / парсер с boost :: spirit.
Это лексер:
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;
};
Я определил два одинаковых шаблона: WORD и 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"
Обновить Кстати, проблема в том, что у вас может быть только одно совпадение токенов — они совпадают по порядку. Вы / можете / обойти это, используя лексеры. Но я не рекомендую это больше, чем использовать lexer здесь, в первую очередь
Мое предложение будет использовать Ци напрямую:
qi::lexeme[".name"] >> qi::lexeme['"' >> *~qi::char_('"') >> '"']
Мое воспоминание о шаблонах токенов Lexer — одно из чрезвычайно запутанных требований побега.
Я мог бы попытаться выяснить это позже — только из любопытства
#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'