c++ - 在语义 Action 中 boost spirit 改变变量值

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

我想在语义操作中更改局部变量值,如下所示:

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;
using boost::phoenix::bind;

void dummy(const std::vector<char>& v, int& var)
{
    var = 7;
}

template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, std::string(), ascii::space_type>
{
public:
    x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
    {
        using namespace qi;
        int local_var = 0;
        start_rule = (+(char_ - ";"))[bind(dummy, _1, ref(local_var))];
        //repeat(ref(local_var))[some_rule];
    }
private:
    qi::rule<Iterator, std::string(), ascii::space_type> start_rule;
};

int main()
{
    typedef std::string::const_iterator iter;
    std::string storage("string;aaa");
    iter it_begin(storage.begin());
    iter it_end(storage.end());
    std::string read_data;
    using boost::spirit::ascii::space;
    x_grammar<iter> g;
    try {
        bool r = qi::phrase_parse(it_begin, it_end, g, space, read_data);
        std::cout << "Pass!\n";
    } catch (const qi::expectation_failure<iter>& x) {
        std::cout << "Error!\n";
    }
}

我在使用带有 boost 1.55 的 GCC 4.6.1 时遇到一些恼人的编译错误。

最佳答案

我不禁要注意,如果编译器错误让您烦恼,那么也许您应该编写有效的代码:/


指导性的帽子......

虽然这当然是一个轻率的评论,但它也具有一定的启发性。

我已经两次告诉你,在你的语法中使用构造函数局部变量的整个想法从根本上被打破了:

你想要的是

  • 继承属性
  • qi::本地人
  • maayyyyybe, maaaayyybe语法成员变量;需要注意的是,它们会使您的规则不可重入。

真正进入你头脑的重要事情是

Boost Spirit generates parser from expression templates. Expression templates are 90% static information (type only), and get "compiled" (.compile()) into "invokable" (.parse()) form.

Most importantly, while you can write control flow in your semantic actions, none of this actually executed at the definition site. It's "compiled" into a lazy actor that can later be invoked.

The generated parse will conditionally invoke the lazy actor when the corresponding parse expression matches


建设性的帽子...

看起来您只想使用函数转换属性。

以下是您可以执行的操作:

  1. 将转换作为语义操作的一部分,将结果放入常规属性(为解析器组合维护“功能”语义):

    qi::rule<Iterator, exposed(), Skipper> myrule;
    myrule = int_ [ _val = phx::bind(custom_xform, _1) ];
    

    custom_xform 是任何老派的可调用对象(包括多态可调用对象):

    exposed custom_xform(int i) { return make_new_exposed(i); } 
    // or
    struct custom_xfrom_t {
    
      template <typename> struct result { typedef exposed type; };
    
      template <typename Int>
        exposed operator()(Int i) const {
            return make_new_exposed(i);
        }
    };
    static const custom_xform_t custom_xform;
    
  2. 你可以添加一些语法糖[1]

    qi::rule<Iterator, exposed(), Skipper> myrule;
    myrule = int_ [ _val = custom_xform(_1) ];
    

    这需要将 custom_xform 定义为惰性 actor:

    phx::function<custom_xform_t> custom_xform; // `custom_xform_t` again the (polymorphic) functor
    

    You may note this wouldn't work for a regular function. You could wrap it in a calleable object, or use the BOOST_PHOENIX_ADAPT_FUNCTION macro to do just that for you

  3. 如果您想要更频繁地应用一些更复杂的转换,请考虑使用 Spirit Customization Points:

    如果您为属性选择特定类型(例如 Ast::MultiplicityAst::VelocityRanking,而不是 intdouble


[1] 使用 BOOST_SPIRIT_USE_PHOENIX_V3

关于c++ - 在语义 Action 中 boost spirit 改变变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23788538/

相关文章:

c++ - 使用 boost spirit 语法构建错误(boost 1.43 和 g++ 4.4.1)第二部分

c++ - 如何解决体系结构 x86_64 的 undefined symbol

c++ - 声明一个带有预处理器宏的字符?

c++ - 使用 boost 标记化给出相同的输出

boost - Boost 中的 pthread 是什么?

c++ - 回复 : Help with Boost Grammar

c++ - C++ const reference的形式是什么(不是对const的引用,而是const引用)

c++ - vector in struct 耗时吗?使用指针更好吗?

C++ 在列表<word>中查找一个句子

c++ - 使用 boost Spirit 为变量分配默认值