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 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 %%
30 document:
31 document_items { g_callbacks->document($1.document_item); }
32 | headers document_items { g_callbacks->document($2.document_item); }
33 ;
34
35 headers:
36 package { }
37 | imports { }
38 | package imports { }
39 ;
40
41 package:
42 PACKAGE { }
43 ;
44
45 imports:
46 IMPORT { g_callbacks->import(&($1.buffer)); }
47 | IMPORT imports { g_callbacks->import(&($1.buffer)); }
48 ;
49
50 document_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
76 declaration:
77 parcelable_decl { $$.document_item = (document_item_type*)$1.user_data; }
78 | interface_decl { $$.document_item = (document_item_type*)$1.interface_item; }
79 ;
80
81 parcelable_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
127 interface_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
160 interface_keywords:
161 INTERFACE
162 | RPC
163 ;
164
165 interface_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
188 interface_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
209 method_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
242 arg_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
263 arg:
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
275 type:
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
293 direction:
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
305 int g_error = 0;
306
yyerror(char * errstr)307 int yyerror(char* errstr)
308 {
309 fprintf(stderr, "%s:%d: %s\n", g_currentFilename, yylineno, errstr);
310 g_error = 1;
311 return 1;
312 }
313
init_buffer_type(buffer_type * buf,int lineno)314 void 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
count_brackets(const char * s)322 static 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