miniswig supports int, float and string constants now
[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     class_body '}' ';'
154         {
155             $$ = current_class;
156         }
157 ;
158
159 class_body: /* empty */
160         | class_body class_body_element
161 ;
162
163 class_body_element:
164         visibility_change
165         | constructor_declaration
166             { 
167                 $1->visibility = current_visibility;
168                 current_class->members.push_back($1);
169             }
170         | destructor_declaration
171             {
172                 $1->visibility = current_visibility;
173                 current_class->members.push_back($1);
174             }
175         | function_declaration
176             {
177                 $1->visibility = current_visibility;
178                 current_class->members.push_back($1);
179             }
180         | field_declaration
181             {
182                 $1->visibility = current_visibility;
183                 current_class->members.push_back($1);
184             }
185 ;
186
187 visibility_change:
188     T_PUBLIC ':'
189         { current_visibility = ClassMember::PUBLIC; }
190     |   T_PROTECTED ':'
191         { current_visibility = ClassMember::PROTECTED; }
192     |   T_PRIVATE ':'
193         { current_visibility = ClassMember::PRIVATE; }
194 ;
195
196 constructor_declaration:    
197     T_ID '('
198         {
199             current_function = new Function();
200             current_function->type = Function::CONSTRUCTOR;
201             current_function->docu_comment = last_docucomment;
202             last_docucomment = "";
203             free($1);
204         }
205     parameter_list ')' ';'
206         {
207             $$ = current_function;
208         }
209 ;
210
211 destructor_declaration:
212     '~' T_ID '(' ')' abstract_declaration ';'
213         {
214             current_function = new Function();
215             current_function->type = Function::DESTRUCTOR;
216             current_function->docu_comment = last_docucomment;
217             last_docucomment = "";
218             free($2);
219             $$ = current_function;
220         }
221 ;
222
223 field_declaration:
224     type T_ID 
225         {
226             current_field = new Field();
227             current_field->type = $1;
228             current_field->name = $2;
229             free($2);
230         }
231     maybe_const_initialisation ';'
232         {
233             $$ = current_field;
234         }
235 ;
236
237 maybe_const_initialisation:
238     /* empty */
239     | '=' T_INT
240         {
241             if(current_field->type->atomic_type == &BasicType::FLOAT) {
242                 current_field->const_float_value = (float) $2;
243             } else {
244                 current_field->const_int_value = $2;
245             }
246             current_field->has_const_value = true;
247         }
248     | '=' T_FLOAT
249         {
250             current_field->const_float_value = $2;
251             current_field->has_const_value = true;
252         }
253     | '=' T_STRING
254         {
255             current_field->const_string_value = $2;
256             current_field->has_const_value = true;
257         }
258 ;          
259
260 function_declaration:
261     type T_ID '(' 
262         {
263             /*
264             current_function = new Function();
265             current_function->type = Function::FUNCTION;
266             current_function->return_type = *($2);
267             delete $2;
268             current_function->name = $3;
269             free($3);
270             current_function->docu_comment = last_docucomment;
271             last_docucomment = "";
272             */
273
274             current_function = new Function();
275             current_function->type = Function::FUNCTION;
276             current_function->return_type = *($1);
277             delete $1;
278             current_function->name = $2;
279             free($2);
280             current_function->docu_comment = last_docucomment;
281             last_docucomment = "";
282         }                           
283     parameter_list ')' abstract_declaration ';'
284         {
285             $$ = current_function;
286         }
287 ;
288
289 abstract_declaration:
290     /* empty */
291     | '=' T_INT
292 ;
293
294 parameter_list:
295     /* empty */
296     | parameters
297 ;
298
299 parameters:
300     parameter
301     | parameters ',' parameter
302 ;
303
304 parameter:
305     type
306         {
307             Parameter parameter;
308             parameter.type = *($1);
309             delete $1;
310             current_function->parameters.push_back(parameter);
311         }
312     | type T_ID
313         {
314             Parameter parameter;
315             parameter.type = *($1);
316             delete $1;
317             parameter.name = $2;
318             free($2);
319             current_function->parameters.push_back(parameter);
320         }
321 ;
322
323 type:
324         {
325             current_type = new Type();
326         }
327     prefix_type_modifiers atomic_type postfix_type_modifiers 
328         {
329             $$ = current_type;
330         }
331 ;
332
333 prefix_type_modifiers:
334     /* empty */
335     | prefix_type_modifiers prefix_type_modifier
336 ;
337
338 prefix_type_modifier:
339     T_UNSIGNED
340         { current_type->_unsigned = true; }
341     | T_SIGNED
342         { current_type->_unsigned = false; }
343     | T_STATIC
344         { current_type->_static = true; }
345     | T_CONST
346         { current_type->_const = true; }
347 ;
348
349 postfix_type_modifiers:
350     /* empty */
351     | postfix_type_modifiers postfix_type_modifier
352 ;
353
354 postfix_type_modifier:
355     T_CONST
356         { current_type->_const = true; }
357     |   '*'
358         { current_type->pointer++; }
359     |   '&'
360         { current_type->ref++; }
361 ;
362
363 atomic_type:
364     T_VOID
365         { current_type->atomic_type = &BasicType::VOID; }
366     | T_BOOL
367         { current_type->atomic_type = &BasicType::BOOL; }
368     | T_CHAR
369         { current_type->atomic_type = &BasicType::CHAR; }
370     | T_SHORT
371         { current_type->atomic_type = &BasicType::SHORT; }
372     | T_INT
373         { current_type->atomic_type = &BasicType::INT; }
374     | T_LONG
375         { current_type->atomic_type = &BasicType::LONG; }
376     | T_FLOAT
377         { current_type->atomic_type = &BasicType::FLOAT; }
378     | T_DOUBLE
379         { current_type->atomic_type = &BasicType::DOUBLE; }
380     | type_identifier
381         { current_type->atomic_type = $1; }
382 ;
383
384 type_identifier:
385     T_ATOMIC_TYPE
386         {
387             // search for type in current compilation unit...
388             $$ = $1;
389         }
390     | namespace_refs "::" T_ATOMIC_TYPE
391         {
392             $$ = $3;
393             search_namespace = 0;
394             search_down = true;
395         }
396 ;
397
398 namespace_refs:
399     T_NAMESPACEREF
400         {
401             search_namespace = $1;
402             search_down = false;
403         }
404     | namespace_refs "::" T_NAMESPACEREF
405         {
406             search_namespace = $3;
407         }
408 ;
409
410 %%
411
412 void yyerror(const char* error)
413 {
414     throw ParseError(error);
415 }
416