【问题标题】:Semantic Action Boost语义动作增强
【发布时间】:2015-08-03 17:47:12
【问题描述】:

这取自Boost Spirit(一个非常淡化的版本)

template <typename Iterator>
    struct calculator : qi::grammar<Iterator, int(), ascii::space_type>
    {
        calculator() : calculator::base_type(expression)
        {
            qi::_val_type _val;
            qi::_1_type _1;
            qi::uint_type uint_;

            expression = term >> *('+' >> term)| ('-' >> term);
            term = uint_[&term_printer]


        qi::rule<Iterator, int(), ascii::space_type> term, expression;
    };
}

现在,通常,当你想使用语义动作时,你会写类似

expression = term >> *('+' >> term[&my_printer] | ('-' >> term[&my_other_printer]);

...

现在,假设在解析过程中找到 qi::rule term 的实例时,会调用其他函数 term_printer()。然后,my_printer() 将在 term_printer() 之后输出它应该输出的任何内容。我的问题是,有没有人知道在发现“+”字符时(在这个特定示例中)在 term_printer() 之前调用 my_printer() 的方法?

如果您不熟悉一些背景知识: http://boost-spirit.com/distrib/spirit_1_8_3/libs/spirit/doc/semantic_actions.html

【问题讨论】:

    标签: c++ boost-spirit


    【解决方案1】:

    您必须将操作附加到负责+ 的解析器。由于 char 不是 Spirit 解析器(使 '+'[my_parser] 无效),这需要您显式创建 Spirit 解析器,而不是依赖简写符号。速记符号是qi::lit 的语法糖,所以:

    //                     vvvvvvvvvvvv-- interesting part
    expression = term >> *(qi::lit('+')[my_printer] >> term) | ('-' >> term);
    

    lit 解析器没有属性,所以 my_printer 必须可以调用为 my_printer() 才能工作。

    【讨论】:

    • 啊,我曾经考虑过使用 qi::lit 一分钟,但到那时我已经束手无策了。让我试一试,但看起来应该可以。
    • 另外,有没有理由可以将它作为 [my_printer] 和 [&my_printer] 传递,它们仍然可以工作?
    • 我假设 my_printer 是一个函数(而不是一个 lambda 或函数对象等,&amp;my_printer 不起作用)。函数可以转换为函数指针纯右值(标准中的 [conv.func]),这发生在对解析器的operator[] 的调用中。该机制与数组衰减为指向其第一个参数的指针的方式非常相似,只是函数衰减为指向自身的指针,并且对于重载函数有一些额外的规则。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    相关资源
    最近更新 更多