(Probably) A bug in the Spirit's magic!
Simone Pellegrini <simone.pellegrini <at> cnaf.infn.it>
2008-05-08 10:29:34 GMT
Hello everyone,
First of all I'd like to congratulate with the mind(s) behind the Spirit
project because it is simple awesome.
However, I guess I have found a BUG. Probably the error is due to my
code, but after several hours of investigation, I am almost sure it is
not.
So, let's say tat I want to parse sequences of arguments (integer
numbers for simplicity) and store them inside a vector. These arguments
can be nested (max one level nesting) and in order to avoid the use of
the composite pattern I preferred to use a simple vector and keep the
position of each argument inside the argument list.
For example the following argument list:
"{10, {20, 30}, 50}"
should return the vector of elements:
[10 (pos:0), 20 (pos:1), 30 (pos:1), 50 (pos:2)]
ok? Simple, doesn't it? :)
So, I have defined the following struct in order to keep the parsed
values:
struct integer{
int val_;
int pos_;
integer(){}
integer(int const& v, int const& pos): val_(v), pos_(pos){}
};
and I have defined the following grammar:
struct arg_grammar : public boost::spirit::grammar<arg_grammar>{
template <typename ScannerT>
struct definition{
integer i;
int pos;
definition(arg_grammar const& self) {
params =
ch_p('{') >>
( ( arg >> *(ch_p(',') >> arg) >> ch_p('}') )
|
ch_p('}') ) >> end_p;
arg =
value_list[ increment_a(pos) ];
value_list =
( ch_p('{') >> value >> *(',' >> value) >> ch_p('}') )
|
value;
value =
int_p[ var(i) = construct_<integer>(arg1, pos) ]
[ push_back_a(self.args, i) ];
}
rule<ScannerT> params, arg, value, value_list;
rule<ScannerT> const& start() const { return params; }
};
arg_grammar(vector<integer>& args_): args(args_){ }
private:
vector<integer>& args;
};
When I try to run the code (considering the previous argument list) I
received something like:
[10 (pos:0), 20 (pos:0), 30 (pos:0), 50 (pos:0)]
That is wrong as far as the position (pos) is not correct! :(
So, after several hours of investigation I can affirm that the problem
here is within the construct_ function. In fact, the pos value is
successfully incremented by the increment_at actor, and printing down
its value you can see that pos starts from 0 and reaches the value of
2.
It seems that the problem happens when the integer object is created,
the pos argument is initialized always with the 0 value even if it has
got a different value (actually 0,1,2). How can be possible???
I have tried to solve the problem changing the grammar as follows:
int_p[ var(i) = construct_<integer>(arg1, pos) ]
[ my_assign(i.pos_, pos) ]
[ push_back_a(self.args, i) ];
where, my_assign is defined as:
struct my_assign{
void operator()(const int&) const{
dest = source;
}
my_assign(int& dest_, int& source_): dest(dest_), source(source_){}
private:
int& dest;
int& source;
};
Using my custom actor everything works fine and the result is:
[10 (pos:0), 20 (pos:1), 30 (pos:1), 50 (pos:2)]
as expected.
Beside that solution, I have also tried to define the pos value as a
member value using closures, then outside the struct definition... as a
class member, but nothing worked.
So, what do you think guys? Where is the problem? Is it something
related to the definition of my grammar or is it a REAL bug?
greetings S. Pellegrini
P.S.: In attachment you can find the source code of the example.
--
Simone Pellegrini
INFN (National Institute of Nuclear Physics)
Viale Berti Pichat 6/2
40127 Bologna - Italy
email: simone.pellegrini <at> cnaf.infn.it
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Spirit-general mailing list
Spirit-general <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spirit-general