下面的程序试图解析C ++标头包含字符串,例如"my/file.hpp"
和<my/file.hpp>
。由于我不明白的原因,我的代码无法解析"
标题。这是Spirit中的一个错误,还是我错过了一些明显的错误?
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <string>
#include <cassert>
using namespace boost::spirit::x3;
int main() {
auto header_name_brackets = '<' >> *(~char_('>')) >> '>';
auto header_name_quotes = '"' >> *(~char_('>')) >> '"';
{
auto s = std::string{"<my/file.hpp>"};
std::string parsed;
assert(phrase_parse(s.begin(), s.end(), header_name_brackets, space, parsed));
}
{
auto s = std::string{"\"my/file.hpp\""};
std::string parsed;
// this assert fails, but I don't know why.
assert(phrase_parse(s.begin(), s.end(), header_name_quotes, space, parsed));
}
}
答案 0 :(得分:4)
因为你已经有了比你能接受的更多答案(:))这里是我的$ 0.02:
template <typename Prefix, typename Postfix>
static auto quoted_(Prefix const& prefix, Postfix const& postfix) {
using namespace boost::spirit::x3;
return rule<struct _, std::string, true> {} = omit[prefix] >> *(char_ - postfix) >> omit[postfix];
}
现在你可以写
了auto header_name_brackets = quoted_('<', '>');
auto header_name_quotes = quoted_('"');
第二个假设明显方便过载。
事实上,我认为有一个错误会跳过分隔符内的空白。通过添加lexeme[]
:
template <typename Prefix, typename Postfix>
static auto quoted_(Prefix const& prefix, Postfix const& postfix) {
using namespace boost::spirit::x3;
return rule<struct _, std::string, true> {} = lexeme [
omit[prefix] >> *(char_ - postfix) >> omit[postfix]
];
}
<强> Live On Coliru 强>
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <cassert>
template <typename Prefix, typename Postfix>
static auto quoted_(Prefix const& prefix, Postfix const& postfix) {
using namespace boost::spirit::x3;
return rule<struct _, std::string, true> {} = lexeme [
omit[prefix] >> *(char_ - postfix) >> omit[postfix]
];
}
template <typename Prefix>
static auto quoted_(Prefix const& prefix) { return quoted_(prefix, prefix); }
int main() {
using boost::spirit::x3::space;
auto header_name_brackets = quoted_('<', '>');
auto header_name_quotes = quoted_('"');
{
auto s = std::string{"<my/file.hpp>"};
std::string parsed;
assert(phrase_parse(s.begin(), s.end(), header_name_brackets, space, parsed));
}
{
auto s = std::string{"\"my/file.hpp\""};
std::string parsed;
assert(phrase_parse(s.begin(), s.end(), header_name_quotes, space, parsed));
}
std::cout << "Bye\n";
}
答案 1 :(得分:2)
您需要更改此规则:
auto header_name_quotes = '"' >> *(~char_('>')) >> '"';
到
auto header_name_quotes = '"' >> *(~char_('\"')) >> '"';
答案 2 :(得分:2)
这对我有用:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <string>
#include <cassert>
using namespace boost::spirit::x3;
int main() {
auto header_name_brackets = '<' >> *(~char_('>')) >> '>';
auto header_name_quotes = '"' >> *(~char_('"')) >> '"';
{
auto s = std::string{"<my/file.hpp>"};
std::string parsed;
assert(phrase_parse(s.begin(), s.end(), header_name_brackets, space, parsed));
}
{
auto s = std::string{"\"my/file.hpp\""};
std::string parsed;
// this assert fails, but I don't know why.
assert(phrase_parse(s.begin(), s.end(), header_name_quotes, space, parsed));
}
}
请注意,您需要匹配第二种情况下除"
之外的所有字符,就像您在第一种情况下使用>
一样。