我正在尝试使用boost::spirit::qi编写一个解析器,它将按原样解析一对"
之间的所有内容,并允许对"
字符进行转义。也就是说,"ab\n\""
应该返回ab\n\"
。我尝试使用以下代码(godbolt link):
#include <boost/spirit/include/qi.hpp>
#include <string>
namespace qi = boost::spirit::qi;
int main() {
std::string input{R"("ab\n\"")"};
std::cout << "[" << input << "]\n";
std::string output;
using Skipper = qi::rule<std::string::const_iterator>;
Skipper skip = qi::space;
qi::rule<std::string::const_iterator, std::string(), Skipper> qstring;
qstring %= qi::lit("\"")
> ( *( (qi::print - qi::lit('"') - qi::lit("\\")) | (qi::char_("\\") > qi::print) ) )
// ^^^^^
> qi::lit("\"");
auto success = qi::phrase_parse(input.cbegin(), input.cend(), qstring, skip, output);
if (!success) {
std::cout << "Failed to parse";
return 1;
}
std::cout << "output = [" << output << "]\n";
return 0;
}
由于一些模板错误,这无法编译,
/opt/compiler-explorer/libs/boost_1_81_0/boost/spirit/home/support/container.hpp:130:12: error: 'char' is not a class, struct, or union type
130 | struct container_value
| ^~~~~~~~~~~~~~~
.....
/opt/compiler-explorer/libs/boost_1_81_0/boost/spirit/home/qi/detail/pass_container.hpp:320:66: error: no type named 'type' in 'struct boost::spirit::traits::container_value<char, void>'
320 | typedef typename traits::container_value<Attr>::type value_type;
如果我将带下划线的qi::char_("\\")
改为qi::lit("\\")
,我可以让代码编译,但这不会为\
创建一个匹配的属性。我还发现,如果我创建一个新规则,只包含Kleene星星,我可以让代码编译,但有没有办法在单个表达式中使用正确的类型?
qi::rule<std::string::const_iterator, std::string(), Skipper> qstring;
qi::rule<std::string::const_iterator, std::string(), Skipper> qstringbody;
qstringbody %= ( *( (qi::print - qi::lit('"') - qi::lit("\\")) | (qi::char_("\\") > qi::print) ) );
qstring %= qi::lit("\"")
> qstringbody
> qi::lit("\"");
1条答案
按热度按时间but5z9lq1#
qi::char_("")与qi::lit("")匹配,但这不会为其匹配的创建属性
这就是你所需要的。解析应该把输入的表示(语法)转换成你有意义的表示(语义)。当然,有一个反映转义的AST是***可能的,但是那样你就不会解析成字符串,而是类似于
假设您不想保留原始输入(否则,
qi::raw[]
就是您的朋友)。应用它
这是我的简化
旁注:它似乎只需要可打印的。我将在下面删除这个假设。当然,您可以根据需要重新引入字符子集。
对分支重新排序后,就不再需要排除
'\\'
,同时还能更好地表达意图:现在,根据示例输入,我推测您可能需要一个C-style treatment of escapes。
(Note这些字符中的一些是冗余的,因为它们已经被编码为辅助输入字符)。
演示
印刷
进一步阅读
有关更完整的转义处理,请参见此处:创建一个boost::spirit::x3解析器,用于带转义序列处理的带引号字符串(也是替代符号的方法)。
它包含了一系列更详细的示例(JSON风格的unicode转义等)。