blob: b346ffaaf1d040cbe22d677e71d0ff48bd203082 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2010 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)
=============================================================================*/
// Used to parse an inner block, saves the streams and restores them if the
// parse fails. On success the action is passed the resulting block.
//
// Might be a good idea to do something more generic in the future.
//
// This is based on `boost::spirit::classic::scoped_lock` by Martin Wille
#ifndef BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
#define BOOST_QUICKBOOK_SCOPED_BLOCK_HPP
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core/composite/composite.hpp>
#include "actions_class.hpp"
namespace quickbook {
namespace cl = boost::spirit::classic;
struct scoped_block_push
{
typedef std::string attribute;
scoped_block_push(quickbook::actions& actions)
: actions(actions)
{
actions.out.push();
actions.phrase.push();
}
~scoped_block_push()
{
actions.phrase.pop();
actions.out.pop();
}
std::string const& finish()
{
actions.inside_paragraph();
return actions.out.str();
}
quickbook::actions& actions;
};
template <typename ParserT>
struct scoped_block_parser
: public cl::unary< ParserT, cl::parser< scoped_block_parser<ParserT> > >
{
typedef scoped_block_parser<ParserT> self_t;
typedef cl::unary< ParserT, cl::parser< scoped_block_parser<ParserT> > > base_t;
template <typename ScannerT>
struct result
{
typedef cl::match<std::string> type;
};
scoped_block_parser(quickbook::actions& a, ParserT const &p)
: base_t(p)
, actions(a)
{}
template <typename ScannerT>
cl::match<std::string> parse(ScannerT const &scan) const
{
typedef typename ScannerT::iterator_t iterator_t;
iterator_t save = scan.first;
scoped_block_push push(actions);
typename cl::parser_result<ParserT, ScannerT>::type result
= this->subject().parse(scan);
if (result)
return scan.create_match(result.length(), push.finish(), save, scan.first);
else
return scan.no_match();
}
quickbook::actions& actions;
};
///////////////////////////////////////////////////////////////////////////
//
// scoped_block_parser_gen
//
// generator for scoped_block_parser objects
// operator[] returns scoped_block_parser according to its argument
//
///////////////////////////////////////////////////////////////////////////
struct scoped_block_parser_gen
{
explicit scoped_block_parser_gen(quickbook::actions& actions)
: actions(actions) {}
template<typename ParserT>
scoped_block_parser
<
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_block_parser<parser_t>
(actions, as_parser_t::convert(p));
}
quickbook::actions& actions;
};
///////////////////////////////////////////////////////////////////////////
//
// scoped_block_d parser directive
//
// constructs a scoped_block_parser generator from its argument
//
///////////////////////////////////////////////////////////////////////////
inline scoped_block_parser_gen scoped_block(quickbook::actions& actions) {
return scoped_block_parser_gen(actions);
}
}
#endif // BOOST_QUICKBOOK_SCOPED_BLOCK_HPP