1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 =============================================================================*/
7 #if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
8 #define BOOST_SPIRIT_CONJURE_AST_HPP
9 
10 #include <boost/config/warning_disable.hpp>
11 #include <boost/variant/recursive_variant.hpp>
12 #include <boost/fusion/include/adapt_struct.hpp>
13 #include <boost/fusion/include/io.hpp>
14 #include <boost/optional.hpp>
15 #include <list>
16 
17 namespace client { namespace ast
18 {
19     ///////////////////////////////////////////////////////////////////////////
20     //  The AST
21     ///////////////////////////////////////////////////////////////////////////
22     struct tagged
23     {
24         int id; // Used to annotate the AST with the iterator position.
25                 // This id is used as a key to a map<int, Iterator>
26                 // (not really part of the AST.)
27     };
28 
29     struct nil {};
30     struct unary;
31     struct function_call;
32     struct expression;
33 
34     struct identifier : tagged
35     {
identifierclient::ast::identifier36         identifier(std::string const& name = "") : name(name) {}
37         std::string name;
38     };
39 
40     typedef boost::variant<
41             nil
42           , bool
43           , unsigned int
44           , identifier
45           , boost::recursive_wrapper<unary>
46           , boost::recursive_wrapper<function_call>
47           , boost::recursive_wrapper<expression>
48         >
49     operand;
50 
51     enum optoken
52     {
53         // precedence 1
54         op_comma,
55 
56         // precedence 2
57         op_assign,
58         op_plus_assign,
59         op_minus_assign,
60         op_times_assign,
61         op_divide_assign,
62         op_mod_assign,
63         op_bit_and_assign,
64         op_bit_xor_assign,
65         op_bitor_assign,
66         op_shift_left_assign,
67         op_shift_right_assign,
68 
69         // precedence 3
70         op_logical_or,
71 
72         // precedence 4
73         op_logical_and,
74 
75         // precedence 5
76         op_bit_or,
77 
78         // precedence 6
79         op_bit_xor,
80 
81         // precedence 7
82         op_bit_and,
83 
84         // precedence 8
85         op_equal,
86         op_not_equal,
87 
88         // precedence 9
89         op_less,
90         op_less_equal,
91         op_greater,
92         op_greater_equal,
93 
94         // precedence 10
95         op_shift_left,
96         op_shift_right,
97 
98         // precedence 11
99         op_plus,
100         op_minus,
101 
102         // precedence 12
103         op_times,
104         op_divide,
105         op_mod,
106 
107         // precedence 13
108         op_positive,
109         op_negative,
110         op_pre_incr,
111         op_pre_decr,
112         op_compl,
113         op_not,
114 
115         // precedence 14
116         op_post_incr,
117         op_post_decr,
118     };
119 
120     struct unary
121     {
122         optoken operator_;
123         operand operand_;
124     };
125 
126     struct operation
127     {
128         optoken operator_;
129         operand operand_;
130     };
131 
132     struct function_call
133     {
134         identifier function_name;
135         std::list<expression> args;
136     };
137 
138     struct expression
139     {
140         operand first;
141         std::list<operation> rest;
142     };
143 
144     struct assignment
145     {
146         identifier lhs;
147         expression rhs;
148     };
149 
150     struct variable_declaration
151     {
152         identifier lhs;
153         boost::optional<expression> rhs;
154     };
155 
156     struct if_statement;
157     struct while_statement;
158     struct statement_list;
159     struct return_statement;
160 
161     typedef boost::variant<
162             variable_declaration
163           , assignment
164           , boost::recursive_wrapper<if_statement>
165           , boost::recursive_wrapper<while_statement>
166           , boost::recursive_wrapper<return_statement>
167           , boost::recursive_wrapper<statement_list>
168         >
169     statement;
170 
171     struct statement_list : std::list<statement> {};
172 
173     struct if_statement
174     {
175         expression condition;
176         statement then;
177         boost::optional<statement> else_;
178     };
179 
180     struct while_statement
181     {
182         expression condition;
183         statement body;
184     };
185 
186     struct return_statement : tagged
187     {
188         boost::optional<expression> expr;
189     };
190 
191     struct function
192     {
193         std::string return_type;
194         identifier function_name;
195         std::list<identifier> args;
196         statement_list body;
197     };
198 
199     typedef std::list<function> function_list;
200 
201     // print functions for debugging
operator <<(std::ostream & out,nil)202     inline std::ostream& operator<<(std::ostream& out, nil)
203     {
204         out << "nil"; return out;
205     }
206 
operator <<(std::ostream & out,identifier const & id)207     inline std::ostream& operator<<(std::ostream& out, identifier const& id)
208     {
209         out << id.name; return out;
210     }
211 }}
212 
213 BOOST_FUSION_ADAPT_STRUCT(
214     client::ast::unary,
215     (client::ast::optoken, operator_)
216     (client::ast::operand, operand_)
217 )
218 
219 BOOST_FUSION_ADAPT_STRUCT(
220     client::ast::operation,
221     (client::ast::optoken, operator_)
222     (client::ast::operand, operand_)
223 )
224 
225 BOOST_FUSION_ADAPT_STRUCT(
226     client::ast::function_call,
227     (client::ast::identifier, function_name)
228     (std::list<client::ast::expression>, args)
229 )
230 
231 BOOST_FUSION_ADAPT_STRUCT(
232     client::ast::expression,
233     (client::ast::operand, first)
234     (std::list<client::ast::operation>, rest)
235 )
236 
237 BOOST_FUSION_ADAPT_STRUCT(
238     client::ast::variable_declaration,
239     (client::ast::identifier, lhs)
240     (boost::optional<client::ast::expression>, rhs)
241 )
242 
243 BOOST_FUSION_ADAPT_STRUCT(
244     client::ast::assignment,
245     (client::ast::identifier, lhs)
246     (client::ast::expression, rhs)
247 )
248 
249 BOOST_FUSION_ADAPT_STRUCT(
250     client::ast::if_statement,
251     (client::ast::expression, condition)
252     (client::ast::statement, then)
253     (boost::optional<client::ast::statement>, else_)
254 )
255 
256 BOOST_FUSION_ADAPT_STRUCT(
257     client::ast::while_statement,
258     (client::ast::expression, condition)
259     (client::ast::statement, body)
260 )
261 
262 BOOST_FUSION_ADAPT_STRUCT(
263     client::ast::return_statement,
264     (boost::optional<client::ast::expression>, expr)
265 )
266 
267 BOOST_FUSION_ADAPT_STRUCT(
268     client::ast::function,
269     (std::string, return_type)
270     (client::ast::identifier, function_name)
271     (std::list<client::ast::identifier>, args)
272     (client::ast::statement_list, body)
273 )
274 
275 #endif
276