#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 Less : public Base { public: typedef boost::shared_ptr child_ptr; private: child_ptr left; child_ptr right; public: Less(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); } }; class If : public Base { public: typedef boost::shared_ptr child_ptr; private: child_ptr left; child_ptr right; public: If(child_ptr l, child_ptr r) : left(l), right(r) {}; void print(std::ostream &out) { out << "if "; left->print(out); out << " "; right->print(out); } }; class IfTag {}; // Define grammar struct ConstructGrammar; // Convenience typedefs typedef boost::proto::terminal >::type Variable; typedef boost::proto::plus AddRule; typedef boost::proto::less LessRule; typedef boost::proto::assign AssignRule; typedef boost::proto::subscript< boost::proto::unary_expr< IfTag, ConstructGrammar >, ConstructGrammar > IfRule; // An if_ "operator" template typename boost::proto::result_of::make_expr::type if_(Expr const &expr) { return boost::proto::make_expr(expr); } // 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 ConstructGrammarCases { // The primary template matches nothing: template struct case_ : boost::proto::not_ {}; }; template<> struct ConstructGrammarCases::case_ : boost::proto::or_< boost::proto::when< Variable, boost::proto::_value> > {}; template<> struct ConstructGrammarCases::case_ : boost::proto::when< AddRule, ConstructBinary< Add, boost::shared_ptr, boost::shared_ptr >(ConstructGrammar(boost::proto::_left), ConstructGrammar(boost::proto::_right))> {}; template<> struct ConstructGrammarCases::case_ : boost::proto::when< LessRule, ConstructBinary< Less, boost::shared_ptr, boost::shared_ptr >(ConstructGrammar(boost::proto::_left), ConstructGrammar(boost::proto::_right))> {}; template<> struct ConstructGrammarCases::case_ : boost::proto::when< AssignRule, ConstructBinary< Assign, boost::shared_ptr, boost::shared_ptr >(ConstructGrammar(boost::proto::_left), ConstructGrammar(boost::proto::_right))> {}; template<> struct ConstructGrammarCases::case_ : boost::proto::when< IfRule, ConstructBinary(ConstructGrammar(boost::proto::_child(ConstructGrammar(boost::proto::_child0))), ConstructGrammar(boost::proto::_child1))> {}; struct ConstructGrammar : boost::proto::switch_ {}; 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( if_(a < b) [ a = a + c ] ); #if 0 // Does not compile. boost::shared_ptr expr = translate( if_(a < b) [ a = a + c ] ); expr->print(std::cout); std::cout << '\n'; #endif return 0; }