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