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