e6094763fc82cef70866a4b768f1ccc785116dce
[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::Visibility current_visibility;
39
40 class ParseError : public std::exception
41 {
42 public:
43     ParseError(const std::string& message) throw() :
44          message()
45     {
46         std::ostringstream msg;
47         msg << "Parse error in '" << current_file
48             << "' line " << getCurrentLine() << ": "
49             << message;
50         this->message = msg.str();
51     }
52     virtual ~ParseError() throw()
53     {}
54     const char* what() const throw()
55     {
56         return message.c_str();
57     }
58
59 private:
60     std::string message;
61 };
62
63 %}
64
65 %token <ival> T_INT
66 %token <fval> T_FLOAT
67 %token <str>  T_STRING
68 %token <str>  T_ID
69 %token <atomic_type> T_ATOMIC_TYPE
70 %token <_namespace> T_NAMESPACEREF
71 %token T_CLASS
72 %token T_STRUCT
73 %token T_STATIC
74 %token T_SUSPEND
75 %token T_CUSTOM
76 %token T_CONST
77 %token T_UNSIGNED
78 %token T_SIGNED
79 %token T_VOID
80 %token T_BOOL
81 %token T_CHAR
82 %token T_SHORT
83 %token T_LONG
84 %token T_DOUBLE
85 %token T_PUBLIC
86 %token T_PROTECTED
87 %token T_PRIVATE
88 %token T_NAMESPACE
89 %token T_DDCOL "::"
90
91 %type <_class> class_declaration
92 %type <function> function_declaration
93 %type <function> constructor_declaration;
94 %type <function> destructor_declaration;
95 %type <field> field_declaration;
96 %type <type>   type
97 %type <atomic_type> type_identifier
98
99 %%
100
101 input:
102         {
103             current_namespace = unit;
104         }
105     namespace_members
106 ;
107
108 namespace_members: /* empty */
109     | namespace_members namespace_member
110 ;
111
112 namespace_declaration:
113     T_NAMESPACE T_ID '{' 
114         {
115             Namespace* newNamespace = new Namespace();
116             newNamespace->name = $2;
117             free($2);
118             current_namespace->add_namespace(newNamespace);
119             current_namespace = newNamespace;
120         }
121     namespace_members '}'
122         {
123             current_namespace = current_namespace->parent;
124         }
125     | T_NAMESPACE T_NAMESPACEREF '{'
126         {
127             current_namespace = $2;
128         }
129     namespace_members '}'
130         {
131             current_namespace = current_namespace->parent;
132         }
133 ;
134
135 namespace_member:
136     class_declaration
137         { current_namespace->add_type($1); }
138     | function_declaration
139         { current_namespace->functions.push_back($1); }
140     | namespace_declaration
141     | field_declaration
142         { current_namespace->fields.push_back($1); }
143 ;  
144
145 class_declaration:
146     T_CLASS T_ID 
147         {
148             current_class = new Class();
149             current_class->name = $2;
150             free($2);
151             current_class->docu_comment = last_docucomment;
152             last_docucomment = "";
153             current_visibility = ClassMember::PROTECTED;
154         }
155     superclass_list '{' class_body '}' ';'
156         {
157             $$ = current_class;
158         }
159 ;
160
161 superclass_list:
162     /* empty */
163     | ':' superclasses
164 ;
165
166 superclasses:
167       superclass
168     | superclasses ',' superclass
169 ;
170
171 superclass:
172     superclass_visibility type_identifier
173         {
174             Class* superclass = dynamic_cast<Class*> ($2);
175             if(superclass == 0)
176                 throw ParseError("SuperClass is not a Class type");
177             current_class->super_classes.push_back(superclass);
178             superclass->sub_classes.push_back(current_class);
179         }
180 ;
181
182 superclass_visibility:
183     T_PUBLIC
184     | T_PROTECTED
185     | T_PRIVATE
186 ;
187
188 class_body: /* empty */
189         | class_body class_body_element
190 ;
191
192 class_body_element:
193         visibility_change
194         | constructor_declaration
195             { 
196                 $1->visibility = current_visibility;
197                 current_class->members.push_back($1);
198             }
199         | destructor_declaration
200             {
201                 $1->visibility = current_visibility;
202                 current_class->members.push_back($1);
203             }
204         | function_declaration
205             {
206                 $1->visibility = current_visibility;
207                 current_class->members.push_back($1);
208             }
209         | field_declaration
210             {
211                 $1->visibility = current_visibility;
212                 current_class->members.push_back($1);
213             }
214 ;
215
216 visibility_change:
217     T_PUBLIC ':'
218         { current_visibility = ClassMember::PUBLIC; }
219     |   T_PROTECTED ':'
220         { current_visibility = ClassMember::PROTECTED; }
221     |   T_PRIVATE ':'
222         { current_visibility = ClassMember::PRIVATE; }
223 ;
224
225 constructor_declaration:    
226     T_ID '('
227         {
228             current_function = new Function();
229             current_function->type = Function::CONSTRUCTOR;
230             current_function->docu_comment = last_docucomment;
231             last_docucomment = "";
232             free($1);
233         }
234     parameter_list ')' ';'
235         {
236             $$ = current_function;
237         }
238 ;
239
240 destructor_declaration:
241     '~' T_ID '(' ')' abstract_declaration ';'
242         {
243             current_function = new Function();
244             current_function->type = Function::DESTRUCTOR;
245             current_function->docu_comment = last_docucomment;
246             last_docucomment = "";
247             free($2);
248             $$ = current_function;
249         }
250 ;
251
252 field_declaration:
253     type T_ID 
254         {
255             current_field = new Field();
256             current_field->type = $1;
257             current_field->docu_comment = last_docucomment;
258             last_docucomment = "";
259             current_field->name = $2;
260             free($2);
261         }
262     maybe_const_initialisation ';'
263         {
264             $$ = current_field;
265         }
266 ;
267
268 maybe_const_initialisation:
269     /* empty */
270     | '=' T_INT
271         {
272             if(current_field->type->atomic_type == &BasicType::FLOAT) {
273                 current_field->const_float_value = (float) $2;
274             } else {
275                 current_field->const_int_value = $2;
276             }
277             current_field->has_const_value = true;
278         }
279     | '=' T_FLOAT
280         {
281             current_field->const_float_value = $2;
282             current_field->has_const_value = true;
283         }
284     | '=' T_STRING
285         {
286             current_field->const_string_value = $2;
287             current_field->has_const_value = true;
288         }
289 ;          
290
291 function_declaration:
292     type T_ID '(' 
293         {
294             current_function = new Function();
295             current_function->type = Function::FUNCTION;
296             current_function->return_type = *($1);
297             delete $1;
298             current_function->name = $2;
299             free($2);
300             current_function->docu_comment = last_docucomment;
301             last_docucomment = "";
302         }                           
303     parameter_list ')' function_attributes abstract_declaration ';'
304         {
305             $$ = current_function;
306         }
307 ;
308
309 function_attributes:
310     /* empty */
311     | T_CONST function_attributes
312     | T_CUSTOM '(' T_STRING ')' function_attributes
313       {
314         current_function->parameter_spec = $3;
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 __attribute__((noreturn))
446 void yyerror(const char* error)
447 {
448     throw ParseError(error);
449 }
450