[spirit] "parseable" foo_thing with Boost.Spirit pattern

Here follows a simple pattern to use Boost.Spirit to create a "parseable" object, with a bonus formatted input operator, allowing you quick access to formatter input for your type. (Yeah, this stuff needs tweaking for better error handling, etc.) class foo_thing { public: /* Other methods and stuff. */ template <typename ForwardIterator> boost::spirit::parse_info<IteratorT> parse (ForwardIterator begin, ForwardIterator end); private: class grammar; /* Data members, etc. */ }; template <typename CharT, typename TraitsT> std::basic_istream<CharT, TraitsT>& operator>> (std::basic_istream<CharT, TraitsT>& i, foo_thing& thing) { using namespace std; using namespace boost::spirit; typedef multi_pass<istreambuf_iterator<CharT> > iterator_t; iterator_t begin(i); iterator_t end = make_multi_pass(istreambuf_iterator<CharT>()); /* What if thing.parse() throws? */ parse_info<iterator_t> info = thing.parse(begin, end); if (!info.hit) i.setstate(ios_base::failbit); return i; } class foo_thing::grammar : public boost::spirit::grammar<foo_thing::grammar> { public: grammar (foo_thing& thing) : _M_thing(thing) {} template <typename ScannerT> class definition; private: foo_thing mutable& _M_thing; }; template <typename ScannerT> class foo_thing::grammar::definition { public: /* Define this one; your parser ultimately writes to self._M_thing. */ definition (foo_thing::grammar const& self); boost::spirit::rule<ScannerT> const& start () const; private: /* Populate with rules. */ }; template <typename IteratorT> boost::spirit::parse_info<IteratorT> foo_thing::parse (IteratorT begin, IteratorT end) { namespace s = boost::spirit; grammar g(*this); s::parse_info<IteratorT> r = s::parse(begin, end, g); return r; } -- Pedro Lamarão Desenvolvimento Intersix Technologies S.A. SP: (55 11 3803-9300) RJ: (55 21 3852-3240) www.intersix.com.br Your Security is our Business
participants (1)
-
Pedro Lamarão