【问题标题】:Why does this Boost.Spirit x3 rule parse correctly with angle brackets, but incorrectly with quotes?为什么这个 Boost.Spirit x3 规则用尖括号正确解析,但用引号不正确?
【发布时间】:2016-08-20 17:38:01
【问题描述】:

下面的程序尝试解析 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));
    }
}

【问题讨论】:

  • 不是很了解 Boost Spirit,但 ~char_('&gt;') 不应该是 ~char_('"') 引用的“标题名称”吗?

标签: c++ c++11 boost boost-spirit boost-spirit-x3


【解决方案1】:

因为你已经得到了比你能接受的更多的答案 (:)) 这是我的 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";
}

【讨论】:

  • 哈,非常好。谢谢!
【解决方案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));
    }
}

请注意,在第二种情况下,您需要匹配除" 之外的所有字符,就像在第一种情况下对&gt; 所做的那样。

【讨论】:

  • 谢谢。我是从 C++17 工作草案语法中提取的。实际上,同时存在 h-char 规则和 q-char 规则。这种愚蠢的疏忽让我发疯了!回想起来,我希望我的问题更实质性。
【解决方案3】:

您需要更改此规则:

auto header_name_quotes   = '"' >> *(~char_('>')) >> '"'; 

auto header_name_quotes   = '"' >> *(~char_('\"')) >> '"'; 

【讨论】:

  • 谢谢!我希望我能接受多个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多