c++ - 精神: discarding attribute during backtracking

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

我不理解以下示例中 x3 的行为(取自更大的语法)。

当然,语法有点奇怪,但大致实现了 (lal)?(<char>)? .当第二组不存在时,默认为 <default> .我不明白为什么要输入 "lal<char>"我得到 defaultchar结果:

#include <iostream>

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/std_pair.hpp>

int main()
{
  namespace x3 = boost::spirit::x3;
  namespace ascii = boost::spirit::x3::ascii;

  using ascii::alnum;
  using ascii::char_;
  using ascii::space;
  using x3::attr;
  using x3::eoi;
  using x3::lexeme;
  using x3::lit;
  using x3::string;

  const auto letter
    = lit("<") >> string("char") >> lit('>')
    | attr(std::string{"default"})
    ;

  const auto letterset
    = letter >> eoi
    | lit("lal") >> letter >> eoi
    ;

  for (std::string i: {"", "<char>", "lal", "lal<char>"})
    {
      auto res = std::string{};
      auto first = i.cbegin();
      auto last = i.cend();
      auto r = x3::phrase_parse(first, last, letterset, space, res);
      if (r && first == last)
        std::cout << i << ": " << res << '\n';
      else
        std::cout << i << ": failed\n";
    }
}

结果:

: default
<char>: char
lal: defaultdefault
lal<char>: defaultchar

我确实注意到,如果我交换 letterset 的替代项,然后我得到了预期的结果,这可能是与回溯相关的标志:在原始情况下,我得到了 default从它的第一次尝试和 char从第二个开始,成功。

我很想将此称为错误,但我是 x3 新手...

这是来自 Boost 1.65 的 X3。

提前致谢@sehe :)

最佳答案

是的,您遇到了回溯的副作用。如果属性是容器(std::string 是容器),Spirit 解析器附加它们的结果,但如果分支失败,则容器不会被清除。

Qi中有hold指令来处理它,X3中没有。我会看看我能对 X3 做些什么,我认为有些解决方案的开销几乎为零,而且没有可怕的 hold 指令。

一般的建议是尝试重写语法以防止回溯,但如果不可能,您可以使用变通方法(它应该是比 hold 稍微更高效的替代方法):

const auto recover_from_backtrack = (rule<class _, std::string>{} = eps) /
    [](auto const& ctx) { x3::_attr(ctx).clear(); x3::_pass(ctx) = false; };

const auto letterset
    = letter >> eoi
    | recover_from_backtrack
    | lit("lal") >> letter >> eoi
    ;

关于c++ - 精神: discarding attribute during backtracking,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48365803/

相关文章:

c++ - 类变量是否包含在 7 +- 2 准则中?

c++ - 如何处理柯南服务器连接被拒绝?

c++ - 这在技术上是 O(n) 算法吗?

c++ - Boost Spirit x3条件(三元)运算符解析器

C++如何重用具有多个返回(退出点)的代码块?

c++ - 在 boost::spirit 上解析递归结构

c++ - Boost spirit x3 - 惰性解析器

c++ - Simple Spirit X3 分词器无法编译,属性不匹配

c++ - 用于解析 `int_` 然后重复等于 `int_` 的 double 的 X3 规则