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