Boost logo

Boost Users :

From: Max Motovilov (max_at_[hidden])
Date: 2005-12-05 23:28:49


Hartmut,

> That's a very good point. I've added it to the exception classes.

But that's not in the CVS yet, right? 'Cause I didn't see it there :)

> these. Just use the following code snippet instead of the simple "while
> (first != last) { ++first; }" loop. The following snippet is taken from
the
> wave driver, where I've implemented the new techniques:

Not sure what's the point of storing the current_position in this snippet as
I don't see you using it anywhere at the time of error recovery. In any
case, I didn't see any suggestion of being able to position the scanner
directly using position_type (and I doublt that's feasible considering that
every logical position in the file has semantic state of the preprocessor
associated with it). I was thinking of achieving recovery with a copy of the
_iterator_ but it doesn't look like this does what I expected it to.

Here's my sample snippet:

try {
 wave_context::iterator_type p = ctx.begin(), last_known_good = p;
 bool done = false;

 while( !done ) {
  try {
   done = p == ctx.end();
   std::cout << p->get_value();
   ++p;
   last_known_good = p;
  } catch( boost::wave::preprocess_exception& err ) {
   if( err.get_severity() >= boost::wave::util::severity_error ) throw;
   complain( err );
   p = last_known_good;
  }
 }
} catch( boost::wave::cpp_exception& err ) {
 complain( err );
 return false;
}

I have half-expected it to go into an infinite loop (as returning back to
the failure point should cause the same error to repeat itself) then I
realized that tokens that would NOT normally be returned to the user (bosy
of the re-defined macro, in my case) may not be part of the state associated
with the iterator. Yet something fishy happens with the state I can't quite
put my finger on. Here's my example input:

=============
#define Foo(x) bar##x
Foo(foo1)
#define Foo(x) x##bar
#define Bar(x) x##foo
Foo(foo2)
Bar(bar1)

=============

This is the result:

=============
#line 2 "..\\test.cpp"
barfoo1

#define Bar(x) x##foo
barfoo2
Bar(bar1)
=============

Note that the definition of Bar went through verbatim, which means that
recovery was not achieved properly. My guess was that parsing of the body of
the second definition of Foo somehow consumed the newline and didn't return
it back to the stream, thus invalidating the production for the next #define
(which, I imagine, was <EOL> <#> <Keyword>). I tried the modified version:

=============
#define Foo(x) bar##x
Foo(foo1)
#define Foo(x) x##bar

#define Bar(x) x##foo
Foo(foo2)
Bar(bar1)
=============

and, sure enough, I got:

=============
#line 2 "..\\test.cpp"
barfoo1

#line 6 "..\\test.cpp"
barfoo2
bar1foo
=============

So the newline was indeed consumed irrecoverably [no pun intended!] and
recovery failed.

But, that's NOT the most interesting part. The most interesting part is that
when I commented out all use of last_known_good from the above snippet, the
code behaved EXACTLY THE SAME in both cases. Which makes me doubt very much
that state has indeed been preserved within the copy of the iterator.
Perhaps Wave iterator has shallow copy? I'd deduce that from the code but
it's been a long day... maybe tomorrow.

Regards,
...Max...


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net