1

i want to share a data within all semantic actions of the grammer rules.

the reason for this question is the runtime issue while construction the parser objects. This takes too long and i need them very frequently ..

Currently i use this schema to get access on shared variables inside the rules action (just as pseudo code below)

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);

so is there a common way to provide a struct/class to the parse call and than access this data within any rule and their corresponding sematic action expect using the full instance of the grammer object?

goal should be something like this

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); 
Markus
  • 373
  • 1
  • 11
  • That's exactly how 'parser context' in X3 behaves, but it smells strange. How deep you *really* need that data to pass? There is rule parametrization ('inherited attributes'), have you tried it? – Nikita Kniazev Jul 21 '20 at 19:37
  • [This is an example](https://stackoverflow.com/questions/16918831/how-to-benchmark-boost-spirit-parser/16931098#16931098) that shows both inherited attributes and `qi::locals<>` used for similar purposes. Perhaps the samples help. Oh, and here an [example that uses local state to sense matrix dimensions during parse (3 variations)](https://stackoverflow.com/a/12772075/85371). That's more accessible because it's self-contained. – sehe Jul 21 '20 at 21:24
  • I saw this Qi::locals stuff but it seems that this works only inside the same rule. I have to share the information over multiple rules. I add in the sample above one more rule for each sample to show this. – Markus Jul 22 '20 at 05:07
  • After reading multiple articles it may come up with the idea to write and custom iterator. Inside this iterator I can store my custom data and access this inside all rules... – Markus Jul 22 '20 at 18:23

1 Answers1

0

the solution with custom iterator works .. so just adding this iterator (code below) and the "iter_pos" boost::spirit helper to access this iterator inside the rules. With this you can call iter.getData() to access a shared information over all rules

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_;
  };
Markus
  • 373
  • 1
  • 11