C++ 尝试分析带引号的字符串文字时,Spirit无法编译
我正在尝试使用Boost::Spirit解析带有转义序列的带引号的字符串。不幸的是,在语法定义中包含引号似乎会导致大量编译时错误(正如Boost所预期的那样)。省略引号可以让程序编译,但显然它不会按预期的方式运行。这是代码(实际上是更大画面的一部分,但它说明了问题):C++ 尝试分析带引号的字符串文字时,Spirit无法编译,c++,parsing,boost,boost-spirit,C++,Parsing,Boost,Boost Spirit,我正在尝试使用Boost::Spirit解析带有转义序列的带引号的字符串。不幸的是,在语法定义中包含引号似乎会导致大量编译时错误(正如Boost所预期的那样)。省略引号可以让程序编译,但显然它不会按预期的方式运行。这是代码(实际上是更大画面的一部分,但它说明了问题): #包括“boost/spirit/include/qi.hpp” #包括“boost/proto/deep_copy.hpp” #包括“boost/optional.hpp” #包括 使用boost::spirit::qi::ch
#包括“boost/spirit/include/qi.hpp”
#包括“boost/proto/deep_copy.hpp”
#包括“boost/optional.hpp”
#包括
使用boost::spirit::qi::char;
使用boost::spirit::qi::lexeme;
使用boost::proto::deep_copy;
自动字符串\文字=深度\复制(
词素[
//字符(““”)
/*>>*/*((char \-'''''-'\\')|(char \('\\')>>char \))
//>>字符(“”)
]);
模板
boost::可选的parse_字符串(迭代器优先、迭代器最后、语法和语法)
{
使用boost::spirit::qi::space;
使用boost::spirit::qi::短语解析;
std::字符串温度;
bool success=短语解析(
第一,
最后,,
gr,
空间
临时雇员
);
if(first==last&&success)
返回温度;
否则返回boost::无;
}
int main()
{
std::字符串str;
我花了一点时间才看到它
归根结底,问题在于[1]
合成
boost::variant<
boost::fusion::vector2<char, char>,
char>
或您希望捕获带引号的原始字符串,而根本不关心公开的属性:
qi::raw [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
后者使用从源迭代器对(qi::raw[]
)到std::string
(绑定属性)的隐式属性转换
现场观看完整内容:
#include <boost/spirit/include/qi.hpp>
#include <boost/proto/deep_copy.hpp>
#include <boost/optional.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace {
auto string_literal = boost::proto::deep_copy(
#if 1
qi::lexeme [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
#else
qi::raw [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
#endif
);
}
template <class Iterator, class Grammar>
boost::optional<std::string> parse_string(Iterator first, Iterator last, Grammar&& gr)
{
std::string temp;
bool success = qi::phrase_parse(
first,
last,
std::forward<Grammar>(gr),
qi::space,
temp
);
if (success && first == last)
return temp;
else return boost::none;
}
int main()
{
std::string str;
std::cout << "string_literal: ";
getline(std::cin, str);
auto presult = parse_string(str.begin(), str.end(), string_literal);
if (presult) {
std::cout << "parsed: '" << *presult << "'\n";
} else
std::cout << "failure\n";
return 0;
}
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间{
自动字符串\u literal=boost::proto::deep\u copy(
#如果1
齐:词素[
'"' >>
*((“\\”>>qi::char|)(qi::char|-”)
>> '"'
]
#否则
齐:生的[
'"' >>
*((“\\”>>qi::char|)(qi::char|-”)
>> '"'
]
#恩迪夫
);
}
模板
boost::可选的parse_字符串(迭代器优先、迭代器最后、语法和语法)
{
std::字符串温度;
bool success=qi::短语解析(
第一,
最后,,
标准:正向(gr),
齐:空间,
临时雇员
);
if(success&&first==last)
返回温度;
否则返回boost::无;
}
int main()
{
std::字符串str;
std::我不能谢谢你。老实说,我不知道该怎么看待Spirit了,所有这些问题都变得越来越累,我想文档也相当缺乏。如果我从头到尾阅读文档,我会知道这一点吗?不管怎样,这非常有帮助-我很可能会使用qi::raw[]
方法,因为我当前的设计最初将所有文本都视为原始字符串,然后使用单独的函数从中“提取”实际值。我想你应该知道:我只是将文档与变量组合在一起,得到了变体。如果你喜欢的话。也就是说,是的,Spirit有它的缺陷(尽管你不遵循常见的习惯用法,例如使用deep\u copy
这一方式有点推动了Spirit v2的发展;顺便说一句,我喜欢由此产生的风格)。我花了大约10分钟才真正看到这个问题,所以你不会听到我说没有问题。再说一次,我很了解spirit,我自己也不会写这个bug(我在写它的时候会意识到char('\\')
对合成属性的影响)所以也许你得给它一点时间。这肯定是一个折衷的办法,我过去也曾为Spirit做过一些案例。但我仍然认为它对一些工作来说是一个非常有价值的工具。我不想没有它。我的辩护是,深拷贝
只是为了节省一些打字时间,因为我真的觉得我对它不够精通我想,这是一个继承自qi::grammar
,带有qi::rule
字段和默认构造函数的struct
结构。你能举个例子说明一个惯用的string\u literal
解析器的样子吗?包装结构的主要目的是允许使用不同的迭代器类型进行实例化:。因此,您可以将其视为“规则容器”(非惯用)或传递模板参数(非惯用)。我坚持使用语法
(第一种方法)。
qi::lexeme [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
qi::raw [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
#include <boost/spirit/include/qi.hpp>
#include <boost/proto/deep_copy.hpp>
#include <boost/optional.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace {
auto string_literal = boost::proto::deep_copy(
#if 1
qi::lexeme [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
#else
qi::raw [
'"' >>
*(('\\' >> qi::char_) | (qi::char_ - '"'))
>> '"'
]
#endif
);
}
template <class Iterator, class Grammar>
boost::optional<std::string> parse_string(Iterator first, Iterator last, Grammar&& gr)
{
std::string temp;
bool success = qi::phrase_parse(
first,
last,
std::forward<Grammar>(gr),
qi::space,
temp
);
if (success && first == last)
return temp;
else return boost::none;
}
int main()
{
std::string str;
std::cout << "string_literal: ";
getline(std::cin, str);
auto presult = parse_string(str.begin(), str.end(), string_literal);
if (presult) {
std::cout << "parsed: '" << *presult << "'\n";
} else
std::cout << "failure\n";
return 0;
}