Boost logo

Boost Users :

From: Joel de Guzman (joel_at_[hidden])
Date: 2004-06-27 19:55:50


Michael Orlov wrote:
> Hi,
>
> I am new to Spirit, and I am writing a reader for s-expressions, and so far
> has encountered the following problems, which seem to me to be contrarry to
> the documentation (Spirit 1.8.0 in Boost 1.31.0).
>
> Consider the following (small) C++ program:
>
> ---------------------------------------------
>
> #include <iostream>
> #include <iterator>
> #include <string>
> #include <boost/spirit/core.hpp>
> #include <boost/spirit/iterator/multi_pass.hpp>
>
> using namespace std;
> using namespace boost::spirit;
>
> struct Sexp
> : public boost::spirit::grammar<Sexp>
> {
> template <typename ScannerT>
> struct definition
> {
> typedef rule<ScannerT> rule;
>
> definition(const Sexp &self)
> {
> first =
> ( sexp = '(' >> *sexp >> ')' );
> }
>
> subrule<0> sexp;
>
> rule first;
> const rule& start() const { return first; }
> };
> };
>
> int main()
> {
> typedef std::istream_iterator<char> iterator_t;
> typedef boost::spirit::multi_pass<
> iterator_t,
> boost::spirit::multi_pass_policies::input_iterator,
> boost::spirit::multi_pass_policies::first_owner
> > iterator_wrapper_t;
>
> Sexp sexper;
>
> iterator_t under_first(cin);
> iterator_t under_last;
>
> iterator_wrapper_t first(under_first);
> iterator_wrapper_t last(under_last);
>
> while (true) {
> parse_info<iterator_wrapper_t> info =
> parse(first, last, sexper);
>
> first.clear_queue();
>
> if (info.hit)
> std::cout << "Hit: " << info.length << std::endl;
> else
> break;
> };
> }
>
> ---------------------------------------------
>
> The purpose is to read s-expression from input, delivering them to the user
> the moment they are ready. Since whitespace skipper tries to consume as much
> space as it can, it is not suitable here, so I don't want to use it.
>
> Here comes the first problem: even when I don't pass space_p to parse(), the
> skipper is still present:
>
> ---
> ( )
> ^D
> Hit: 2
> ---
>
> ---
> (())(
> Hit: 4
> )
> ^D
> Hit: 2
> ---

cin does the skips, not Spirit. Try adding:

cin.unsetf(ios::skipws); // Turn of white space skipping on the stream

Of course you already know that, don't you ;-)

> Another problem is when I try to use istreambuf_iterator instead of
> istream_iterator (this is done in Spirit examples, too). When substituting
> istreambuf_iterator in the first typedef in main(), the program no longer
> compiles - neither with Intel Compiler 8.0.055, nor with GCC 3.3.2.
>
> Intel complains about
> /usr/local/include/boost/spirit/iterator/multi_pass.hpp(537): error: initial
> value of reference to non-const must be an lvalue
> return **input;
> and GCC's messages are too long to parse. :)

I'm curious as to why you don't just do it this way?

     Sexp sexper;
     string str;
     while (getline(cin, str))
     {
         if (str[0] == 'q' || str[0] == 'Q')
             break;

         parse_info<> info = parse(str.c_str(), sexper);

         if (info.hit)
           std::cout << "Hit: " << info.length << std::endl;
         else
           std::cout << "Fail. " << std::endl;
     }

Anyway, if it's working in the Spirit examples as you say, then
why don't you just do it the way it's done in the examples? It
would probably save us more time looking for the problem.

BTW, please post replies to Spirit's mailing list:

Spirit-general mailing list
Spirit-general_at_[hidden]
https://lists.sourceforge.net/lists/listinfo/spirit-general

Regards,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

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