eps解析器可能会失败,因为"后初始化"那可能会失败

时间:2016-07-11 08:22:35

标签: c++ parsing boost c++14 boost-spirit-x3

我正在阅读the Boost X3 Quick Start tutorial并注意到该行

  

eps是一个特殊的精神解析器,它不消耗任何输入但总是成功的。我们用它来初始化规则的合成属性,在其他任何东西之前归零。 [...]以这种方式使用eps有助于进行前后初始化。

现在我无法帮助,但是想知道eps_that_might_fail是否对解析输入的一部分进行某种语义/后期分析是有用的,这可能会失败,具有某种局部性语法中的检查。

是否存在可能失败的eps,使用此构造进行额外的输入验证是否是一个好主意?

我试图表达的一个可怕的例子:

int_ >> eps_might_fail[is_prime]

如果我没有弄错的话,这只会解析素数,并允许完整的解析器在它需要素数时失败。

1 个答案:

答案 0 :(得分:4)

语义操作适用于此。

Spirit Qi

最自然的例子是

 qi::int_ [ qi::_pass = is_prime(qi::_1) ]

确保在存在语义操作时使用%=规则赋值,因为没有它,语义操作会禁用自动属性传播。

显然,你可能会更加冗长,并写下

 qi::int_ >> qi::eps(is_prime(qi::_val))

正如您所看到的,引用的文档稍微不完整:eps已经可以使用一个参数,在这种情况下是一个懒惰的角色is_prime(qi::_val),它确定它是否成功失败。

Spirit X3

在Spirit X3中,除了X3不与Phoenix集成之外,同样的机制也适用。这意味着两件事:

  • 在最重要的一面,我们可以使用核心语言功能(lambdas)进行语义动作,使学习曲线不那么陡峭
  • 在缺点方面,没有x3::eps的1参数版本需要一个懒惰的演员

这是一个使用X3的演示程序:

<强> Live On Coliru

#include <boost/spirit/home/x3.hpp>

namespace parser {
    using namespace boost::spirit::x3;

    auto is_ltua = [](auto& ctx) {
        _pass(ctx) = 0 == (_attr(ctx) % 42); 
    };

    auto start = int_ [ is_ltua ];

}

#include <iostream>

int main() {
    for (std::string const txt : { "43", "42", "84", "85" }) {
        int data;
        if (parse(txt.begin(), txt.end(), parser::start, data))
            std::cout << "Parsed " << data << "\n";
        else
            std::cout << "Parse failed (" << txt << ")\n";
    }
}

打印

Parse failed (43)
Parsed 42
Parsed 84
Parse failed (85)