Terms with Variables (C++)
In this earlier post I showed a nifty OCaml type for modeling terms with variables for problems involving substitutions. I got interested in what it would take to implement the type in C++(03) (doing 'sum' types in C++ elegantly is a perennial problem). It ain't nowhere near as succinct but we got there nonetheless.
#include <list>
#include <boost/variant.hpp>
/*
type ('a, 'b) term =
| Term of 'a * ('a, 'b) term list
| Var of 'b
*/
template <class A, class B> struct term;
template <class B> struct var;
template <class A, class B>
struct make_tree
{
typedef boost::variant <
boost::recursive_wrapper<term <A, B> >, var<B> > type;
};
template <class A, class B>
struct term
{
typedef typename make_tree <A, B>::type tree;
A a;
std::list <tree> children;
term (A a
, std::list<tree> const& children)
: a (a), children (children)
{}
};
template <class A, class B>
inline term <A, B> make_term (
A a, std::list<typename make_tree<A, B>::type> const& c, B const*)
{
return term<A, B> (a, c);
}
template <class B>
struct var
{
B tag;
var (B tag) : tag (tag) {}
};
template <class B>
inline var<B> make_var (B tag) { return var<B> (tag); }
For example, this little program builds the term represented by the concrete syntax "a(b(), c)".
int main ()
{
typedef make_tree<std::string, std::string>::type tree;
typedef std::list<tree> term_list;
std::string const* tag_str=(std::string const*)0L;
// a(b(), c)
term_list l;
l.push_back (make_term(std::string("b"), term_list (), tag_str));
l.push_back (make_var(std::string("c")));
tree t = make_term(std::string("a"), l, tag_str);
return 0;
}