У меня есть qi::symbol<char, std::string>
escapedDoubleQuote
, который преобразует двойной ""
в \"
.boost :: spirit: как написать парсер, который анализирует 2 строки и объединить их в одну?
Я пытаюсь использовать это в более сложном синтаксическом анализаторе и хочу, чтобы результат оставался одной строкой. Но не получилось. Я пробовал с и без qi::lexeme
, qi::as_string
и qi::as<std::string>
.
#include <iostream>
#include <boost/spirit/home/qi.hpp>
#include <vector>
#include <string>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
struct escapedDoubleQuote_ : qi::symbols<char, std::string >
{
escapedDoubleQuote_()
{
add("\"\"", "\\\"");
}
} escapedDoubleQuote;
template<typename Iterator>
struct MyGrammar : qi::grammar<Iterator, std::string()>
{
MyGrammar() : MyGrammar::base_type(escapedField)
{
subField = +(~qi::char_("\""));
escapedField =
qi::lexeme[ // or qi::as<std::string> ... both seems to do nothing.
subField
>> -(escapedDoubleQuote >> escapedField)
];
}
qi::rule<Iterator, std::string()> subField;
qi::rule<Iterator, std::string()> escapedField;
};
int main()
{
typedef std::string::const_iterator iterator_type;
typedef MyGrammar<iterator_type> parser_type;
parser_type parser;
std::string input = "123\"\"456\"\"789";
std::string output;
iterator_type it = input.begin();
bool parsed = parse(
it,
input.cend(),
parser,
output
);
if(parsed && it == input.end())
{
std::cout << output << std::endl;
// expected: 123\"456\"789
// actual : \"789
}
return 0;
}
В конце концов, я хочу использовать анализатор и иметь выход один std::string
. В примере 123\"\"456\"\"789
должен выводиться номер 123\"456\"789
.
Примечание: Я знаю, что могу определить escapedDoubleQuote
, как qi::symbols<char, std::vector<char> >
так, что результат будет достигнут, но я хочу понять, если и как можно объединить строки.
Когда вы «назначаете контейнер из значения», и оба контейнера и значения одного типа, Дух перезаписывает контейнер со значением (см. «boost/spirit/home/qi/detail/assign_to.hpp "поиск' struct assign_to_container_from_value <Атрибут, Атрибут> '). Если вы используете 'vector' в «символах», типы не совпадают, а другой путь выбран, чтобы достичь «void append_to_string (Attribute & attr, Iterator begin, Iterator end)», который делает то, что вы ожидаете. [Этот хак] (http://coliru.stacked-crooked.com/a/97d43835f2dc1123) обходит проблему, но может сломать что-то еще. –
llonesmiz
@cv_and_he Да, это выглядит слишком хаки. Лично я не буду трогать черты встроенных типов. Хорошее место на включении, хотя/cc OP: обратите внимание! – sehe