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