|
Boost Users : |
Subject: Re: [Boost-users] Proto Help
From: David A. Greene (greened_at_[hidden])
Date: 2009-12-30 23:42:54
> In the grammar rule when<>, I'm not sure I can make a nested function
> type like that. I'm trying to tell the grammar to match the children and
> transform them, passing them to the ConstructBinary transformation to
> build the Add subtree.
>
> Any help is greatly appreciated. Thanks!
Here is a compilable testcase. Surprisingly, the nested function type seems
to compile. But how can I statically initialize a terminal that refers to a
boost::shared_ptr? I can't statically initialize the shared_ptr. Is there a
way to set a terminal's value after the fact?
-Dave
#include <boost/proto/proto.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <iostream>
// The toy IR
struct Base {
virtual void print(std::ostream &) = 0;
};
class Reference : public Base {
std::string name;
public:
Reference(const std::string &n) : name(n) {};
const std::string &getName(void) const {
return name;
}
void print(std::ostream &out) {
out << getName();
}
};
class Add : public Base {
typedef boost::shared_ptr<Base> child_ptr;
child_ptr left;
child_ptr right;
public:
Add(child_ptr l, child_ptr r) : left(l), right(r) {};
void print(std::ostream &out) {
out << "+ ";
left->print(out);
out << " ";
right->print(out);
}
};
// Define grammar
struct ConstructGrammar;
// Convenience typedefs
typedef boost::proto::terminal<boost::shared_ptr<Reference> >::type Variable;
typedef boost::proto::plus<ConstructGrammar, ConstructGrammar> AddRule;
// Semantic Actions
// Transform a one-operand node
template<typename NodeType,
typename Child = typename NodeType::child_ptr,
typename Dummy = boost::proto::callable>
struct ConstructUnary : boost::proto::callable {
typedef boost::shared_ptr<NodeType> result_type;
result_type operator()(Child child) {
return result_type(new NodeType(child));
}
};
// Transform a two-operand node
template<typename NodeType,
typename Child,
typename Dummy = boost::proto::callable>
struct ConstructBinary : boost::proto::callable {
typedef boost::shared_ptr<NodeType> result_type;
result_type operator()(Child left, Child right) {
return result_type(new NodeType(left, right));
}
};
// Grammar rules
struct ConstructGrammarCases {
// The primary template matches nothing:
template<typename Tag>
struct case_ : boost::proto::not_<boost::proto::_> {};
};
template<>
struct ConstructGrammarCases::case_<boost::proto::tag::terminal>
: boost::proto::or_<
boost::proto::when<
Variable,
boost::proto::_value> > {};
template<>
struct ConstructGrammarCases::case_<boost::proto::tag::plus>
: boost::proto::when<
AddRule,
ConstructBinary<
Add,
boost::shared_ptr<Base> >(ConstructGrammar(boost::proto::_left),
ConstructGrammar(boost::proto::_right))> {};
struct ConstructGrammar : boost::proto::switch_<ConstructGrammarCases> {};
template<typename Expr>
boost::shared_ptr<Base> translate(const Expr &expr) {
ConstructGrammar trans;
return trans(expr);
}
int main(void)
{
boost::shared_ptr<Base> a(new Reference("a"));
boost::shared_ptr<Base> b(new Reference("b"));
boost::shared_ptr<Base> c(new Reference("c"));
boost::shared_ptr<Base> expr1(new Add(b, c));
boost::shared_ptr<Base> expr2(new Add(a, expr1));
expr2->print(std::cout);
std::cout << '\n';
// How to initialize?
Variable av = {};
Variable bv = {};
Variable cv = {};
// These compile, but don't appear to do anything.
av = new Reference("a");
bv = new Reference("b");
cv = new Reference("c");
boost::shared_ptr<Base> expr3 = translate(av + (bv + cv));
// This faults with a null shared_ptr.
expr3->print(std::cout);
std::cout << '\n';
return 0;
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net