Boost::Spirit 在尝试解析带引号的字符串文字时编译失败
Boost::Spirit fails to compile when trying to parse quoted string literal
我正在尝试使用 Boost::Spirit 解析带有转义序列的带引号的字符串。不幸的是,似乎在语法定义中包含引号会导致大量(-ly 无用)编译时错误(正如人们对 Boost 所期望的那样)。省略引号可以让程序编译,但显然它不会按预期运行。这是代码(实际上是更大图景的一部分,但它演示了问题):
#include "boost/spirit/include/qi.hpp"
#include "boost/proto/deep_copy.hpp"
#include "boost/optional.hpp"
#include <string>
using boost::spirit::qi::char_;
using boost::spirit::qi::lexeme;
using boost::proto::deep_copy;
auto string_literal = deep_copy(
lexeme[
// char_('"')
/* >> */ *((char_ - '"' - '') | (char_('') >> char_))
// >> char_('"')
]);
template <class Iterator, class Grammar>
boost::optional<std::string> parse_string(Iterator first, Iterator last, Grammar&& gr)
{
using boost::spirit::qi::space;
using boost::spirit::qi::phrase_parse;
std::string temp;
bool success = phrase_parse(
first,
last,
gr,
space,
temp
);
if (first == last && success)
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;
} else
std::cout << "failuren";
return 0;
}
取消注释string_literal
定义的注释部分会导致错误。在当前状态(带注释)下,代码将编译。我已经尝试了几件事,例如将引号移动到parse_string
中,以及使用不太具体的定义(上面的定义是我能想到的最不具体的,仍然有用,正确的语法在 OCaml 语言手册中,但我想我可以单独验证转义序列),但没有任何效果。
我的 Boost 版本是 1.56.0,我的编译器是 MinGW-w64 g++ 4.9.1。任何帮助都非常感谢。
我花了一点时间才看到它。
问题在于 - 最终 - 事实上[1]
(qi::char_('') >> qi::char_) | (qi::char_ - '"')
合成为
boost::variant<
boost::fusion::vector2<char, char>,
char>
而不是,正如您可能期望的那样char
或std::vector<char>
.Spirit的属性兼容性规则近乎魔法,它们让你侥幸逃脱(这真是太漂亮了),但它也隐藏了你的意识问题。
只有当你进一步使规则复杂化时,才会抱怨它。
现在我可以看到两种可能的路由:要么你想返回去转义的字符串值(不带引号),你把它改成:[2]
qi::lexeme [
'"' >>
*(('' >> qi::char_) | (qi::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 << "failuren";
return 0;
}
[1] 通过重新排序分支略有简化
[2](请注意,''
等效于通过表达式模板操作数的隐式转换qi::lit('')
)
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 如何使用字符串文字作为宏参数
- 有没有办法从非C/C++文件中读取C++原始字符串文字的内容
- 构造<int>具有 2 个字符串文字的向量
- 初始化或分配空字符串文字到指向 C 中的 char 的指针或指向 C++ 中 const char 的指针的原因是什么
- 方便地对C++中的所有字符串文字进行模糊处理
- 比较 std::string 和 C 样式字符串文字
- 如何从char16_t字符串文字中读取双精度?
- 如果我在块中编写字符串文字,是否会从数据部分复制整个字符串数据?
- C++ 不能在cout中使用向量和字符串文字
- 为什么必须将 const 添加到 constexpr 中才能进行字符串文字声明?
- C++:Unicode 字符串文字的可移植性
- 返回空字符串文字 VS. 返回空点 - 它们是一样的吗?
- 确保字符指针始终指向相同的字符串文字
- 如何按照 Google C++风格指南连接字符串文字?
- 通过 constexpr 中的 'const char *' glvalue 访问字符串文字的值会出错
- 字符串文字到 char 数组的转换如何在C++中实际工作
- 另一个字符串文字,UDL 迷宫
- strlen 是否针对字符串文字进行了优化?
- 用户定义的字符串文字为字符串null终止