Update of /cvsroot/boost/boost/libs/xpressive/proto/example
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4329
Modified Files:
Jamfile.v2
Added Files:
calc1.cpp calc2.cpp calc3.cpp
Log Message:
some calculator examples
--- NEW FILE: calc1.cpp ---
// Copyright 2007 Eric Niebler. 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 is a simple example of how to build an arithmetic expression
// evaluator with placeholders.
#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/context.hpp>
using namespace boost;
template<typename I> struct arg {};
// Define some placeholders
proto::terminal< arg< mpl::int_<1> > >::type const _1 = {{}};
proto::terminal< arg< mpl::int_<2> > >::type const _2 = {{}};
// Define a calculator context, for evaluating arithmetic expressions
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
double d[2];
// The result of evaluating arithmetic expressions
typedef double result_type;
explicit calculator_context(double d1 = 0., double d2 = 0.)
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<typename I>
double operator()(proto::tag::terminal, arg<I>) const
{
return d[ I() - 1 ];
}
};
template<typename Expr>
double evaluate( Expr const &expr, double d1 = 0., double d2 = 0. )
{
// Create a calculator context with d1 and d2 substituted for _1 and _2
calculator_context const ctx(d1, d2);
// Evaluate the calculator expression with the calculator_context
return proto::eval(expr, ctx);
}
int main()
{
// Displays "5"
std::cout << evaluate( _1 + 2.0, 3.0 ) << std::endl;
// Displays "6"
std::cout << evaluate( _1 * _2, 3.0, 2.0 ) << std::endl;
// Displays "1.5"
std::cout << evaluate( (_1 - _2) / _2, 3.0, 2.0 ) << std::endl;
return 0;
}
--- NEW FILE: calc2.cpp ---
// Copyright 2007 Eric Niebler. 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 example enhances the simple arithmetic expression evaluator
// in calc1.cpp by using proto::extends to make arithemetic
// expressions immediately evaluatable with operator(), a-la a
// function object
#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/context.hpp>
using namespace boost;
// Will be used to define the placeholders _1 and _2
template<typename I> struct arg {};
// For expressions in the calculator domain, operator()
// will be special; it will evaluate the expression.
struct calculator_domain
: proto::domain<>
{};
// Define a calculator context, for evaluating arithmetic expressions
// (This is as before, in calc1.cpp)
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
double d[2];
// The result of evaluating arithmetic expressions
typedef double result_type;
explicit calculator_context(double d1 = 0., double d2 = 0.)
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<typename I>
double operator()(proto::tag::terminal, arg<I>) const
{
return d[ I() - 1 ];
}
};
// Wrap all calculator expressions in this type, which defines
// operator() to evaluate the expression.
template<typename Expr>
struct calculator_expression
: proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
{
typedef
proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
base_type;
explicit calculator_expression(Expr const &expr = Expr())
: base_type(expr)
{}
using base_type::operator=;
// Override operator() to evaluate the expression
double operator()() const
{
calculator_context const ctx;
return proto::eval(*this, ctx);
}
double operator()(double d1) const
{
calculator_context const ctx(d1);
return proto::eval(*this, ctx);
}
double operator()(double d1, double d2) const
{
calculator_context const ctx(d1, d2);
return proto::eval(*this, ctx);
}
};
// Tell proto how to generate expressions in the calculator_domain
namespace boost { namespace proto
{
template<typename Expr>
struct generate<calculator_domain, Expr>
{
typedef calculator_expression<Expr> type;
static type make(Expr const &expr)
{
return type(expr);
}
};
}}
// Define some placeholders (notice they're wrapped in calculator_expression<>)
calculator_expression<proto::terminal< arg< mpl::int_<1> > >::type> const _1;
calculator_expression<proto::terminal< arg< mpl::int_<2> > >::type> const _2;
// Now, our arithmetic expressions are immediately executable function objects:
int main()
{
// Displays "5"
std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
// Displays "6"
std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
// Displays "1.5"
std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
return 0;
}
--- NEW FILE: calc3.cpp ---
// Copyright 2007 Eric Niebler. 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 example enhances the arithmetic expression evaluator
// in calc2.cpp by using a proto transform to calculate the
// number of arguments an expression requires and using a
// compile-time assert to guarantee that the right number of
// arguments are actually specified.
#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/min_max.hpp>
#include <boost/xpressive/proto/proto.hpp>
#include <boost/xpressive/proto/context.hpp>
#include <boost/xpressive/proto/transform/arg.hpp>
#include <boost/xpressive/proto/transform/fold.hpp>
using namespace boost;
// Will be used to define the placeholders _1 and _2
template<typename I> struct arg { typedef I arity; };
// Some custom transforms for calculating the max arity of a calculator
expression
template<typename Grammar>
struct max_arity
: Grammar
{
template<typename Expr, typename State, typename Visitor>
struct apply
{
// Calculate the arity of the current expression.
typedef typename Grammar::template apply<Expr, State, Visitor>::type
arity;
// The old maximum is passed along in the State parameter by
// proto::trans::fold<> (see below). The new maximum is the
// larger of the old maximum and the arity we just calculated.
typedef typename mpl::max<arity, State>::type type;
};
//// If this transform had a runtime counterpart, it would look like this:
//template<typename Expr, typename State, typename Visitor>
//static typename apply<Expr, State, Visitor>::type
//call(Expr const &expr, State const &state, Visitor &visitor)
//{
// ... do stuff ...
//}
};
// Fetch the arity of a placeholder terminal
template<typename Grammar>
struct placeholder_arity
: Grammar
{
template<typename Expr, typename, typename>
struct apply
{
typedef typename proto::result_of::arg<Expr>::type::arity type;
};
// As with max_arity<> above, placeholder_arity<> has no need
// for a call() member function.
};
using proto::_;
// This grammar basically says that a calculator expression is one of:
// - A placeholder terminal
// - Some other terminal
// - Some non-terminal whose children are calculator expressions
// In addition, it has transforms that say how to calculate the the
// expression arity for each of the three cases.
struct CalculatorGrammar
: proto::or_<
// placeholders have a non-zero arity ...
placeholder_arity< proto::terminal< arg<_> > >
// Any other terminals have arity 0 ...
, proto::trans::always< proto::terminal<_>, mpl::int_<0> >
// For any non-terminals, find the arity of the children and
// take the maximum. This is recursive.
, proto::trans::fold<
// This matches any non-terminal for which the children
// are themselves calculator expressions.
proto::nary_expr<_, proto::vararg< max_arity< CalculatorGrammar > >
>
>
>
{};
// Simple wrapper for calculating a calculator expression's arity.
// It specifies mpl::int_<0> as the initial state. The visitor, which
// is not used, is mpl::void_.
template<typename Expr>
struct calculator_arity
: CalculatorGrammar::apply<Expr, mpl::int_<0>, mpl::void_>
{};
// For expressions in the calculator domain, operator()
// will be special; it will evaluate the expression.
struct calculator_domain
: proto::domain<>
{};
// Define a calculator context, for evaluating arithmetic expressions
// (This is as before, in calc1.cpp and calc2.cpp)
struct calculator_context
: proto::callable_context< calculator_context const >
{
// The values bound to the placeholders
double d[2];
// The result of evaluating arithmetic expressions
typedef double result_type;
explicit calculator_context(double d1 = 0., double d2 = 0.)
{
d[0] = d1;
d[1] = d2;
}
// Handle the evaluation of the placeholder terminals
template<typename I>
double operator()(proto::tag::terminal, arg<I>) const
{
return d[ I() - 1 ];
}
};
// Wrap all calculator expressions in this type, which defines
// operator() to evaluate the expression.
template<typename Expr>
struct calculator_expression
: proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
{
typedef
proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
base_type;
explicit calculator_expression(Expr const &expr = Expr())
: base_type(expr)
{}
using base_type::operator=;
// Override operator() to evaluate the expression
double operator()() const
{
// Assert that the expression has arity 0
BOOST_MPL_ASSERT_RELATION(0, ==, calculator_arity<Expr>::type::value);
calculator_context const ctx;
return proto::eval(*this, ctx);
}
double operator()(double d1) const
{
// Assert that the expression has arity 1
BOOST_MPL_ASSERT_RELATION(1, ==, calculator_arity<Expr>::type::value);
calculator_context const ctx(d1);
return proto::eval(*this, ctx);
}
double operator()(double d1, double d2) const
{
// Assert that the expression has arity 2
BOOST_MPL_ASSERT_RELATION(2, ==, calculator_arity<Expr>::type::value);
calculator_context const ctx(d1, d2);
return proto::eval(*this, ctx);
}
};
// Tell proto how to generate expressions in the calculator_domain
namespace boost { namespace proto
{
template<typename Expr>
struct generate<calculator_domain, Expr>
{
typedef calculator_expression<Expr> type;
static type make(Expr const &expr)
{
return type(expr);
}
};
}}
// Define some placeholders (notice they're wrapped in calculator_expression<>)
calculator_expression<proto::terminal< arg< mpl::int_<1> > >::type> const _1;
calculator_expression<proto::terminal< arg< mpl::int_<2> > >::type> const _2;
// Now, our arithmetic expressions are immediately executable function objects:
int main()
{
// Displays "5"
std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
// Displays "6"
std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
// Displays "1.5"
std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
// This won't compile because the arity of the
// expression doesn't match the number of arguments
// ( (_1 - _2) / _2 )( 3.0 );
return 0;
}
Index: Jamfile.v2
===================================================================
RCS file: /cvsroot/boost/boost/libs/xpressive/proto/example/Jamfile.v2,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Jamfile.v2 4 Apr 2007 07:02:00 -0000 1.1
+++ Jamfile.v2 17 Apr 2007 06:29:32 -0000 1.2
@@ -6,3 +6,19 @@
:
hello.cpp
;
+
+
+exe calc1
+ :
+ calc1.cpp
+ ;
+
+exe calc2
+ :
+ calc2.cpp
+ ;
+
+exe calc3
+ :
+ calc3.cpp
+ ;
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs