Boost.Spirit.Qi: Take the rule attribute and set it as the field of the struct attribute in the application?

Like many other questions, I am trying to parse a simple grammar into a tree of structures using Boost.Spirit.Qi.

I will try to redo what I am trying to do in the simplest case. I have:

struct Integer { int value; }; BOOST_FUSION_ADAPT_STRUCT(Integer, (int, value)) 

Later, inside the grammar structure, I have the following member variable:

 qi::rule<Iterator, Integer> integer; 

which I define with

 integer = qi::int_; 

However, when I try to parse an integer using

 qi::phrase_parse(iter, end, g, space, myInteger); 

myInteger.value is not always initialized after a successful analysis. Similarly, I tried the following definitions (obviously those that do not compile are wrong):

 integer = qi::int_[qi::_val = qi::_1]; //compiles, uninitialized value integer = qi::int_[qi::_r1 = qi::_1]; //doesn't compile integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1]; //doesn't integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; //doesn't 

It is clear that I do not understand something about the Spirit, the Phoenix, or something else. I understand that qi::_1 is the first attribute of qi::int_ , here, and should represent a syntactic integer when the part in square brackets is executed as a function object. Then I assume that the function object will take the attached attribute integer qi::_val and try to assign it a syntactic integer. My assumption was that due to my call to BOOST_FUSION_ADAPT_STRUCT both will be compatible, and this certainly does occur in terms of static analysis, but the data is not saved.

Is there a reference (&) notation that I am missing somewhere?

+6
c ++ boost-spirit boost-spirit-qi boost-phoenix
source share
1 answer

If Integer should be the attribute opened by this rule, you need to declare it as:

 qi::rule<Iterator, Integer()> integer; 

(note the brackets). Spirit needs to use the function declaration syntax to describe the interface. It is used not only in the Spirit, but also in several other libraries (see, for example, boost :: function).

The main reason for this is that it is a nice concise way of specifying a functional interface. If you think about what a rule is, you quickly realize that it looks like a function: it can return a value (the analyzed result, i.e., the Synthesized attribute). In addition, it can take one or more arguments (inherited attributes).

A second, but small reason, is that the Spirit needs to be able to distinguish between the various parameters of the rule template. Template parameters can be specified in any order (except for an iterator), so it needs some ways to figure out what. The syntax for declaring a function is quite different from the skipper or encoding (the other two possible template parameters) to allow it to be recognized at compile time.

Let's look at your different attempts:

This can be done if you change the definition of the rule as described above.

 integer = qi::int_[qi::_val = qi::_1]; 

_val refers to your Integer , and _1 refers to int . Therefore, you need to define an assignment operator from int in order to make this work:

 struct Integer { int value; Integer& operator=(int) {...} }; 

In this case, you do not need to adapt your type as a Fusion sequence.

But you can write it even easier:

 integer = qi::int_ >> qi::eps; 

which is equivalent to 100% (eps is a trick used to convert the right-hand side into a parser sequence, which allows you to use the built-in distribution of attributes by matching the elements of your adapted Fusion sequence with the attributes of the sequence elements).

It:

 integer = qi::int_[qi::_r1 = qi::_1]; 

will not work because _r1 refers to the first inherited attribute of the rule. However, your rule does not have nested attributes.

This will work:

 integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1]; 

but does not require you to adapt your type as a Fusion sequence.

And so it will be:

 integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; 
+13
source share

All Articles