reworked miniswig a bit to support virtual functions and to only emit constructors...
[supertux.git] / tools / miniswig / parser.yy
1 %{
2
3 #include <iostream>
4 #include <sstream>
5 #include <stdexcept>
6 #include "tree.h"
7 #include "globals.h"
8
9 %}
10
11 %pure_parser
12 %union {
13     char*       str;
14     int         ival;
15     float       fval;
16     Class*      _class;
17     Function*   function;
18     Type*       type;
19     AtomicType* atomic_type;
20     Namespace*  _namespace;
21 }
22
23 %{
24
25 extern int yylex(YYSTYPE* yylval);
26 void yyerror(const char* s);
27 extern int yylineno;
28
29 bool search_down = true;
30 Namespace* search_namespace = 0;
31 Namespace* current_namespace = 0;
32 static Class* current_class = 0;
33 static Function* currentFunction = 0;
34 static Type* current_type = 0;
35 static ClassMember::Visbility current_visibility;
36
37 class ParseError : public std::exception
38 {
39 public:
40     ParseError(const std::string& message) throw()
41     {
42         std::ostringstream msg;
43         msg << "Parse error in line " << yylineno << ": "
44             << message;
45         this->message = msg.str();
46     }
47     virtual ~ParseError() throw()
48     {}
49     const char* what() const throw()
50     {
51         return message.c_str();
52     }
53
54 private:
55     std::string message;
56 };
57
58 %}
59
60 %token <ival> T_INT
61 %token <fval> T_FLOAT
62 %token <str>  T_STRING
63 %token <str>  T_ID
64 %token <atomic_type> T_ATOMIC_TYPE
65 %token <_namespace> T_NAMESPACEREF;
66 %token T_CLASS
67 %token T_STRUCT
68 %token T_STATIC
69 %token T_VIRTUAL
70 %token T_CONST
71 %token T_UNSIGNED
72 %token T_SIGNED
73 %token T_VOID
74 %token T_BOOL
75 %token T_CHAR
76 %token T_SHORT
77 %token T_INT
78 %token T_LONG
79 %token T_FLOAT
80 %token T_DOUBLE
81 %token T_PUBLIC
82 %token T_PROTECTED
83 %token T_PRIVATE
84 %token T_NAMESPACE
85 %token T_DDCOL "::"
86
87 %type <_class> class_declaration
88 %type <function> function_declaration
89 %type <function> constructor_declaration;
90 %type <function> destructor_declaration;
91 %type <type>   type
92 %type <atomic_type> type_identifier
93
94 %%
95
96 input:
97         {
98             current_namespace = unit;
99         }
100     namespace_members
101 ;
102
103 namespace_members: /* empty */
104     | namespace_members namespace_member
105 ;
106
107 namespace_declaration:
108     T_NAMESPACE T_ID '{' 
109         {
110             Namespace* newNamespace = new Namespace();
111             newNamespace->name = $2;
112             free($2);
113             current_namespace->add_namespace(newNamespace);
114             current_namespace = newNamespace;
115         }
116     namespace_members '}'
117         {
118             current_namespace = current_namespace->parent;
119         }
120     | T_NAMESPACE T_NAMESPACEREF '{'
121         {
122             current_namespace = $2;
123         }
124     namespace_members '}'
125         {
126             current_namespace = current_namespace->parent;
127         }
128 ;
129
130 namespace_member:
131     class_declaration
132         { current_namespace->add_type($1); }
133     | function_declaration
134         { current_namespace->functions.push_back($1); }
135     | namespace_declaration
136 ;  
137
138 class_declaration:
139     T_CLASS T_ID '{' 
140         {
141             current_class = new Class();
142             current_class->name = $2;
143             free($2);
144             current_visibility = ClassMember::PROTECTED;
145         }
146     class_body '}' ';'
147         {
148             $$ = current_class;
149         }
150 ;
151
152 class_body: /* empty */
153         | class_body class_body_element
154 ;
155
156 class_body_element:
157         visibility_change
158         | constructor_declaration
159             { 
160                 $1->visibility = current_visibility;
161                 current_class->members.push_back($1);
162             }
163         | destructor_declaration
164             {
165                 $1->visibility = current_visibility;
166                 current_class->members.push_back($1);
167             }
168         | function_declaration
169             {
170                 $1->visibility = current_visibility;
171                 current_class->members.push_back($1);
172             }
173         | variable_declaration
174 ;
175
176 visibility_change:
177     T_PUBLIC ':'
178         { current_visibility = ClassMember::PUBLIC; }
179     |   T_PROTECTED ':'
180         { current_visibility = ClassMember::PROTECTED; }
181     |   T_PRIVATE ':'
182         { current_visibility = ClassMember::PRIVATE; }
183 ;
184
185 constructor_declaration:    
186     T_ID '('
187         {
188             currentFunction = new Function();
189             currentFunction->type = Function::CONSTRUCTOR;
190             free($1);
191         }
192     parameter_list ')' ';'
193         {
194             $$ = currentFunction;
195         }
196 ;
197
198 destructor_declaration:
199     maybe_virtual '~' T_ID '(' ')' abstract_declaration ';'
200         {
201             currentFunction = new Function();
202             currentFunction->type = Function::DESTRUCTOR;
203             free($3);
204             $$ = currentFunction;
205         }
206 ;
207
208 maybe_virtual:
209     /* empty */
210     | T_VIRTUAL
211 ;
212
213 variable_declaration:
214     type T_ID ';'
215 ;
216
217 function_declaration:
218     maybe_virtual type T_ID '(' 
219         {
220             currentFunction = new Function();
221             currentFunction->type = Function::FUNCTION;
222             currentFunction->return_type = *($2);
223             delete $2;
224             currentFunction->name = $3;
225             free($3);
226         }                           
227     parameter_list ')' abstract_declaration ';'
228         {
229             $$ = currentFunction;
230         }
231 ;
232
233 abstract_declaration:
234     /* empty */
235     | '=' T_INT
236 ;
237
238 parameter_list:
239     /* empty */
240     | parameters
241 ;
242
243 parameters:
244     parameter
245     | parameters ',' parameter
246 ;
247
248 parameter:
249     type
250         {
251             Parameter parameter;
252             parameter.type = *($1);
253             delete $1;
254             currentFunction->parameters.push_back(parameter);
255         }
256     | type T_ID
257         {
258             Parameter parameter;
259             parameter.type = *($1);
260             delete $1;
261             parameter.name = *($2);
262             free($2);
263             currentFunction->parameters.push_back(parameter);
264         }
265 ;
266
267 type:
268         {
269             current_type = new Type();
270         }
271     prefix_type_modifiers atomic_type postfix_type_modifiers 
272         {
273             $$ = current_type;
274         }
275 ;
276
277 prefix_type_modifiers:
278     /* empty */
279     | prefix_type_modifiers prefix_type_modifier
280 ;
281
282 prefix_type_modifier:
283     T_UNSIGNED
284         { current_type->_unsigned = true; }
285     | T_SIGNED
286         { current_type->_unsigned = false; }
287     | T_STATIC
288         { current_type->_static = true; }
289     | T_CONST
290         { current_type->_const = true; }
291 ;
292
293 postfix_type_modifiers:
294     /* empty */
295     | postfix_type_modifiers postfix_type_modifier
296 ;
297
298 postfix_type_modifier:
299     T_CONST
300         { current_type->_const = true; }
301     |   '*'
302         { current_type->pointer++; }
303     |   '&'
304         { current_type->ref++; }
305 ;
306
307 atomic_type:
308     T_VOID
309         { current_type->atomic_type = &BasicType::VOID; }
310     | T_BOOL
311         { current_type->atomic_type = &BasicType::BOOL; }
312     | T_CHAR
313         { current_type->atomic_type = &BasicType::CHAR; }
314     | T_SHORT
315         { current_type->atomic_type = &BasicType::SHORT; }
316     | T_INT
317         { current_type->atomic_type = &BasicType::INT; }
318     | T_LONG
319         { current_type->atomic_type = &BasicType::LONG; }
320     | T_FLOAT
321         { current_type->atomic_type = &BasicType::FLOAT; }
322     | T_DOUBLE
323         { current_type->atomic_type = &BasicType::DOUBLE; }
324     | type_identifier
325         { current_type->atomic_type = $1; }
326 ;
327
328 type_identifier:
329     T_ATOMIC_TYPE
330         {
331             // search for type in current compilation unit...
332             $$ = $1;
333         }
334     | namespace_refs "::" T_ATOMIC_TYPE
335         {
336             $$ = $3;
337             search_namespace = 0;
338             search_down = true;
339         }
340 ;
341
342 namespace_refs:
343     T_NAMESPACEREF
344         {
345             search_namespace = $1;
346             search_down = false;
347         }
348     | namespace_refs "::" T_NAMESPACEREF
349         {
350             search_namespace = $3;
351         }
352 ;
353
354 %%
355
356 void yyerror(const char* error)
357 {
358     throw ParseError(error);
359 }
360