#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); } }; // Define grammar struct ConstructExpressionGrammar; struct ConstructStatementGrammar; struct ConstructGrammar; namespace keyword { struct if_ { friend std::ostream& operator<<(std::ostream& sout, if_) { return sout << "if_"; } }; struct else_ { friend std::ostream& operator<<(std::ostream& sout, else_) { return sout << "else_"; } }; struct do_ { friend std::ostream& operator<<(std::ostream& sout, do_) { return sout << "do_"; } }; struct while_ { friend std::ostream& operator<<(std::ostream& sout, while_) { return sout << "while_"; } }; } class Domain; // Expression wrapper template struct Expression { BOOST_PROTO_EXTENDS(Expr, Expression, Domain) // Use BOOST_PROTO_EXTENDS_MEMBERS() to define "virtual" // data members that all expressions in the mini-lambda // domain will have. They can be used to create expressions // like "if_(x)[y].else_[z]" and "do_[y].while_(z)". BOOST_PROTO_EXTENDS_MEMBERS( ((keyword::else_, else_)) ((keyword::while_, while_)) ) }; // Convenience typedefs typedef Expression >::type> Variable; typedef Expression::type> IfTerminal; typedef boost::proto::plus AddRule; typedef boost::proto::less LessRule; typedef boost::proto::assign AssignRule; typedef boost::proto::subscript< boost::proto::function< IfTerminal, ConstructExpressionGrammar >, ConstructStatementGrammar > IfRule; // 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))> {}; template<> struct ConstructExpressionGrammarCases::case_ : boost::proto::when< LessRule, ConstructBinary< Less, boost::shared_ptr >(ConstructExpressionGrammar(boost::proto::_left), ConstructExpressionGrammar(boost::proto::_right))> {}; struct ConstructExpressionGrammar : boost::proto::switch_ {}; struct ConstructStatementGrammarCases { // The primary template matches nothing: #ifdef NO_SPECIALIZATION template struct case_ : boost::proto::when< IfRule, ConstructBinary(ConstructExpressionGrammar(boost::proto::_right(boost::proto::_left)), ConstructStatementGrammar(boost::proto::_right))> {}; #else template struct case_ : boost::proto::not_ {}; #endif }; template<> struct ConstructStatementGrammarCases::case_ : boost::proto::when< AssignRule, ConstructBinary< Assign, boost::shared_ptr >(ConstructExpressionGrammar(boost::proto::_left), ConstructExpressionGrammar(boost::proto::_right))> {}; #ifdef NO_SPECIALIZATION template<> struct ConstructStatementGrammarCases::case_ : boost::proto::when< IfRule, ConstructBinary(ConstructExpressionGrammar(boost::proto::_right(boost::proto::_left)), ConstructStatementGrammar(boost::proto::_right))> {}; #endif struct ConstructStatementGrammar : boost::proto::switch_ {}; // General IR grammar. struct ConstructGrammar : boost::proto::or_< ConstructExpressionGrammar, ConstructStatementGrammar> {}; struct Domain : boost::proto::domain > {}; // An if_ "operator" template typename boost::proto::result_of::make_expr< boost::proto::tag::function, Domain, keyword::if_, Expr const &>::type if_(Expr const &expr) { return boost::proto::make_expr( keyword::if_(), boost::ref(expr)); } 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; }