Checking in miniswig: It's a flex/bison based parser that is able to parse
[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 static Class* currentClass = 0;
30 static Function* currentFunction = 0;
31 static Type* currentType = 0;
32 static ClassMember::Visbility currentVisibility;
33
34 class ParseError : public std::exception
35 {
36 public:
37     ParseError(const std::string& message) throw()
38     {
39         std::ostringstream msg;
40         msg << "Parse error in line " << yylineno << ": "
41             << message;
42         this->message = msg.str();
43     }
44     virtual ~ParseError() throw()
45     {}
46     const char* what() const throw()
47     {
48         return message.c_str();
49     }
50
51 private:
52     std::string message;
53 };
54
55 %}
56
57 %token <ival> T_INT
58 %token <fval> T_FLOAT
59 %token <str>  T_STRING
60 %token <str>  T_ID
61 %token <atomic_type> T_ATOMIC_TYPE
62 %token <_namespace> T_NAMESPACE;
63 %token T_CLASS
64 %token T_STRUCT
65 %token T_STATIC
66 %token T_CONST
67 %token T_UNSIGNED
68 %token T_SIGNED
69 %token T_VOID
70 %token T_BOOL
71 %token T_CHAR
72 %token T_SHORT
73 %token T_INT
74 %token T_LONG
75 %token T_FLOAT
76 %token T_DOUBLE
77 %token T_PUBLIC
78 %token T_PROTECTED
79 %token T_PRIVATE
80 %token T_DDCOL "::"
81
82 %type <_class> class_declaration
83 %type <function> function_declaration
84 %type <function> constructor_declaration;
85 %type <function> destructor_declaration;
86 %type <type>   type
87 %type <atomic_type> type_identifier
88
89 %%
90
91 input:  /* empty */
92     | compilation_unit
93 ;
94
95 compilation_unit: compilation_unit_part
96     | compilation_unit compilation_unit_part
97 ;
98
99 compilation_unit_part: class_declaration
100         { unit->types.push_back($1); }  
101     | function_declaration
102         { unit->functions.push_back($1); }
103 ;  
104
105 class_declaration: T_CLASS T_ID '{' 
106             {
107                 currentClass = new Class();
108                 currentClass->name = $2;
109                 free($2);
110                 currentVisibility = ClassMember::PROTECTED;
111             }
112         class_body '}' ';'
113             {
114                 $$ = currentClass;
115             }
116 ;
117
118 class_body: /* empty */
119         | visibility_change class_body
120         | constructor_declaration
121             { 
122                 $1->visibility = currentVisibility;
123                 currentClass->members.push_back($1);
124             }
125           class_body
126         | destructor_declaration
127             {
128                 $1->visibility = currentVisibility;
129                 currentClass->members.push_back($1);
130             }
131           class_body
132         | function_declaration
133             {
134                 $1->visibility = currentVisibility;
135                 currentClass->members.push_back($1);
136             }
137           class_body
138         | variable_declaration class_body
139 ;
140
141 visibility_change:  T_PUBLIC ':'
142             { currentVisibility = ClassMember::PUBLIC; }
143         |   T_PROTECTED ':'
144             { currentVisibility = ClassMember::PROTECTED; }
145         |   T_PRIVATE ':'
146             { currentVisibility = ClassMember::PRIVATE; }
147 ;
148
149 constructor_declaration:    T_ID '('
150         {
151             currentFunction = new Function();
152             currentFunction->type = Function::CONSTRUCTOR;
153             free($1);
154         }
155     param_list ')' ';'
156         {
157             $$ = currentFunction;
158         }
159 ;
160
161 destructor_declaration:     '~' T_ID '(' ')' ';'
162         {
163             currentFunction = new Function();
164             currentFunction->type = Function::DESTRUCTOR;
165             free($2);
166             $$ = currentFunction;
167         }
168 ;
169
170 variable_declaration:   type T_ID ';'
171
172 function_declaration:       type T_ID '(' 
173         {
174             currentFunction = new Function();
175             currentFunction->type = Function::FUNCTION;
176             currentFunction->return_type = *($1);
177             delete $1;
178             currentFunction->name = $2;
179             free($2);
180         }                           
181     param_list ')' ';'
182         {
183             $$ = currentFunction;
184         }
185 ;
186
187 param_list: /* empty */
188         | param_list2
189 ;
190
191 param_list2: parameter
192         | parameter ',' param_list2
193 ;
194
195 parameter: type
196             {
197                 Parameter parameter;
198                 parameter.type = *($1);
199                 delete $1;
200                 currentFunction->parameters.push_back(parameter);
201             }
202         | type T_ID
203             {
204                 Parameter parameter;
205                 parameter.type = *($1);
206                 delete $1;
207                 parameter.name = *($2);
208                 free($2);
209                 currentFunction->parameters.push_back(parameter);
210             }
211 ;
212
213 type: {
214           currentType = new Type();
215       }
216       prefix_type_modifiers atomic_type postfix_type_modifiers 
217       {
218           $$ = currentType;
219       }
220 ;
221
222 prefix_type_modifiers: /* empty */
223             | T_UNSIGNED prefix_type_modifiers
224             | T_SIGNED prefix_type_modifiers
225             | T_STATIC prefix_type_modifiers
226             | T_CONST prefix_type_modifiers
227 ;
228
229 postfix_type_modifiers: /* empty */
230             | T_CONST postfix_type_modifiers
231                 { currentType->_const = true; }
232             |   '*' postfix_type_modifiers
233                 { currentType->pointer++; }
234             |   '&' postfix_type_modifiers
235                 { currentType->ref++; }
236 ;
237
238 atomic_type:    T_VOID      { currentType->atomic_type = &BasicType::VOID; }
239             |   T_BOOL      { currentType->atomic_type = &BasicType::BOOL; }
240             |   T_CHAR      { currentType->atomic_type = &BasicType::CHAR; }
241             |   T_SHORT     { currentType->atomic_type = &BasicType::SHORT; }
242             |   T_INT       { currentType->atomic_type = &BasicType::INT; }
243             |   T_LONG      { currentType->atomic_type = &BasicType::LONG; }
244             |   T_FLOAT     { currentType->atomic_type = &BasicType::FLOAT; }
245             |   T_DOUBLE    { currentType->atomic_type = &BasicType::DOUBLE; }
246             |   type_identifier  { currentType->atomic_type = $1; }
247 ;
248
249 type_identifier: T_ATOMIC_TYPE
250         {
251             // search for type in current compilation unit...
252             $$ = $1;
253         }
254         |   T_NAMESPACE "::" type_identifier
255         {
256             // hack...
257             $$ = $3;
258         }
259 ;
260
261 %%
262
263 void yyerror(const char* error)
264 {
265     throw ParseError(error);
266 }
267