1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 Copyright (c) 2001-2011 Hartmut Kaiser 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 #if !defined(BOOST_SPIRIT_CONJURE_AST_HPP) 9 #define BOOST_SPIRIT_CONJURE_AST_HPP 10 11 #include <boost/config/warning_disable.hpp> 12 #include <boost/variant/recursive_variant.hpp> 13 #include <boost/fusion/include/adapt_struct.hpp> 14 #include <boost/fusion/include/io.hpp> 15 #include <boost/spirit/include/support_extended_variant.hpp> 16 #include <boost/spirit/include/support_attributes.hpp> 17 #include <boost/optional.hpp> 18 #include <list> 19 20 #include "ids.hpp" 21 22 namespace client { namespace ast 23 { 24 /////////////////////////////////////////////////////////////////////////// 25 // The AST 26 /////////////////////////////////////////////////////////////////////////// 27 struct tagged 28 { 29 int id; // Used to annotate the AST with the iterator position. 30 // This id is used as a key to a map<int, Iterator> 31 // (not really part of the AST.) 32 }; 33 34 struct nil {}; 35 struct unary_expr; 36 struct function_call; 37 struct expression; 38 39 struct identifier : tagged 40 { identifierclient::ast::identifier41 identifier(std::string const& name = "") : name(name) {} 42 std::string name; 43 }; 44 45 struct primary_expr : 46 tagged, 47 boost::spirit::extended_variant< 48 nil 49 , bool 50 , unsigned int 51 , identifier 52 , boost::recursive_wrapper<expression> 53 > 54 { primary_exprclient::ast::primary_expr55 primary_expr() : base_type() {} primary_exprclient::ast::primary_expr56 primary_expr(bool val) : base_type(val) {} primary_exprclient::ast::primary_expr57 primary_expr(unsigned int val) : base_type(val) {} primary_exprclient::ast::primary_expr58 primary_expr(identifier const& val) : base_type(val) {} primary_exprclient::ast::primary_expr59 primary_expr(expression const& val) : base_type(val) {} primary_exprclient::ast::primary_expr60 primary_expr(primary_expr const& rhs) 61 : base_type(rhs.get()) {} 62 }; 63 64 struct operand : 65 tagged, 66 boost::spirit::extended_variant< 67 nil 68 , primary_expr 69 , boost::recursive_wrapper<unary_expr> 70 , boost::recursive_wrapper<function_call> 71 > 72 { operandclient::ast::operand73 operand() : base_type() {} operandclient::ast::operand74 operand(primary_expr const& val) : base_type(val) {} operandclient::ast::operand75 operand(unary_expr const& val) : base_type(val) {} operandclient::ast::operand76 operand(function_call const& val) : base_type(val) {} operandclient::ast::operand77 operand(operand const& rhs) 78 : base_type(rhs.get()) {} 79 }; 80 81 struct unary_expr : tagged 82 { 83 token_ids::type operator_; 84 operand operand_; 85 }; 86 87 struct operation 88 { 89 token_ids::type operator_; 90 operand operand_; 91 }; 92 93 struct function_call 94 { 95 identifier function_name; 96 std::list<expression> args; 97 }; 98 99 struct expression 100 { 101 operand first; 102 std::list<operation> rest; 103 }; 104 105 struct assignment 106 { 107 identifier lhs; 108 token_ids::type operator_; 109 expression rhs; 110 }; 111 112 struct variable_declaration 113 { 114 identifier lhs; 115 boost::optional<expression> rhs; 116 }; 117 118 struct if_statement; 119 struct while_statement; 120 struct statement_list; 121 struct return_statement; 122 123 typedef boost::variant< 124 nil 125 , variable_declaration 126 , assignment 127 , boost::recursive_wrapper<if_statement> 128 , boost::recursive_wrapper<while_statement> 129 , boost::recursive_wrapper<return_statement> 130 , boost::recursive_wrapper<statement_list> 131 , boost::recursive_wrapper<expression> 132 > 133 statement; 134 135 struct statement_list : std::list<statement> {}; 136 137 struct if_statement 138 { 139 expression condition; 140 statement then; 141 boost::optional<statement> else_; 142 }; 143 144 struct while_statement 145 { 146 expression condition; 147 statement body; 148 }; 149 150 struct return_statement : tagged 151 { 152 boost::optional<expression> expr; 153 }; 154 155 struct function 156 { 157 std::string return_type; 158 identifier function_name; 159 std::list<identifier> args; 160 boost::optional<statement_list> body; 161 }; 162 163 typedef std::list<function> function_list; 164 165 // print functions for debugging operator <<(std::ostream & out,nil)166 inline std::ostream& operator<<(std::ostream& out, nil) 167 { 168 out << "nil"; return out; 169 } 170 operator <<(std::ostream & out,identifier const & id)171 inline std::ostream& operator<<(std::ostream& out, identifier const& id) 172 { 173 out << id.name; return out; 174 } 175 }} 176 177 BOOST_FUSION_ADAPT_STRUCT( 178 client::ast::unary_expr, 179 (client::token_ids::type, operator_) 180 (client::ast::operand, operand_) 181 ) 182 183 BOOST_FUSION_ADAPT_STRUCT( 184 client::ast::operation, 185 (client::token_ids::type, operator_) 186 (client::ast::operand, operand_) 187 ) 188 189 BOOST_FUSION_ADAPT_STRUCT( 190 client::ast::function_call, 191 (client::ast::identifier, function_name) 192 (std::list<client::ast::expression>, args) 193 ) 194 195 BOOST_FUSION_ADAPT_STRUCT( 196 client::ast::expression, 197 (client::ast::operand, first) 198 (std::list<client::ast::operation>, rest) 199 ) 200 201 BOOST_FUSION_ADAPT_STRUCT( 202 client::ast::variable_declaration, 203 (client::ast::identifier, lhs) 204 (boost::optional<client::ast::expression>, rhs) 205 ) 206 207 BOOST_FUSION_ADAPT_STRUCT( 208 client::ast::assignment, 209 (client::ast::identifier, lhs) 210 (client::token_ids::type, operator_) 211 (client::ast::expression, rhs) 212 ) 213 214 BOOST_FUSION_ADAPT_STRUCT( 215 client::ast::if_statement, 216 (client::ast::expression, condition) 217 (client::ast::statement, then) 218 (boost::optional<client::ast::statement>, else_) 219 ) 220 221 BOOST_FUSION_ADAPT_STRUCT( 222 client::ast::while_statement, 223 (client::ast::expression, condition) 224 (client::ast::statement, body) 225 ) 226 227 BOOST_FUSION_ADAPT_STRUCT( 228 client::ast::return_statement, 229 (boost::optional<client::ast::expression>, expr) 230 ) 231 232 BOOST_FUSION_ADAPT_STRUCT( 233 client::ast::function, 234 (std::string, return_type) 235 (client::ast::identifier, function_name) 236 (std::list<client::ast::identifier>, args) 237 (boost::optional<client::ast::statement_list>, body) 238 ) 239 240 #endif 241