【发布时间】:2014-10-26 09:30:29
【问题描述】:
我有一个 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> > 以便实现结果,但我想了解是否以及如何组合字符串。
【问题讨论】:
-
当你“从一个值分配给一个容器”并且容器和值都是相同的类型时,Spirit会用值覆盖容器(参见“boost/spirit/home/qi/detail /assign_to.hpp" 搜索
struct assign_to_container_from_value<Attribute, Attribute>)。如果您在symbols中使用vector<char>,则类型不一样,并且选择到达void append_to_string(Attribute& attr, Iterator begin, Iterator end)的另一条路径符合您的预期。 This hack 回避了这个问题,但可能会破坏其他东西。 -
@cv_and_he 是的,这看起来太老套了。我个人不会触及内置类型的特征。虽然 /cc OP 包含在包含的好地方:请注意!
标签: c++ boost boost-spirit