diff options
Diffstat (limited to 'tools/quickbook/src/parsers.hpp')
-rw-r--r-- | tools/quickbook/src/parsers.hpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/tools/quickbook/src/parsers.hpp b/tools/quickbook/src/parsers.hpp new file mode 100644 index 0000000000..19d385de5e --- /dev/null +++ b/tools/quickbook/src/parsers.hpp @@ -0,0 +1,257 @@ +/*============================================================================= + Copyright (c) 2010-2011 Daniel James + Copyright (c) 2003 Martin Wille + http://spirit.sourceforge.net/ + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + =============================================================================*/ + +// Some custom parsers for use in quickbook. + +#ifndef BOOST_QUICKBOOK_PARSERS_HPP +#define BOOST_QUICKBOOK_PARSERS_HPP + +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_nil.hpp> +#include <boost/spirit/include/phoenix1_primitives.hpp> +#include <boost/spirit/include/phoenix1_tuples.hpp> +#include <boost/spirit/include/phoenix1_binders.hpp> + +namespace quickbook { + namespace cl = boost::spirit::classic; + + /////////////////////////////////////////////////////////////////////////// + // + // scoped_parser<Impl> + // + // Impl is a struct with the methods: + // + // void start(); + // void success(parse_iterator, parse_iterator); + // void failure(); + // void cleanup(); + // + /////////////////////////////////////////////////////////////////////////// + + template <typename Impl, typename Arguments, typename ParserT> + struct scoped_parser_impl + : public cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > > + { + typedef scoped_parser_impl<Impl, Arguments, ParserT> self_t; + typedef cl::unary< ParserT, cl::parser< scoped_parser_impl<Impl, Arguments, ParserT> > > base_t; + + template <typename ScannerT> + struct result { typedef cl::match<> type; }; + + scoped_parser_impl( + Impl const& impl, + Arguments const& arguments, + ParserT const &p) + : base_t(p) + , impl_(impl) + , arguments_(arguments) + {} + + struct scoped + { + explicit scoped(Impl const& impl) + : impl_(impl) + , in_progress_(false) + {} + + typedef phoenix::tuple_index<0> t0; + typedef phoenix::tuple_index<1> t1; + + bool start(phoenix::tuple<> const&) + { + in_progress_ = impl_.start(); + return in_progress_; + } + + template <typename Arg1> + bool start(phoenix::tuple<Arg1> const& x) + { + in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()])(); + return in_progress_; + } + + template <typename Arg1, typename Arg2> + bool start(phoenix::tuple<Arg1, Arg2> const& x) + { + in_progress_ = phoenix::bind(&Impl::start)(phoenix::var(impl_), x[t0()], x[t1()])(); + return in_progress_; + } + + void success(parse_iterator f, parse_iterator l) + { + in_progress_ = false; + impl_.success(f, l); + } + + void failure() + { + in_progress_ = false; + impl_.failure(); + } + + ~scoped() + { + if (in_progress_) impl_.failure(); + impl_.cleanup(); + } + + Impl impl_; + bool in_progress_; + }; + + template <typename ScannerT> + typename result<ScannerT>::type parse(ScannerT const &scan) const + { + typedef typename ScannerT::iterator_t iterator_t; + iterator_t save = scan.first; + + scoped scope(impl_); + if (!scope.start(arguments_)) + return scan.no_match(); + + typename cl::parser_result<ParserT, ScannerT>::type result + = this->subject().parse(scan); + + bool success = scope.impl_.result(result, scan); + + if (success) { + scope.success(save, scan.first); + + if (result) { + return scan.create_match(result.length(), cl::nil_t(), save, scan.first); + } + else { + return scan.create_match(scan.first.base() - save.base(), cl::nil_t(), save, scan.first); + } + } + else { + scope.failure(); + return scan.no_match(); + } + } + + Impl impl_; + Arguments arguments_; + }; + + template <typename Impl, typename Arguments> + struct scoped_parser_gen + { + explicit scoped_parser_gen(Impl impl, Arguments const& arguments) + : impl_(impl), arguments_(arguments) {} + + template<typename ParserT> + scoped_parser_impl + < + Impl, + Arguments, + typename cl::as_parser<ParserT>::type + > + operator[](ParserT const &p) const + { + typedef cl::as_parser<ParserT> as_parser_t; + typedef typename as_parser_t::type parser_t; + + return scoped_parser_impl<Impl, Arguments, parser_t> + (impl_, arguments_, p); + } + + Impl impl_; + Arguments arguments_; + }; + + template <typename Impl> + struct scoped_parser + { + scoped_parser(Impl const& impl) + : impl_(impl) {} + + scoped_parser_gen<Impl, phoenix::tuple<> > + operator()() const + { + typedef phoenix::tuple<> tuple; + return scoped_parser_gen<Impl, tuple>(impl_, tuple()); + } + + template <typename Arg1> + scoped_parser_gen<Impl, phoenix::tuple<Arg1> > + operator()(Arg1 x1) const + { + typedef phoenix::tuple<Arg1> tuple; + return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1)); + } + + template <typename Arg1, typename Arg2> + scoped_parser_gen<Impl, phoenix::tuple<Arg1, Arg2> > + operator()(Arg1 x1, Arg2 x2) const + { + typedef phoenix::tuple<Arg1, Arg2> tuple; + return scoped_parser_gen<Impl, tuple>(impl_, tuple(x1, x2)); + } + + Impl impl_; + }; + + /////////////////////////////////////////////////////////////////////////// + // + // Lookback parser + // + // usage: lookback[body] + // + // Requires that iterator has typedef 'lookback_range' and function + // 'lookback' returning a 'lookback_range'. + // + /////////////////////////////////////////////////////////////////////////// + + template <typename ParserT> + struct lookback_parser + : public cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > > + { + typedef lookback_parser<ParserT> self_t; + typedef cl::unary< ParserT, cl::parser< lookback_parser<ParserT> > > base_t; + + template <typename ScannerT> + struct result + { + typedef typename cl::parser_result<ParserT, ScannerT>::type type; + }; + + lookback_parser(ParserT const& p) + : base_t(p) + {} + + template <typename ScannerT> + typename result<ScannerT>::type parse(ScannerT const &scan) const + { + typedef typename ScannerT::iterator_t::lookback_range::iterator iterator_t; + typedef cl::scanner<iterator_t, typename ScannerT::policies_t> scanner_t; + + iterator_t begin = scan.first.lookback().begin(); + scanner_t lookback_scan(begin, scan.first.lookback().end(), scan); + + if (this->subject().parse(lookback_scan)) + return scan.empty_match(); + else + return scan.no_match(); + } + }; + + struct lookback_gen + { + template <typename ParserT> + lookback_parser<ParserT> operator[](ParserT const& p) const + { + return lookback_parser<ParserT>(p); + } + }; + + lookback_gen const lookback = lookback_gen(); +} + +#endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP |