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