在解析步骤中的 boost spirit 操作中共享本地数据

share local data in boost spirit actions inside the parse step

我想在语法规则的所有语义操作中共享一个数据。

这个问题的原因是构建解析器对象时的运行时问题。这需要太长时间,我经常需要它们..

目前我使用这个模式来访问规则操作中的共享变量(就像下面的伪代码一样)

struct my_grammar : public qi::grammar<Iterator, common_node(), eol_skipper >
{ 
  int myLocalVar;

  int localFunction(parameter)
  {
     return myLocalVar;
  }
  myRule1  = (...)[_val = phoenix::bind(&localFunction,this,_1)]
  myRule2  = (...)[_val = phoenix::bind(&localFunction,this,_1)]
}

my_grammar worker;
boost::spirit::qi::phrase_parse(first, last, worker, eolSkipper, ret);

那么,是否有一种通用方法可以为解析调用提供 struct/class,而不是在任何规则中访问此数据及其相应的语义操作(期望使用语法对象的完整实例)?

目标应该是这样的

struct myLocalData 
{ 
  int myLocalVar;

  int localFunction(parameter)
  {
     return myLocalVar;
  }
} ;



struct my_grammar : public qi::grammar<Iterator, common_node(), eol_skipper >
    { // no more local variables here
      myRule1 = (...)[_val = phoenix::bind(&localFunction,_ptr_to_instance_object, _1)]
      myRule2 = (...)[_val = phoenix::bind(&localFunction,_ptr_to_instance_object, _1)]
    }

myLocalData instance; // share this data in all rules
my_grammer worker;
boost::spirit::qi::phrase_parse(first, last, worker, eolSkipper, ret,instance); 

自定义迭代器的解决方案有效.. 所以只需添加此迭代器(下面的代码)和“iter_pos”boost::spirit 帮助程序即可在规则内访问此迭代器。有了这个,您可以调用 iter.getData() 来访问所有规则的共享信息

class custom_iterator {
  public:
    typedef wchar_t value_type;
    typedef std::ptrdiff_t difference_type;
    typedef const value_type* pointer;
    typedef const value_type& reference;
    typedef std::forward_iterator_tag iterator_category;

    custom_iterator() :handler_(nullptr) { }

    custom_iterator(parserDataS* handler, scriptSTDWStringType::const_iterator iter)
      :
      handler_(handler), iter_(iter)
    { }

    custom_iterator& operator++() {
      ++iter_;
      return *this;
    }

    custom_iterator operator++(int) {
      custom_iterator tmp = *this;
      iter_++;
      return tmp;
    }

    value_type operator*() const {
      return *iter_;
    }

    friend bool operator==(custom_iterator a, custom_iterator b) {
      return a.iter_ == b.iter_;
    }

    friend bool operator!=(custom_iterator a, custom_iterator b) {
      return a.iter_ != b.iter_;
    }

    scriptSTDWStringType::const_iterator getIter() const { return iter_; }
    parserDataS* getData() const { return const_cast<parserDataS *>(handler_); }

  private:
    scriptSTDWStringType::const_iterator iter_;
    parserDataS* handler_;
  };