#include #include #include #include // 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 { public: typedef boost::shared_ptr child_ptr; private: 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); } }; class Assign : public Base { public: typedef boost::shared_ptr child_ptr; private: child_ptr left; child_ptr right; public: Assign(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 ConstructExpressionGrammar; struct ConstructStatementGrammar; struct ConstructGrammar; class Domain; // Expression wrapper template struct Wrapper { BOOST_PROTO_EXTENDS(Expr, Wrapper, Domain) }; // Convenience typedefs typedef Wrapper >::type> Variable; typedef boost::proto::plus AddRule; typedef boost::proto::assign AssignRule; // Semantic Actions // Transform a one-operand node template struct ConstructUnary : boost::proto::callable { typedef boost::shared_ptr result_type; result_type operator()(Child child) { return result_type(new NodeType(child)); } }; // Transform a two-operand node template struct ConstructBinary : boost::proto::callable { typedef boost::shared_ptr result_type; result_type operator()(Child left, Child right) { return result_type(new NodeType(left, right)); } }; // Grammar rules struct ConstructExpressionGrammarCases { // The primary template matches nothing: template struct case_ : boost::proto::not_ {}; }; template<> struct ConstructExpressionGrammarCases::case_ : boost::proto::or_< boost::proto::when< Variable, boost::proto::_value> > {}; template<> struct ConstructExpressionGrammarCases::case_ : boost::proto::when< AddRule, ConstructBinary< Add, boost::shared_ptr >(ConstructExpressionGrammar(boost::proto::_left), ConstructExpressionGrammar(boost::proto::_right))> {}; struct ConstructExpressionGrammar : boost::proto::switch_ {}; struct ConstructStatementGrammarCases { // The primary template matches nothing: template struct case_ : boost::proto::not_ {}; }; template<> struct ConstructStatementGrammarCases::case_ : boost::proto::when< AssignRule, ConstructBinary< Assign, boost::shared_ptr >(ConstructExpressionGrammar(boost::proto::_left), ConstructExpressionGrammar(boost::proto::_right))> {}; struct ConstructStatementGrammar : boost::proto::switch_ {}; // General IR grammar. struct ConstructGrammar : boost::proto::or_< ConstructExpressionGrammar, ConstructStatementGrammar> {}; struct Domain : boost::proto::domain > {}; template boost::shared_ptr translate(const Expr &expr) { ConstructGrammar trans; return trans(expr); } int main(void) { Variable a = {{boost::shared_ptr(new Reference("a"))}}; Variable b = {{boost::shared_ptr(new Reference("b"))}}; Variable c = {{boost::shared_ptr(new Reference("c"))}} ; boost::proto::display_expr( a = a + c ); boost::shared_ptr expr = translate( a = a + c ); expr->print(std::cout); std::cout << '\n'; return 0; }