【问题标题】:Boost.Spirit parser does not matchBoost.Spirit 解析器不匹配
【发布时间】:2013-03-22 14:56:43
【问题描述】:

我很难理解为什么以下解析器无法解析 test。 调用qi::phrase_parse后,result为真,it2指向字符串末尾,但mynr仍为0:

std::string test = "#define   SOMEMACRO 8.0";
  auto it2 = test.begin();
  auto endIt2 = test.end();
  double mynr = 0;
  bool result = 
    qi::phrase_parse(
      it2, 
      endIt2, 
      ("#define" >> (*qi::alnum) >> qi::double_[ref(mynr) = qi::_1]), 
      qi::space);

我怀疑它与qi::alnum 和空间跳过有关。

我尝试将我的案例简化为单个组件。我分别验证了这三个解析器,发现:

  • “#define”确实消耗了“#define”
  • (*qi::alnum) 可以消费 SOMEMACRO
  • qi::double_ 可以消费 8.0

单独地,每个解析器都可以正常工作,但是以上面的形式组合在一起却很奇怪。进一步的小测试似乎向我表明(*qi::alnum) 当我使用它时,它似乎消耗的不仅仅是SOMEMACRO,而是字符串的其余部分。

【问题讨论】:

    标签: c++ boost boost-spirit boost-spirit-qi


    【解决方案1】:

    您的更新实际上让我意识到发生了什么。你是对的,*alnum 吃的比你想吃的多。

    ("#define" >> lexeme[*qi::alnum] >> (qi::double_)[boost::phoenix::ref(mynr) = boost::spirit::_1])
    

    这行得通。

    *alnum 正在吃字母数字字符,并跳过它们之间的空格。所以它实际上吃了SOMEMACRO 8。然后,当我建议它在最后吃8.0时起作用时,那是因为双解析器消耗了.0

    顶部的新解析器要求*alnum 中间没有空格。

    以下是有关语法的新注意事项:

    1. 我已经包含了存储双精度值的语义动作。它将它存储在一个名为 mynr 的双精度中。
    2. 我已将*alnum 包裹在lexeme 中。这会导致解析器在里面时不会跳过任何字符。
    3. 有了这个正确的语法,它就可以解析"#define SOMEMACRO 8.0""#define SOMEMACRO 8"

    【讨论】:

    • 我试过了,它确实在使用 8.0 时消耗了整个字符串。但是我不认为它会像我期望的那样解析它。我已经用我的发现更新了我的问题。
    • 你的语义动作应该是:[boost::phoenix::ref(mynr) = boost::spirit::_1].
    • 这对我来说现在解析正确,我错过了 *alnum 也在做 preskips。
    • 预跳过是什么意思?这是否意味着它使用parse_phrase 中的skip 参数来跳过alnum char 之前的内容?另外,这就是为什么需要eps 吗?因为eps 不做预跳转?
    • 所以,我对它进行了一些修改以简化它。在这种情况下lexemeno_skip 效果更好。我会尝试解释两者。在您原来的情况下,您的语法与*space >> #define >> *space >> *(*space >> alnum) >> *space >> double >> *space 相同。我们想要将其转换为#define >> *space >> *alnum >> *space >> double >> *space. Note that the only difference is the *alnum` 区域。 Lexeme 会导致这种变化发生。
    猜你喜欢
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多