1 %{
2 #include "aidl_language.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 int yyerror(char* errstr);
8 int yylex(void);
9 extern int yylineno;
10
11 static int count_brackets(const char*);
12
13 %}
14
15 %token IMPORT
16 %token PACKAGE
17 %token IDENTIFIER
18 %token IDVALUE
19 %token GENERIC
20 %token ARRAY
21 %token PARCELABLE
22 %token INTERFACE
23 %token FLATTENABLE
24 %token RPC
25 %token IN
26 %token OUT
27 %token INOUT
28 %token ONEWAY
29
30 %%
31 document:
32 document_items { g_callbacks->document($1.document_item); }
33 | headers document_items { g_callbacks->document($2.document_item); }
34 ;
35
36 headers:
37 package { }
38 | imports { }
39 | package imports { }
40 ;
41
42 package:
43 PACKAGE { }
44 ;
45
46 imports:
47 IMPORT { g_callbacks->import(&($1.buffer)); }
48 | IMPORT imports { g_callbacks->import(&($1.buffer)); }
49 ;
50
51 document_items:
52 { $$.document_item = NULL; }
53 | document_items declaration {
54 if ($2.document_item == NULL) {
55 // error cases only
56 $$ = $1;
57 } else {
58 document_item_type* p = $1.document_item;
59 while (p && p->next) {
60 p=p->next;
61 }
62 if (p) {
63 p->next = (document_item_type*)$2.document_item;
64 $$ = $1;
65 } else {
66 $$.document_item = (document_item_type*)$2.document_item;
67 }
68 }
69 }
70 | document_items error {
71 fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", g_currentFilename,
72 $2.buffer.lineno, $2.buffer.data);
73 $$ = $1;
74 }
75 ;
76
77 declaration:
78 parcelable_decl { $$.document_item = (document_item_type*)$1.user_data; }
79 | interface_decl { $$.document_item = (document_item_type*)$1.interface_item; }
80 ;
81
82 parcelable_decl:
83 PARCELABLE IDENTIFIER ';' {
84 user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type));
85 b->document_item.item_type = USER_DATA_TYPE;
86 b->document_item.next = NULL;
87 b->keyword_token = $1.buffer;
88 b->name = $2.buffer;
89 b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
90 b->semicolon_token = $3.buffer;
91 b->flattening_methods = PARCELABLE_DATA;
92 $$.user_data = b;
93 }
94 | PARCELABLE ';' {
95 fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n",
96 g_currentFilename, $1.buffer.lineno);
97 $$.user_data = NULL;
98 }
99 | PARCELABLE error ';' {
100 fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n",
101 g_currentFilename, $2.buffer.lineno, $2.buffer.data);
102 $$.user_data = NULL;
103 }
104 | FLATTENABLE IDENTIFIER ';' {
105 user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type));
106 b->document_item.item_type = USER_DATA_TYPE;
107 b->document_item.next = NULL;
108 b->keyword_token = $1.buffer;
109 b->name = $2.buffer;
110 b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
111 b->semicolon_token = $3.buffer;
112 b->flattening_methods = PARCELABLE_DATA | RPC_DATA;
113 $$.user_data = b;
114 }
115 | FLATTENABLE ';' {
116 fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name.\n",
117 g_currentFilename, $1.buffer.lineno);
118 $$.user_data = NULL;
119 }
120 | FLATTENABLE error ';' {
121 fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name, saw \"%s\".\n",
122 g_currentFilename, $2.buffer.lineno, $2.buffer.data);
123 $$.user_data = NULL;
124 }
125
126 ;
127
128 interface_header:
129 INTERFACE {
130 interface_type* c = (interface_type*)malloc(sizeof(interface_type));
131 c->document_item.item_type = INTERFACE_TYPE_BINDER;
132 c->document_item.next = NULL;
133 c->interface_token = $1.buffer;
134 c->oneway = false;
135 memset(&c->oneway_token, 0, sizeof(buffer_type));
136 c->comments_token = &c->interface_token;
137 $$.interface_obj = c;
138 }
139 | ONEWAY INTERFACE {
140 interface_type* c = (interface_type*)malloc(sizeof(interface_type));
141 c->document_item.item_type = INTERFACE_TYPE_BINDER;
142 c->document_item.next = NULL;
143 c->interface_token = $2.buffer;
144 c->oneway = true;
145 c->oneway_token = $1.buffer;
146 c->comments_token = &c->oneway_token;
147 $$.interface_obj = c;
148 }
149 | RPC {
150 interface_type* c = (interface_type*)malloc(sizeof(interface_type));
151 c->document_item.item_type = INTERFACE_TYPE_RPC;
152 c->document_item.next = NULL;
153 c->interface_token = $1.buffer;
154 c->oneway = false;
155 memset(&c->oneway_token, 0, sizeof(buffer_type));
156 c->comments_token = &c->interface_token;
157 $$.interface_obj = c;
158 }
159 ;
160
161 interface_keywords:
162 INTERFACE
163 | RPC
164 ;
165
166 interface_decl:
167 interface_header IDENTIFIER '{' interface_items '}' {
168 interface_type* c = $1.interface_obj;
169 c->name = $2.buffer;
170 c->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
171 c->open_brace_token = $3.buffer;
172 c->interface_items = $4.interface_item;
173 c->close_brace_token = $5.buffer;
174 $$.interface_obj = c;
175 }
176 | interface_keywords error '{' interface_items '}' {
177 fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n",
178 g_currentFilename, $2.buffer.lineno, $2.buffer.data);
179 $$.document_item = NULL;
180 }
181 | interface_keywords error '}' {
182 fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n",
183 g_currentFilename, $2.buffer.lineno, $2.buffer.data);
184 $$.document_item = NULL;
185 }
186
187 ;
188
189 interface_items:
190 { $$.interface_item = NULL; }
191 | interface_items method_decl {
192 interface_item_type* p=$1.interface_item;
193 while (p && p->next) {
194 p=p->next;
195 }
196 if (p) {
197 p->next = (interface_item_type*)$2.method;
198 $$ = $1;
199 } else {
200 $$.interface_item = (interface_item_type*)$2.method;
201 }
202 }
203 | interface_items error ';' {
204 fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n",
205 g_currentFilename, $3.buffer.lineno);
206 $$ = $1;
207 }
208 ;
209
210 method_decl:
211 type IDENTIFIER '(' arg_list ')' ';' {
212 method_type *method = (method_type*)malloc(sizeof(method_type));
213 method->interface_item.item_type = METHOD_TYPE;
214 method->interface_item.next = NULL;
215 method->oneway = false;
216 method->type = $1.type;
217 memset(&method->oneway_token, 0, sizeof(buffer_type));
218 method->name = $2.buffer;
219 method->open_paren_token = $3.buffer;
220 method->args = $4.arg;
221 method->close_paren_token = $5.buffer;
222 method->hasId = false;
223 memset(&method->equals_token, 0, sizeof(buffer_type));
224 memset(&method->id, 0, sizeof(buffer_type));
225 method->semicolon_token = $6.buffer;
226 method->comments_token = &method->type.type;
227 $$.method = method;
228 }
229 | ONEWAY type IDENTIFIER '(' arg_list ')' ';' {
230 method_type *method = (method_type*)malloc(sizeof(method_type));
231 method->interface_item.item_type = METHOD_TYPE;
232 method->interface_item.next = NULL;
233 method->oneway = true;
234 method->oneway_token = $1.buffer;
235 method->type = $2.type;
236 method->name = $3.buffer;
237 method->open_paren_token = $4.buffer;
238 method->args = $5.arg;
239 method->close_paren_token = $6.buffer;
240 method->hasId = false;
241 memset(&method->equals_token, 0, sizeof(buffer_type));
242 memset(&method->id, 0, sizeof(buffer_type));
243 method->semicolon_token = $7.buffer;
244 method->comments_token = &method->oneway_token;
245 $$.method = method;
246 }
247 | type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' {
248 method_type *method = (method_type*)malloc(sizeof(method_type));
249 method->interface_item.item_type = METHOD_TYPE;
250 method->interface_item.next = NULL;
251 method->oneway = false;
252 memset(&method->oneway_token, 0, sizeof(buffer_type));
253 method->type = $1.type;
254 method->name = $2.buffer;
255 method->open_paren_token = $3.buffer;
256 method->args = $4.arg;
257 method->close_paren_token = $5.buffer;
258 method->hasId = true;
259 method->equals_token = $6.buffer;
260 method->id = $7.buffer;
261 method->semicolon_token = $8.buffer;
262 method->comments_token = &method->type.type;
263 $$.method = method;
264 }
265 | ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';' {
266 method_type *method = (method_type*)malloc(sizeof(method_type));
267 method->interface_item.item_type = METHOD_TYPE;
268 method->interface_item.next = NULL;
269 method->oneway = true;
270 method->oneway_token = $1.buffer;
271 method->type = $2.type;
272 method->name = $3.buffer;
273 method->open_paren_token = $4.buffer;
274 method->args = $5.arg;
275 method->close_paren_token = $6.buffer;
276 method->hasId = true;
277 method->equals_token = $7.buffer;
278 method->id = $8.buffer;
279 method->semicolon_token = $9.buffer;
280 method->comments_token = &method->oneway_token;
281 $$.method = method;
282 }
283 ;
284
285 arg_list:
286 { $$.arg = NULL; }
287 | arg { $$ = $1; }
288 | arg_list ',' arg {
289 if ($$.arg != NULL) {
290 // only NULL on error
291 $$ = $1;
292 arg_type *p = $1.arg;
293 while (p && p->next) {
294 p=p->next;
295 }
296 $3.arg->comma_token = $2.buffer;
297 p->next = $3.arg;
298 }
299 }
300 | error {
301 fprintf(stderr, "%s:%d: syntax error in parameter list\n", g_currentFilename, $1.buffer.lineno);
302 $$.arg = NULL;
303 }
304 ;
305
306 arg:
307 direction type IDENTIFIER {
308 arg_type* arg = (arg_type*)malloc(sizeof(arg_type));
309 memset(&arg->comma_token, 0, sizeof(buffer_type));
310 arg->direction = $1.buffer;
311 arg->type = $2.type;
312 arg->name = $3.buffer;
313 arg->next = NULL;
314 $$.arg = arg;
315 }
316 ;
317
318 type:
319 IDENTIFIER {
320 $$.type.type = $1.buffer;
321 init_buffer_type(&$$.type.array_token, yylineno);
322 $$.type.dimension = 0;
323 }
324 | IDENTIFIER ARRAY {
325 $$.type.type = $1.buffer;
326 $$.type.array_token = $2.buffer;
327 $$.type.dimension = count_brackets($2.buffer.data);
328 }
329 | GENERIC {
330 $$.type.type = $1.buffer;
331 init_buffer_type(&$$.type.array_token, yylineno);
332 $$.type.dimension = 0;
333 }
334 ;
335
336 direction:
337 { init_buffer_type(&$$.buffer, yylineno); }
338 | IN { $$.buffer = $1.buffer; }
339 | OUT { $$.buffer = $1.buffer; }
340 | INOUT { $$.buffer = $1.buffer; }
341 ;
342
343 %%
344
345 #include <ctype.h>
346 #include <stdio.h>
347
348 int g_error = 0;
349
yyerror(char * errstr)350 int yyerror(char* errstr)
351 {
352 fprintf(stderr, "%s:%d: %s\n", g_currentFilename, yylineno, errstr);
353 g_error = 1;
354 return 1;
355 }
356
init_buffer_type(buffer_type * buf,int lineno)357 void init_buffer_type(buffer_type* buf, int lineno)
358 {
359 buf->lineno = lineno;
360 buf->token = 0;
361 buf->data = NULL;
362 buf->extra = NULL;
363 }
364
count_brackets(const char * s)365 static int count_brackets(const char* s)
366 {
367 int n=0;
368 while (*s) {
369 if (*s == '[') n++;
370 s++;
371 }
372 return n;
373 }
374