我有一个qi::symbol<char, std::string>
escapedDoubleQuote
可将双""
转换为\"
。
我尝试将其用于更复杂的解析器,并希望结果仍然是单个字符串。但没有成功。我尝试使用和不使用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> >
,以便实现结果,但我想了解是否以及如何组合字符串。
答案 0 :(得分:0)
正如@cv_and_he所建议的那样,“原子”赋值行为源于公开属性类型(std::vector<char>
)到std::string
的转换。
具体来说,它是关于escapedField
的声明属性,因为当它以递归方式调用时,会创建不兼容的合成属性组合:[std::vector<char>, std::string, std::string]
如果您可以保持属性“相等”,则可以解决问题:
MyGrammar() : MyGrammar::base_type(start)
{
subField = +(~qi::char_("\""));
escapedField = subField >> -(escapedDoubleQuote >> escapedField);
start = escapedField;
}
qi::rule<Iterator, std::vector<char>()> subField, escapedField;
qi::rule<Iterator, std::string()> start;
(我删除了lexeme
,因为示例代码中没有队长,请参阅Boost spirit skipper issues)