also rename .h to .hpp in miniswig dir
[supertux.git] / tools / miniswig / parser.yy
1 %{
2
3 #include <iostream>
4 #include <sstream>
5 #include <stdexcept>
6 #include "tree.hpp"
7 #include "globals.hpp"
8
9 %}
10
11 %pure_parser
12 %union {
13     char*       str;
14     int         ival;
15     float       fval;
16     Class*      _class;
17     Function*   function;
18     Type*       type;
19     AtomicType* atomic_type;
20     Namespace*  _namespace;
21 }
22
23 %{
24
25 extern int yylex(YYSTYPE* yylval);
26 void yyerror(const char* s);
27 extern int yylineno;
28
29 bool search_down = true;
30 Namespace* search_namespace = 0;
31 Namespace* current_namespace = 0;
32 static Class* current_class = 0;
33 static Function* currentFunction = 0;
34 static Type* current_type = 0;
35 static ClassMember::Visbility current_visibility;
36
37 class ParseError : public std::exception
38 {
39 public:
40     ParseError(const std::string& message) throw()
41     {
42         std::ostringstream msg;
43         msg << "Parse error in '" << current_file
44             << "' line " << getCurrentLine() << ": "
45             << message;
46         this->message = msg.str();
47     }
48     virtual ~ParseError() throw()
49     {}
50     const char* what() const throw()
51     {
52         return message.c_str();
53     }
54
55 private:
56     std::string message;
57 };
58
59 %}
60
61 %token <ival> T_INT
62 %token <fval> T_FLOAT
63 %token <str>  T_STRING
64 %token <str>  T_ID
65 %token <atomic_type> T_ATOMIC_TYPE
66 %token <_namespace> T_NAMESPACEREF
67 %token T_CLASS
68 %token T_STRUCT
69 %token T_STATIC
70 %token T_VIRTUAL
71 %token T_CONST
72 %token T_UNSIGNED
73 %token T_SIGNED
74 %token T_VOID
75 %token T_BOOL
76 %token T_CHAR
77 %token T_SHORT
78 %token T_INT
79 %token T_LONG
80 %token T_FLOAT
81 %token T_DOUBLE
82 %token T_PUBLIC
83 %token T_PROTECTED
84 %token T_PRIVATE
85 %token T_NAMESPACE
86 %token T_DDCOL "::"
87
88 %type <_class> class_declaration
89 %type <function> function_declaration
90 %type <function> constructor_declaration;
91 %type <function> destructor_declaration;
92 %type <type>   type
93 %type <atomic_type> type_identifier
94
95 %%
96
97 input:
98         {
99             current_namespace = unit;
100         }
101     namespace_members
102 ;
103
104 namespace_members: /* empty */
105     | namespace_members namespace_member
106 ;
107
108 namespace_declaration:
109     T_NAMESPACE T_ID '{' 
110         {
111             Namespace* newNamespace = new Namespace();
112             newNamespace->name = $2;
113             free($2);
114             current_namespace->add_namespace(newNamespace);
115             current_namespace = newNamespace;
116         }
117     namespace_members '}'
118         {
119             current_namespace = current_namespace->parent;
120         }
121     | T_NAMESPACE T_NAMESPACEREF '{'
122         {
123             current_namespace = $2;
124         }
125     namespace_members '}'
126         {
127             current_namespace = current_namespace->parent;
128         }
129 ;
130
131 namespace_member:
132     class_declaration
133         { current_namespace->add_type($1); }
134     | function_declaration
135         { current_namespace->functions.push_back($1); }
136     | namespace_declaration
137 ;  
138
139 class_declaration:
140     T_CLASS T_ID '{' 
141         {
142             current_class = new Class();
143             current_class->name = $2;
144             free($2);
145             current_class->docu_comment = last_docucomment;
146             last_docucomment = "";
147             current_visibility = ClassMember::PROTECTED;
148         }
149     class_body '}' ';'
150         {
151             $$ = current_class;
152         }
153 ;
154
155 class_body: /* empty */
156         | class_body class_body_element
157 ;
158
159 class_body_element:
160         visibility_change
161         | constructor_declaration
162             { 
163                 $1->visibility = current_visibility;
164                 current_class->members.push_back($1);
165             }
166         | destructor_declaration
167             {
168                 $1->visibility = current_visibility;
169                 current_class->members.push_back($1);
170             }
171         | function_declaration
172             {
173                 $1->visibility = current_visibility;
174                 current_class->members.push_back($1);
175             }
176         | variable_declaration
177 ;
178
179 visibility_change:
180     T_PUBLIC ':'
181         { current_visibility = ClassMember::PUBLIC; }
182     |   T_PROTECTED ':'
183         { current_visibility = ClassMember::PROTECTED; }
184     |   T_PRIVATE ':'
185         { current_visibility = ClassMember::PRIVATE; }
186 ;
187
188 constructor_declaration:    
189     T_ID '('
190         {
191             currentFunction = new Function();
192             currentFunction->type = Function::CONSTRUCTOR;
193             currentFunction->docu_comment = last_docucomment;
194             last_docucomment = "";
195             free($1);
196         }
197     parameter_list ')' ';'
198         {
199             $$ = currentFunction;
200         }
201 ;
202
203 destructor_declaration:
204     maybe_virtual '~' T_ID '(' ')' abstract_declaration ';'
205         {
206             currentFunction = new Function();
207             currentFunction->type = Function::DESTRUCTOR;
208             currentFunction->docu_comment = last_docucomment;
209             last_docucomment = "";
210             free($3);
211             $$ = currentFunction;
212         }
213 ;
214
215 maybe_virtual:
216     /* empty */
217     | T_VIRTUAL
218 ;
219
220 variable_declaration:
221     type T_ID ';'
222         {
223             delete $1;
224             free($2);
225         }
226 ;
227
228 function_declaration:
229     maybe_virtual type T_ID '(' 
230         {
231             currentFunction = new Function();
232             currentFunction->type = Function::FUNCTION;
233             currentFunction->return_type = *($2);
234             delete $2;
235             currentFunction->name = $3;
236             free($3);
237             currentFunction->docu_comment = last_docucomment;
238             last_docucomment = "";
239         }                           
240     parameter_list ')' abstract_declaration ';'
241         {
242             $$ = currentFunction;
243         }
244 ;
245
246 abstract_declaration:
247     /* empty */
248     | '=' T_INT
249 ;
250
251 parameter_list:
252     /* empty */
253     | parameters
254 ;
255
256 parameters:
257     parameter
258     | parameters ',' parameter
259 ;
260
261 parameter:
262     type
263         {
264             Parameter parameter;
265             parameter.type = *($1);
266             delete $1;
267             currentFunction->parameters.push_back(parameter);
268         }
269     | type T_ID
270         {
271             Parameter parameter;
272             parameter.type = *($1);
273             delete $1;
274             parameter.name = $2;
275             free($2);
276             currentFunction->parameters.push_back(parameter);
277         }
278 ;
279
280 type:
281         {
282             current_type = new Type();
283         }
284     prefix_type_modifiers atomic_type postfix_type_modifiers 
285         {
286             $$ = current_type;
287         }
288 ;
289
290 prefix_type_modifiers:
291     /* empty */
292     | prefix_type_modifiers prefix_type_modifier
293 ;
294
295 prefix_type_modifier:
296     T_UNSIGNED
297         { current_type->_unsigned = true; }
298     | T_SIGNED
299         { current_type->_unsigned = false; }
300     | T_STATIC
301         { current_type->_static = true; }
302     | T_CONST
303         { current_type->_const = true; }
304 ;
305
306 postfix_type_modifiers:
307     /* empty */
308     | postfix_type_modifiers postfix_type_modifier
309 ;
310
311 postfix_type_modifier:
312     T_CONST
313         { current_type->_const = true; }
314     |   '*'
315         { current_type->pointer++; }
316     |   '&'
317         { current_type->ref++; }
318 ;
319
320 atomic_type:
321     T_VOID
322         { current_type->atomic_type = &BasicType::VOID; }
323     | T_BOOL
324         { current_type->atomic_type = &BasicType::BOOL; }
325     | T_CHAR
326         { current_type->atomic_type = &BasicType::CHAR; }
327     | T_SHORT
328         { current_type->atomic_type = &BasicType::SHORT; }
329     | T_INT
330         { current_type->atomic_type = &BasicType::INT; }
331     | T_LONG
332         { current_type->atomic_type = &BasicType::LONG; }
333     | T_FLOAT
334         { current_type->atomic_type = &BasicType::FLOAT; }
335     | T_DOUBLE
336         { current_type->atomic_type = &BasicType::DOUBLE; }
337     | type_identifier
338         { current_type->atomic_type = $1; }
339 ;
340
341 type_identifier:
342     T_ATOMIC_TYPE
343         {
344             // search for type in current compilation unit...
345             $$ = $1;
346         }
347     | namespace_refs "::" T_ATOMIC_TYPE
348         {
349             $$ = $3;
350             search_namespace = 0;
351             search_down = true;
352         }
353 ;
354
355 namespace_refs:
356     T_NAMESPACEREF
357         {
358             search_namespace = $1;
359             search_down = false;
360         }
361     | namespace_refs "::" T_NAMESPACEREF
362         {
363             search_namespace = $3;
364         }
365 ;
366
367 %%
368
369 void yyerror(const char* error)
370 {
371     throw ParseError(error);
372 }
373