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