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
#include 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
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@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spirit-general Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net