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