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