2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 04:42:11 +00:00
Files
spirit/example/karma/functor_facilities.cpp
Joel de Guzman 2431a80d8a spirit2 ! :)
[SVN r44360]
2008-04-13 03:02:30 +00:00

203 lines
6.8 KiB
C++

// Copyright (c) 2001-2008 Hartmut Kaiser
//
// 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)
// This examples demonstrate how to write functor based generators for special
// purposes.
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/karma_stream.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <cstdlib>
using namespace boost::spirit;
///////////////////////////////////////////////////////////////////////////////
// The functor generator 'counter' can be used for output annotation with some
// item counting information.
///////////////////////////////////////////////////////////////////////////////
struct counter_impl : boost::spirit::karma::functor_base
{
template <typename OutputIterator, typename Context, typename Parameter>
bool operator()(Parameter const&, Context& ctx, OutputIterator& sink) const
{
namespace karma = boost::spirit::karma;
return karma::generate(sink, int_ << ": ", counter++);
}
counter_impl(int& counter_)
: counter(counter_) {}
int& counter;
};
inline boost::spirit::result_of::as_generator<counter_impl>::type
counter(int& counter_)
{
using namespace boost::spirit::karma;
return as_generator(counter_impl(counter_));
}
///////////////////////////////////////////////////////////////////////////////
// The functor generator 'confix' allows a simple syntax for generating
// output wrapped inside a pair of a prefix and a suffix.
///////////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct confix_impl : public boost::spirit::karma::functor_base
{
template <typename Context>
struct apply
{
typedef boost::spirit::hold_any type;
};
template <typename OutputIterator, typename Context, typename Parameter>
bool operator()(Parameter const& v, Context& ctx, OutputIterator& sink) const
{
namespace karma = boost::spirit::karma;
return karma::generate(sink, open << xpr << close, v);
}
confix_impl(char const* open_, char const* close_, Expr const& xpr_)
: open(open_), close(close_), xpr(xpr_) {}
std::string open;
std::string close;
Expr xpr;
};
template <typename Expr>
inline typename boost::spirit::result_of::as_generator<confix_impl<Expr> >::type
confix(Expr const& xpr_, char const* open_ = "", char const* close_ = "")
{
using namespace boost::spirit::karma;
return as_generator(confix_impl<Expr>(open_, close_, xpr_));
}
///////////////////////////////////////////////////////////////////////////////
// The functor generator 'list' allows a simple syntax for generating
// list formatted output.
//
// This example uses phoenix::bind to allow to omit the second argument from
// the operator() and to allow to switch the remaining two arguments.
///////////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct list_impl : boost::spirit::karma::functor_base
{
// this function will be called to generate the output
template <typename OutputIterator, typename Parameter>
bool operator()(OutputIterator& sink, Parameter const& v) const
{
namespace karma = boost::spirit::karma;
return karma::generate(sink, xpr % delim, v);
}
list_impl(Expr const& xpr_, char const* delim_)
: xpr(xpr_), delim(delim_) {}
Expr xpr;
std::string delim;
};
// Supply the expected parameter type explicitly
struct list_impl_mf
{
// the expected parameter type of a functor has to be defined using a
// embedded apply metafunction
template <typename Context>
struct apply
{
typedef boost::spirit::hold_any type;
};
};
template <typename Expr>
inline list_impl<Expr>
list(Expr const& xpr, char const* delim)
{
return list_impl<Expr>(xpr, delim);
}
///////////////////////////////////////////////////////////////////////////////
int main()
{
namespace karma = boost::spirit::karma;
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
///////////////////////////////////////////////////////////////////////////
// Output the given containers in list format
// We use a special functor generator here to annotate the output with
// a integer counting the entries.
///////////////////////////////////////////////////////////////////////////
std::vector<int> v (8);
std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
int counter1 = 1;
std::cout <<
karma::format(
(counter(counter1) << int_) % ", ", // format description
v // data
) << std::endl;
// Here we initialize the counter to 100
int counter2 = 100;
std::cout <<
karma::format(
'[' << (
(counter(counter2) << int_) % ", "
) << ']', // format description
v // data
) << std::endl;
///////////////////////////////////////////////////////////////////////////
// list
// The output format description used below adds special item formatting
///////////////////////////////////////////////////////////////////////////
std::list<std::string> names;
names.push_back("Spirit");
names.push_back("Qi");
names.push_back("Karma");
// specifying a prefix item suffix scheme directly
std::cout <<
karma::format(
('{' << stream << '}') % ", ", // format description
names // data
) << std::endl;
// The confix generator nicely wraps the given expression with prefix and
// suffix strings
std::cout <<
karma::format(
confix(stream % ", ", "[", "]"), // format description
names // data
) << std::endl;
///////////////////////////////////////////////////////////////////////////
// Output the given container as a list
// We use a separate metafunction list_impl_mf to specify the expected
// parameter type of this functor generator.
// We use phoenix::bind to allow to omit the 2nd argument from the functor
// function operator and to change the sequence of the remaining two
// arguments.
///////////////////////////////////////////////////////////////////////////
std::string str("Hello world!");
std::cout <<
karma::format(
karma::as_generator_mf<list_impl_mf>(bind(list(stream, ", "), _3, _1)),
str
) << std::endl;
return 0;
}