03fb00c99cb73a3be560300f8012d34abfc6541c
[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     {
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_LONG
83 %token T_DOUBLE
84 %token T_PUBLIC
85 %token T_PROTECTED
86 %token T_PRIVATE
87 %token T_NAMESPACE
88 %token T_DDCOL "::"
89
90 %type <_class> class_declaration
91 %type <function> function_declaration
92 %type <function> constructor_declaration;
93 %type <function> destructor_declaration;
94 %type <field> field_declaration;
95 %type <type>   type
96 %type <atomic_type> type_identifier
97
98 %%
99
100 input:
101         {
102             current_namespace = unit;
103         }
104     namespace_members
105 ;
106
107 namespace_members: /* empty */
108     | namespace_members namespace_member
109 ;
110
111 namespace_declaration:
112     T_NAMESPACE T_ID '{' 
113         {
114             Namespace* newNamespace = new Namespace();
115             newNamespace->name = $2;
116             free($2);
117             current_namespace->add_namespace(newNamespace);
118             current_namespace = newNamespace;
119         }
120     namespace_members '}'
121         {
122             current_namespace = current_namespace->parent;
123         }
124     | T_NAMESPACE T_NAMESPACEREF '{'
125         {
126             current_namespace = $2;
127         }
128     namespace_members '}'
129         {
130             current_namespace = current_namespace->parent;
131         }
132 ;
133
134 namespace_member:
135     class_declaration
136         { current_namespace->add_type($1); }
137     | function_declaration
138         { current_namespace->functions.push_back($1); }
139     | namespace_declaration
140     | field_declaration
141         { current_namespace->fields.push_back($1); }
142 ;  
143
144 class_declaration:
145     T_CLASS T_ID 
146         {
147             current_class = new Class();
148             current_class->name = $2;
149             free($2);
150             current_class->docu_comment = last_docucomment;
151             last_docucomment = "";
152             current_visibility = ClassMember::PROTECTED;
153         }
154     superclass_list '{' class_body '}' ';'
155         {
156             $$ = current_class;
157         }
158 ;
159
160 superclass_list:
161     /* empty */
162     | ':' superclasses
163 ;
164
165 superclasses:
166       superclass
167     | superclasses ',' superclass
168 ;
169
170 superclass:
171     superclass_visibility type_identifier
172         {
173             Class* superclass = dynamic_cast<Class*> ($2);
174             if(superclass == 0)
175                 throw ParseError("SuperClass is not a Class type");
176             current_class->super_classes.push_back(superclass);
177             superclass->sub_classes.push_back(current_class);
178         }
179 ;
180
181 superclass_visibility:
182     T_PUBLIC
183     | T_PROTECTED
184     | T_PRIVATE
185 ;
186
187 class_body: /* empty */
188         | class_body class_body_element
189 ;
190
191 class_body_element:
192         visibility_change
193         | constructor_declaration
194             { 
195                 $1->visibility = current_visibility;
196                 current_class->members.push_back($1);
197             }
198         | destructor_declaration
199             {
200                 $1->visibility = current_visibility;
201                 current_class->members.push_back($1);
202             }
203         | function_declaration
204             {
205                 $1->visibility = current_visibility;
206                 current_class->members.push_back($1);
207             }
208         | field_declaration
209             {
210                 $1->visibility = current_visibility;
211                 current_class->members.push_back($1);
212             }
213 ;
214
215 visibility_change:
216     T_PUBLIC ':'
217         { current_visibility = ClassMember::PUBLIC; }
218     |   T_PROTECTED ':'
219         { current_visibility = ClassMember::PROTECTED; }
220     |   T_PRIVATE ':'
221         { current_visibility = ClassMember::PRIVATE; }
222 ;
223
224 constructor_declaration:    
225     T_ID '('
226         {
227             current_function = new Function();
228             current_function->type = Function::CONSTRUCTOR;
229             current_function->docu_comment = last_docucomment;
230             last_docucomment = "";
231             free($1);
232         }
233     parameter_list ')' ';'
234         {
235             $$ = current_function;
236         }
237 ;
238
239 destructor_declaration:
240     '~' T_ID '(' ')' abstract_declaration ';'
241         {
242             current_function = new Function();
243             current_function->type = Function::DESTRUCTOR;
244             current_function->docu_comment = last_docucomment;
245             last_docucomment = "";
246             free($2);
247             $$ = current_function;
248         }
249 ;
250
251 field_declaration:
252     type T_ID 
253         {
254             current_field = new Field();
255             current_field->type = $1;
256             current_field->docu_comment = last_docucomment;
257             last_docucomment = "";
258             current_field->name = $2;
259             free($2);
260         }
261     maybe_const_initialisation ';'
262         {
263             $$ = current_field;
264         }
265 ;
266
267 maybe_const_initialisation:
268     /* empty */
269     | '=' T_INT
270         {
271             if(current_field->type->atomic_type == &BasicType::FLOAT) {
272                 current_field->const_float_value = (float) $2;
273             } else {
274                 current_field->const_int_value = $2;
275             }
276             current_field->has_const_value = true;
277         }
278     | '=' T_FLOAT
279         {
280             current_field->const_float_value = $2;
281             current_field->has_const_value = true;
282         }
283     | '=' T_STRING
284         {
285             current_field->const_string_value = $2;
286             current_field->has_const_value = true;
287         }
288 ;          
289
290 function_declaration:
291     type T_ID '(' 
292         {
293             current_function = new Function();
294             current_function->type = Function::FUNCTION;
295             current_function->return_type = *($1);
296             delete $1;
297             current_function->name = $2;
298             free($2);
299             current_function->docu_comment = last_docucomment;
300             last_docucomment = "";
301         }                           
302     parameter_list ')' function_attributes abstract_declaration ';'
303         {
304             $$ = current_function;
305         }
306 ;
307
308 function_attributes:
309     /* empty */
310     | T_CONST function_attributes
311     | T_CUSTOM '(' T_STRING ')' function_attributes
312       {
313         current_function->parameter_spec = $3;
314         current_function->custom = true;
315       }
316     | T_SUSPEND function_attributes
317       {
318         current_function->suspend = true;
319       }
320 ;
321
322 abstract_declaration:
323     /* empty */
324     | '=' T_INT
325 ;
326
327 parameter_list:
328     /* empty */
329     | parameters
330 ;
331
332 parameters:
333     parameter
334     | parameters ',' parameter
335 ;
336
337 parameter:
338     type
339         {
340             Parameter parameter;
341             parameter.type = *($1);
342             delete $1;
343             current_function->parameters.push_back(parameter);
344         }
345     | type T_ID
346         {
347             Parameter parameter;
348             parameter.type = *($1);
349             delete $1;
350             parameter.name = $2;
351             free($2);
352             current_function->parameters.push_back(parameter);
353         }
354 ;
355
356 type:
357         {
358             current_type = new Type();
359         }
360     prefix_type_modifiers atomic_type postfix_type_modifiers 
361         {
362             $$ = current_type;
363         }
364 ;
365
366 prefix_type_modifiers:
367     /* empty */
368     | prefix_type_modifiers prefix_type_modifier
369 ;
370
371 prefix_type_modifier:
372     T_UNSIGNED
373         { current_type->_unsigned = true; }
374     | T_SIGNED
375         { current_type->_unsigned = false; }
376     | T_STATIC
377         { current_type->_static = true; }
378     | T_CONST
379         { current_type->_const = true; }
380 ;
381
382 postfix_type_modifiers:
383     /* empty */
384     | postfix_type_modifiers postfix_type_modifier
385 ;
386
387 postfix_type_modifier:
388     T_CONST
389         { current_type->_const = true; }
390     |   '*'
391         { current_type->pointer++; }
392     |   '&'
393         { current_type->ref++; }
394 ;
395
396 atomic_type:
397     T_VOID
398         { current_type->atomic_type = &BasicType::VOID; }
399     | T_BOOL
400         { current_type->atomic_type = &BasicType::BOOL; }
401     | T_CHAR
402         { current_type->atomic_type = &BasicType::CHAR; }
403     | T_SHORT
404         { current_type->atomic_type = &BasicType::SHORT; }
405     | T_INT
406         { current_type->atomic_type = &BasicType::INT; }
407     | T_LONG
408         { current_type->atomic_type = &BasicType::LONG; }
409     | T_FLOAT
410         { current_type->atomic_type = &BasicType::FLOAT; }
411     | T_DOUBLE
412         { current_type->atomic_type = &BasicType::DOUBLE; }
413     | type_identifier
414         { current_type->atomic_type = $1; }
415 ;
416
417 type_identifier:
418     T_ATOMIC_TYPE
419         {
420             $$ = $1;
421         }
422     | namespace_refs "::" T_ATOMIC_TYPE
423         {
424             $$ = $3;
425             search_namespace = 0;
426             search_down = true;
427         }
428 ;
429
430 namespace_refs:
431     T_NAMESPACEREF
432         {
433             search_namespace = $1;
434             search_down = false;
435         }
436     | namespace_refs "::" T_NAMESPACEREF
437         {
438             search_namespace = $3;
439         }
440 ;
441
442 %%
443
444 void yyerror(const char* error)
445 {
446     throw ParseError(error);
447 }
448