miniswig suspend is now an attribute appended to functions
[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     Field*      field;
19     Type*       type;
20     AtomicType* atomic_type;
21     Namespace*  _namespace;
22 }
23
24 %{
25
26 extern int yylex(YYSTYPE* yylval);
27 void yyerror(const char* s);
28 extern int yylineno;
29
30 bool search_down = true;
31 Namespace* search_namespace = 0;
32 Namespace* current_namespace = 0;
33 static Class* current_class = 0;
34 static Function* current_function = 0;
35 static Type* current_type = 0;
36 static Field* current_field = 0;
37 static ClassMember::Visbility current_visibility;
38
39 class ParseError : public std::exception
40 {
41 public:
42     ParseError(const std::string& message) throw()
43     {
44         std::ostringstream msg;
45         msg << "Parse error in '" << current_file
46             << "' line " << getCurrentLine() << ": "
47             << message;
48         this->message = msg.str();
49     }
50     virtual ~ParseError() throw()
51     {}
52     const char* what() const throw()
53     {
54         return message.c_str();
55     }
56
57 private:
58     std::string message;
59 };
60
61 %}
62
63 %token <ival> T_INT
64 %token <fval> T_FLOAT
65 %token <str>  T_STRING
66 %token <str>  T_ID
67 %token <atomic_type> T_ATOMIC_TYPE
68 %token <_namespace> T_NAMESPACEREF
69 %token T_CLASS
70 %token T_STRUCT
71 %token T_STATIC
72 %token T_SUSPEND
73 %token T_CONST
74 %token T_UNSIGNED
75 %token T_SIGNED
76 %token T_VOID
77 %token T_BOOL
78 %token T_CHAR
79 %token T_SHORT
80 %token T_INT
81 %token T_LONG
82 %token T_FLOAT
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_SUSPEND function_attributes
312       {
313         current_function->suspend = true;
314       }
315 ;
316
317 abstract_declaration:
318     /* empty */
319     | '=' T_INT
320 ;
321
322 parameter_list:
323     /* empty */
324     | parameters
325 ;
326
327 parameters:
328     parameter
329     | parameters ',' parameter
330 ;
331
332 parameter:
333     type
334         {
335             Parameter parameter;
336             parameter.type = *($1);
337             delete $1;
338             current_function->parameters.push_back(parameter);
339         }
340     | type T_ID
341         {
342             Parameter parameter;
343             parameter.type = *($1);
344             delete $1;
345             parameter.name = $2;
346             free($2);
347             current_function->parameters.push_back(parameter);
348         }
349 ;
350
351 type:
352         {
353             current_type = new Type();
354         }
355     prefix_type_modifiers atomic_type postfix_type_modifiers 
356         {
357             $$ = current_type;
358         }
359 ;
360
361 prefix_type_modifiers:
362     /* empty */
363     | prefix_type_modifiers prefix_type_modifier
364 ;
365
366 prefix_type_modifier:
367     T_UNSIGNED
368         { current_type->_unsigned = true; }
369     | T_SIGNED
370         { current_type->_unsigned = false; }
371     | T_STATIC
372         { current_type->_static = true; }
373     | T_CONST
374         { current_type->_const = true; }
375 ;
376
377 postfix_type_modifiers:
378     /* empty */
379     | postfix_type_modifiers postfix_type_modifier
380 ;
381
382 postfix_type_modifier:
383     T_CONST
384         { current_type->_const = true; }
385     |   '*'
386         { current_type->pointer++; }
387     |   '&'
388         { current_type->ref++; }
389 ;
390
391 atomic_type:
392     T_VOID
393         { current_type->atomic_type = &BasicType::VOID; }
394     | T_BOOL
395         { current_type->atomic_type = &BasicType::BOOL; }
396     | T_CHAR
397         { current_type->atomic_type = &BasicType::CHAR; }
398     | T_SHORT
399         { current_type->atomic_type = &BasicType::SHORT; }
400     | T_INT
401         { current_type->atomic_type = &BasicType::INT; }
402     | T_LONG
403         { current_type->atomic_type = &BasicType::LONG; }
404     | T_FLOAT
405         { current_type->atomic_type = &BasicType::FLOAT; }
406     | T_DOUBLE
407         { current_type->atomic_type = &BasicType::DOUBLE; }
408     | type_identifier
409         { current_type->atomic_type = $1; }
410 ;
411
412 type_identifier:
413     T_ATOMIC_TYPE
414         {
415             $$ = $1;
416         }
417     | namespace_refs "::" T_ATOMIC_TYPE
418         {
419             $$ = $3;
420             search_namespace = 0;
421             search_down = true;
422         }
423 ;
424
425 namespace_refs:
426     T_NAMESPACEREF
427         {
428             search_namespace = $1;
429             search_down = false;
430         }
431     | namespace_refs "::" T_NAMESPACEREF
432         {
433             search_namespace = $3;
434         }
435 ;
436
437 %%
438
439 void yyerror(const char* error)
440 {
441     throw ParseError(error);
442 }
443