1%{
2#include "aidl_language.h"
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7int yyerror(char* errstr);
8int yylex(void);
9extern int yylineno;
10
11static 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%%
31document:
32        document_items                          { g_callbacks->document($1.document_item); }
33    |   headers document_items                  { g_callbacks->document($2.document_item); }
34    ;
35
36headers:
37        package                                 { }
38    |   imports                                 { }
39    |   package imports                         { }
40    ;
41
42package:
43        PACKAGE                                 { }
44    ;
45
46imports:
47        IMPORT                                  { g_callbacks->import(&($1.buffer)); }
48    |   IMPORT imports                          { g_callbacks->import(&($1.buffer)); }
49    ;
50
51document_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
77declaration:
78        parcelable_decl                            { $$.document_item = (document_item_type*)$1.user_data; }
79    |   interface_decl                             { $$.document_item = (document_item_type*)$1.interface_item; }
80    ;
81
82parcelable_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
128interface_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
161interface_keywords:
162        INTERFACE
163    |   RPC
164    ;
165
166interface_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
189interface_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
210method_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
285arg_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
306arg:
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
318type:
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
336direction:
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
348int g_error = 0;
349
350int yyerror(char* errstr)
351{
352    fprintf(stderr, "%s:%d: %s\n", g_currentFilename, yylineno, errstr);
353    g_error = 1;
354    return 1;
355}
356
357void 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
365static 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