1/* 2 * Copyright (C) 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17%{ 18#include "aidl_language.h" 19#include "parser.h" 20#include "aidl_language_y.h" 21#include "logging.h" 22#include <android-base/parseint.h> 23#include <set> 24#include <map> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28 29int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *); 30 31AidlLocation loc(const yy::parser::location_type& begin, const yy::parser::location_type& end) { 32 AIDL_FATAL_IF(begin.begin.filename != begin.end.filename, AIDL_LOCATION_HERE); 33 AIDL_FATAL_IF(begin.end.filename != end.begin.filename, AIDL_LOCATION_HERE); 34 AIDL_FATAL_IF(end.begin.filename != end.end.filename, AIDL_LOCATION_HERE); 35 AidlLocation::Point begin_point { 36 .line = begin.begin.line, 37 .column = begin.begin.column, 38 }; 39 AidlLocation::Point end_point { 40 .line = end.end.line, 41 .column = end.end.column, 42 }; 43 return AidlLocation(*begin.begin.filename, begin_point, end_point, AidlLocation::Source::EXTERNAL); 44} 45 46AidlLocation loc(const yy::parser::location_type& l) { 47 return loc(l, l); 48} 49 50#define lex_scanner ps->Scanner() 51 52%} 53 54%initial-action { 55 @$.begin.filename = @$.end.filename = 56 const_cast<std::string *>(&ps->FileName()); 57} 58 59%parse-param { Parser* ps } 60%lex-param { void *lex_scanner } 61 62%glr-parser 63%skeleton "glr.cc" 64 65%expect-rr 0 66 67%define parse.error verbose 68%locations 69 70%union { 71 AidlToken* token; 72 char character; 73 std::string *str; 74 std::vector<std::unique_ptr<AidlToken>> *token_list; 75 AidlAnnotation* annotation; 76 AidlAnnotationParameter* param; 77 std::map<std::string, std::shared_ptr<AidlConstantValue>>* param_list; 78 std::vector<std::unique_ptr<AidlAnnotation>>* annotation_list; 79 AidlTypeSpecifier* type; 80 AidlArgument* arg; 81 AidlArgument::Direction direction; 82 AidlConstantValue* const_expr; 83 AidlEnumerator* enumerator; 84 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators; 85 std::vector<std::unique_ptr<AidlConstantValue>>* constant_value_list; 86 std::vector<std::unique_ptr<AidlArgument>>* arg_list; 87 AidlVariableDeclaration* variable; 88 AidlMethod* method; 89 AidlMember* constant; 90 std::vector<std::unique_ptr<AidlMember>>* members; 91 AidlDefinedType* declaration; 92 std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args; 93 std::vector<std::string>* type_params; 94 std::vector<std::unique_ptr<AidlDefinedType>>* declarations; 95 AidlUnstructuredHeaders* unstructured_headers; 96} 97 98%destructor { } <direction> 99%destructor { delete ($$); } <*> 100 101%token<token> PACKAGE "package" 102%token<token> IMPORT "import" 103%token<token> ANNOTATION "annotation" 104%token<token> C_STR "string literal" 105%token<token> IDENTIFIER "identifier" 106%token<token> INTERFACE "interface" 107%token<token> PARCELABLE "parcelable" 108%token<token> ONEWAY "oneway" 109%token<token> ENUM "enum" 110%token<token> UNION "union" 111%token<token> CONST "const" 112 113%token<token> CHARVALUE "char literal" 114%token<token> FLOATVALUE "float literal" 115%token<token> HEXVALUE "hex literal" 116%token<token> INTVALUE "int literal" 117 118%token '(' ')' ',' '=' '[' ']' '.' '{' '}' ';' 119%token UNKNOWN "unrecognized character" 120%token<token> CPP_HEADER "cpp_header (which can also be used as an identifier)" 121%token<token> NDK_HEADER "ndk_header (which can also be used as an identifier)" 122%token IN "in" 123%token INOUT "inout" 124%token OUT "out" 125%token TRUE_LITERAL "true" 126%token FALSE_LITERAL "false" 127 128/* Operator precedence and associativity, as per 129 * http://en.cppreference.com/w/cpp/language/operator_precedence */ 130/* Precedence level 13 - 14, LTR, logical operators*/ 131%left LOGICAL_OR 132%left LOGICAL_AND 133/* Precedence level 10 - 12, LTR, bitwise operators*/ 134%left '|' 135%left '^' 136%left '&' 137/* Precedence level 9, LTR */ 138%left EQUALITY NEQ 139/* Precedence level 8, LTR */ 140%left '<' '>' LEQ GEQ 141/* Precedence level 7, LTR */ 142%left LSHIFT RSHIFT 143/* Precedence level 6, LTR */ 144%left '+' '-' 145/* Precedence level 5, LTR */ 146%left '*' '/' '%' 147/* Precedence level 3, RTL; but we have to use %left here */ 148%right UNARY_PLUS UNARY_MINUS '!' '~' 149 150%type<declaration> decl 151%type<declaration> unannotated_decl 152%type<declaration> interface_decl 153%type<declaration> parcelable_decl 154%type<declaration> enum_decl 155%type<declaration> union_decl 156%type<members> parcelable_members interface_members 157%type<variable> variable_decl 158%type<type_params> optional_type_params 159%type<method> method_decl 160%type<constant> constant_decl 161%type<enumerator> enumerator 162%type<enumerators> enumerators enum_decl_body 163%type<param> parameter 164%type<param_list> parameter_list 165%type<param_list> parameter_non_empty_list 166%type<annotation> annotation 167%type<annotation_list>annotation_list 168%type<type> type 169%type<type> non_array_type 170%type<arg_list> arg_list arg_non_empty_list 171%type<arg> arg 172%type<direction> direction 173%type<type_args> type_args 174%type<type_params> type_params 175%type<const_expr> const_expr 176%type<constant_value_list> constant_value_list 177%type<constant_value_list> constant_value_non_empty_list 178%type<token_list> imports 179%type<declarations> decls 180%type<token> import identifier error qualified_name optional_package 181%type<unstructured_headers> optional_unstructured_headers 182 183%% 184 185document 186 : optional_package imports decls { 187 Comments comments; 188 if ($1) { 189 comments = $1->GetComments(); 190 } else if (!$2->empty()) { 191 comments = $2->front()->GetComments(); 192 } 193 std::vector<std::string> imports; 194 for (const auto& import : *$2) { 195 imports.push_back(import->GetText()); 196 } 197 ps->MakeDocument(loc(@1), comments, std::move(imports), std::move(*$3)); 198 delete $1; 199 delete $2; 200 delete $3; 201 } 202 ; 203 204/* A couple of tokens that are keywords elsewhere are identifiers when 205 * occurring in the identifier position. Therefore identifier is a 206 * non-terminal, which is either an IDENTIFIER token, or one of the 207 * aforementioned keyword tokens. 208 */ 209identifier 210 : IDENTIFIER 211 | CPP_HEADER 212 | NDK_HEADER 213 ; 214 215optional_package 216 : { 217 $$ = nullptr; 218 } 219 | PACKAGE qualified_name ';' { 220 ps->SetPackage($2->GetText()); 221 $$ = $1; // for comments 222 delete $2; 223 } 224 ; 225 226imports 227 : { $$ = new std::vector<std::unique_ptr<AidlToken>>(); } 228 | imports import 229 { 230 $$ = $1; 231 $$->emplace_back($2); 232 } 233 234import 235 : IMPORT qualified_name ';' { 236 // carry the comments before "import" token 237 $$ = new AidlToken($2->GetText(), $1->GetComments()); 238 delete $1; 239 delete $2; 240 }; 241 242qualified_name 243 : identifier { 244 $$ = $1; 245 } 246 | qualified_name '.' identifier 247 { $$ = $1; 248 $$->Append('.'); 249 $$->Append($3->GetText()); 250 delete $3; 251 }; 252 253decls 254 : decl 255 { $$ = new std::vector<std::unique_ptr<AidlDefinedType>>(); 256 if ($1 != nullptr) { 257 $$->emplace_back($1); 258 } 259 } 260 | decls decl 261 { $$ = $1; 262 if ($2 != nullptr) { 263 $$->emplace_back($2); 264 } 265 } 266 267decl 268 : annotation_list unannotated_decl 269 { 270 $$ = $2; 271 272 if ($1->size() > 0 && $$ != nullptr) { 273 // copy comments from annotation to decl 274 $$->SetComments($1->begin()->get()->GetComments()); 275 $$->Annotate(std::move(*$1)); 276 } 277 278 delete $1; 279 } 280 ; 281 282unannotated_decl 283 : parcelable_decl 284 | interface_decl 285 | enum_decl 286 | union_decl 287 ; 288 289type_params 290 : identifier { 291 $$ = new std::vector<std::string>(); 292 $$->emplace_back($1->GetText()); 293 delete $1; 294 } 295 | type_params ',' identifier { 296 $1->emplace_back($3->GetText()); 297 $$ = $1; 298 delete $3; 299 }; 300 301optional_type_params 302 : /* none */ { $$ = nullptr; } 303 | '<' type_params '>' { 304 $$ = $2; 305 }; 306 307optional_unstructured_headers 308 : /* none */ { $$ = new AidlUnstructuredHeaders; } 309 | optional_unstructured_headers CPP_HEADER C_STR { 310 $$ = $1; 311 $$->cpp = $3->GetText(); 312 delete $2; 313 delete $3; 314 } 315 | optional_unstructured_headers NDK_HEADER C_STR { 316 $$ = $1; 317 $$->ndk = $3->GetText(); 318 delete $2; 319 delete $3; 320 } 321 ; 322 323parcelable_decl 324 : PARCELABLE qualified_name optional_type_params optional_unstructured_headers ';' { 325 // No check for type name here. We allow nested types for unstructured parcelables. 326 $$ = new AidlParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), *$4, $3); 327 delete $1; 328 delete $2; 329 delete $4; 330 } 331 | PARCELABLE qualified_name optional_type_params '{' parcelable_members '}' { 332 ps->CheckValidTypeName(*$2, loc(@2)); 333 $$ = new AidlStructuredParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5); 334 delete $1; 335 delete $2; 336 } 337 | PARCELABLE error ';' { 338 ps->AddError(); 339 $$ = nullptr; 340 delete $1; 341 }; 342 343parcelable_members 344 : /* empty */ { 345 $$ = new std::vector<std::unique_ptr<AidlMember>>(); 346 } 347 | parcelable_members variable_decl { 348 $1->emplace_back($2); 349 $$ = $1; 350 } 351 | parcelable_members constant_decl { 352 $1->emplace_back($2); 353 $$ = $1; 354 } 355 | parcelable_members decl { 356 if ($2) $1->emplace_back($2); // decl may be nullptr on error 357 $$ = $1; 358 } 359 | parcelable_members error ';' { 360 ps->AddError(); 361 $$ = $1; 362 }; 363 364variable_decl 365 : type identifier ';' { 366 $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText()); 367 delete $2; 368 } 369 | type identifier '=' const_expr ';' { 370 // TODO(b/123321528): Support enum type default assignments (TestEnum foo = TestEnum.FOO). 371 $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText(), $4); 372 delete $2; 373 } 374 ; 375 376interface_decl 377 : INTERFACE qualified_name ';' { 378 ps->CheckValidTypeName(*$2, loc(@2)); 379 $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), nullptr); 380 delete $1; 381 delete $2; 382 } 383 | INTERFACE qualified_name '{' interface_members '}' { 384 ps->CheckValidTypeName(*$2, loc(@2)); 385 $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), $4); 386 delete $1; 387 delete $2; 388 } 389 | ONEWAY INTERFACE qualified_name '{' interface_members '}' { 390 ps->CheckValidTypeName(*$3, loc(@3)); 391 $$ = new AidlInterface(loc(@2), $3->GetText(), $1->GetComments(), true, ps->Package(), $5); 392 delete $1; 393 delete $2; 394 delete $3; 395 } 396 | INTERFACE error '{' interface_members '}' { 397 ps->AddError(); 398 $$ = nullptr; 399 delete $1; 400 delete $4; 401 }; 402 403interface_members 404 : 405 { $$ = new std::vector<std::unique_ptr<AidlMember>>(); } 406 | interface_members method_decl 407 { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; } 408 | interface_members constant_decl 409 { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; } 410 | interface_members decl 411 { 412 if ($2) $1->emplace_back($2); // decl may be nullptr on error 413 $$ = $1; 414 } 415 | interface_members error ';' { 416 ps->AddError(); 417 $$ = $1; 418 }; 419 420const_expr 421 : TRUE_LITERAL { $$ = AidlConstantValue::Boolean(loc(@1), true); } 422 | FALSE_LITERAL { $$ = AidlConstantValue::Boolean(loc(@1), false); } 423 | CHARVALUE { 424 $$ = AidlConstantValue::Character(loc(@1), $1->GetText()); 425 delete $1; 426 } 427 | INTVALUE { 428 $$ = AidlConstantValue::Integral(loc(@1), $1->GetText()); 429 if ($$ == nullptr) { 430 AIDL_ERROR(loc(@1)) << "Could not parse integer: " 431 << $1->GetText(); 432 ps->AddError(); 433 $$ = AidlConstantValue::Integral(loc(@1), "0"); 434 } 435 delete $1; 436 } 437 | FLOATVALUE { 438 $$ = AidlConstantValue::Floating(loc(@1), $1->GetText()); 439 delete $1; 440 } 441 | HEXVALUE { 442 $$ = AidlConstantValue::Integral(loc(@1), $1->GetText()); 443 if ($$ == nullptr) { 444 AIDL_ERROR(loc(@1)) << "Could not parse hexvalue: " 445 << $1->GetText(); 446 ps->AddError(); 447 $$ = AidlConstantValue::Integral(loc(@1), "0"); 448 } 449 delete $1; 450 } 451 | C_STR { 452 $$ = AidlConstantValue::String(loc(@1), $1->GetText()); 453 delete $1; 454 } 455 | qualified_name { 456 $$ = new AidlConstantReference(loc(@1), $1->GetText()); 457 delete $1; 458 } 459 | '{' constant_value_list '}' { 460 $$ = AidlConstantValue::Array(loc(@1), std::unique_ptr<vector<unique_ptr<AidlConstantValue>>>($2)); 461 } 462 | const_expr LOGICAL_OR const_expr { 463 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "||", std::unique_ptr<AidlConstantValue>($3)); 464 } 465 | const_expr LOGICAL_AND const_expr { 466 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "&&", std::unique_ptr<AidlConstantValue>($3)); 467 } 468 | const_expr '|' const_expr { 469 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "|" , std::unique_ptr<AidlConstantValue>($3)); 470 } 471 | const_expr '^' const_expr { 472 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "^" , std::unique_ptr<AidlConstantValue>($3)); 473 } 474 | const_expr '&' const_expr { 475 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "&" , std::unique_ptr<AidlConstantValue>($3)); 476 } 477 | const_expr EQUALITY const_expr { 478 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "==", std::unique_ptr<AidlConstantValue>($3)); 479 } 480 | const_expr NEQ const_expr { 481 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "!=", std::unique_ptr<AidlConstantValue>($3)); 482 } 483 | const_expr '<' const_expr { 484 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<" , std::unique_ptr<AidlConstantValue>($3)); 485 } 486 | const_expr '>' const_expr { 487 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">" , std::unique_ptr<AidlConstantValue>($3)); 488 } 489 | const_expr LEQ const_expr { 490 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<=", std::unique_ptr<AidlConstantValue>($3)); 491 } 492 | const_expr GEQ const_expr { 493 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">=", std::unique_ptr<AidlConstantValue>($3)); 494 } 495 | const_expr LSHIFT const_expr { 496 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<<", std::unique_ptr<AidlConstantValue>($3)); 497 } 498 | const_expr RSHIFT const_expr { 499 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">>", std::unique_ptr<AidlConstantValue>($3)); 500 } 501 | const_expr '+' const_expr { 502 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "+" , std::unique_ptr<AidlConstantValue>($3)); 503 } 504 | const_expr '-' const_expr { 505 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "-" , std::unique_ptr<AidlConstantValue>($3)); 506 } 507 | const_expr '*' const_expr { 508 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "*" , std::unique_ptr<AidlConstantValue>($3)); 509 } 510 | const_expr '/' const_expr { 511 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "/" , std::unique_ptr<AidlConstantValue>($3)); 512 } 513 | const_expr '%' const_expr { 514 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "%" , std::unique_ptr<AidlConstantValue>($3)); 515 } 516 | '+' const_expr %prec UNARY_PLUS { 517 $$ = new AidlUnaryConstExpression(loc(@1), "+", std::unique_ptr<AidlConstantValue>($2)); 518 } 519 | '-' const_expr %prec UNARY_MINUS { 520 $$ = new AidlUnaryConstExpression(loc(@1), "-", std::unique_ptr<AidlConstantValue>($2)); 521 } 522 | '!' const_expr { 523 $$ = new AidlUnaryConstExpression(loc(@1), "!", std::unique_ptr<AidlConstantValue>($2)); 524 } 525 | '~' const_expr { 526 $$ = new AidlUnaryConstExpression(loc(@1), "~", std::unique_ptr<AidlConstantValue>($2)); 527 } 528 | '(' const_expr ')' 529 { 530 $$ = $2; 531 } 532 | '(' error ')' 533 { 534 AIDL_ERROR(loc(@1)) << "invalid const expression within parenthesis"; 535 ps->AddError(); 536 // to avoid segfaults 537 $$ = AidlConstantValue::Integral(loc(@1), "0"); 538 } 539 ; 540 541constant_value_list 542 : /* empty */ { 543 $$ = new std::vector<std::unique_ptr<AidlConstantValue>>; 544 } 545 | constant_value_non_empty_list { 546 $$ = $1; 547 } 548 | constant_value_non_empty_list ',' { 549 $$ = $1; 550 } 551 ; 552 553constant_value_non_empty_list 554 : const_expr { 555 $$ = new std::vector<std::unique_ptr<AidlConstantValue>>; 556 $$->push_back(std::unique_ptr<AidlConstantValue>($1)); 557 } 558 | constant_value_non_empty_list ',' const_expr { 559 $$ = $1; 560 $$->push_back(std::unique_ptr<AidlConstantValue>($3)); 561 } 562 ; 563 564constant_decl 565 : annotation_list CONST type identifier '=' const_expr ';' { 566 if ($1->size() > 0) { 567 $3->SetComments($1->begin()->get()->GetComments()); 568 } else { 569 $3->SetComments($2->GetComments()); 570 } 571 // TODO(b/151102494) do not merge annotations. 572 $3->Annotate(std::move(*$1)); 573 $$ = new AidlConstantDeclaration(loc(@4), $3, $4->GetText(), $6); 574 delete $1; 575 delete $2; 576 delete $4; 577 } 578 ; 579 580enumerator 581 : identifier '=' const_expr { 582 $$ = new AidlEnumerator(loc(@1), $1->GetText(), $3, $1->GetComments()); 583 delete $1; 584 } 585 | identifier { 586 $$ = new AidlEnumerator(loc(@1), $1->GetText(), nullptr, $1->GetComments()); 587 delete $1; 588 } 589 ; 590 591enumerators 592 : enumerator { 593 $$ = new std::vector<std::unique_ptr<AidlEnumerator>>(); 594 $$->push_back(std::unique_ptr<AidlEnumerator>($1)); 595 } 596 | enumerators ',' enumerator { 597 $1->push_back(std::unique_ptr<AidlEnumerator>($3)); 598 $$ = $1; 599 } 600 ; 601 602enum_decl_body 603 : '{' enumerators '}' { $$ = $2; } 604 | '{' enumerators ',' '}' { $$ = $2; } 605 ; 606 607enum_decl 608 : ENUM qualified_name enum_decl_body { 609 ps->CheckValidTypeName(*$2, loc(@2)); 610 $$ = new AidlEnumDeclaration(loc(@2), $2->GetText(), $3, ps->Package(), $1->GetComments()); 611 delete $1; 612 delete $2; 613 delete $3; 614 } 615 ; 616 617union_decl 618 : UNION qualified_name optional_type_params '{' parcelable_members '}' { 619 ps->CheckValidTypeName(*$2, loc(@2)); 620 $$ = new AidlUnionDecl(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5); 621 delete $1; 622 delete $2; 623 } 624 ; 625 626method_decl 627 : type identifier '(' arg_list ')' ';' { 628 $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments()); 629 delete $2; 630 } 631 | annotation_list ONEWAY type identifier '(' arg_list ')' ';' { 632 const auto& comments = ($1->size() > 0) ? $1->begin()->get()->GetComments() : $2->GetComments(); 633 $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments); 634 $3->Annotate(std::move(*$1)); 635 delete $1; 636 delete $2; 637 delete $4; 638 } 639 | type identifier '(' arg_list ')' '=' INTVALUE ';' { 640 int32_t serial = 0; 641 if (!android::base::ParseInt($7->GetText(), &serial)) { 642 AIDL_ERROR(loc(@7)) << "Could not parse int value: " << $7->GetText(); 643 ps->AddError(); 644 } 645 $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments(), serial); 646 delete $2; 647 delete $7; 648 } 649 | annotation_list ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' { 650 const auto& comments = ($1->size() > 0) ? $1->begin()->get()->GetComments() : $2->GetComments(); 651 int32_t serial = 0; 652 if (!android::base::ParseInt($9->GetText(), &serial)) { 653 AIDL_ERROR(loc(@9)) << "Could not parse int value: " << $9->GetText(); 654 ps->AddError(); 655 } 656 $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments, serial); 657 $3->Annotate(std::move(*$1)); 658 delete $1; 659 delete $2; 660 delete $4; 661 delete $9; 662 }; 663 664arg_non_empty_list 665 : arg { 666 $$ = new std::vector<std::unique_ptr<AidlArgument>>(); 667 $$->push_back(std::unique_ptr<AidlArgument>($1)); 668 } 669 | arg_non_empty_list ',' arg { 670 $$ = $1; 671 $$->push_back(std::unique_ptr<AidlArgument>($3)); 672 }; 673 674arg_list 675 : /*empty*/ 676 { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); } 677 | arg_non_empty_list { $$ = $1; } 678 ; 679 680arg 681 : direction type identifier { 682 $$ = new AidlArgument(loc(@3), $1, $2, $3->GetText()); 683 delete $3; 684 } 685 | type identifier { 686 $$ = new AidlArgument(loc(@2), $1, $2->GetText()); 687 delete $2; 688 }; 689 690non_array_type 691 : annotation_list qualified_name { 692 $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), /*array=*/std::nullopt, nullptr, $2->GetComments()); 693 if (!$1->empty()) { 694 $$->SetComments($1->begin()->get()->GetComments()); 695 $$->Annotate(std::move(*$1)); 696 } 697 delete $1; 698 delete $2; 699 } 700 | non_array_type '<' type_args '>' { 701 ps->SetTypeParameters($1, $3); 702 $$ = $1; 703 } 704 | non_array_type '<' non_array_type '<' type_args RSHIFT { 705 ps->SetTypeParameters($3, $5); 706 auto params = new std::vector<std::unique_ptr<AidlTypeSpecifier>>(); 707 params->emplace_back($3); 708 ps->SetTypeParameters($1, params); 709 $$ = $1; 710 } 711 | non_array_type '<' type_args ',' non_array_type '<' type_args RSHIFT { 712 ps->SetTypeParameters($5, $7); 713 $3->emplace_back($5); 714 ps->SetTypeParameters($1, $3); 715 $$ = $1; 716 }; 717 718type 719 : non_array_type 720 | type annotation_list '[' ']' { 721 if (!$2->empty()) { 722 AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported."; 723 ps->AddError(); 724 } 725 if (!$1->MakeArray(DynamicArray{})) { 726 AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size."; 727 ps->AddError(); 728 } 729 $$ = $1; 730 delete $2; 731 } 732 | type annotation_list '[' const_expr ']' { 733 if (!$2->empty()) { 734 AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported."; 735 ps->AddError(); 736 } 737 if (!$1->MakeArray(FixedSizeArray{std::unique_ptr<AidlConstantValue>($4)})) { 738 AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size."; 739 ps->AddError(); 740 } 741 $$ = $1; 742 delete $2; 743 } 744 ; 745 746type_args 747 : type { 748 if (!$1->GetAnnotations().empty()) { 749 AIDL_ERROR(loc(@1)) << "Annotations for type arguments are not supported."; 750 ps->AddError(); 751 } 752 $$ = new std::vector<std::unique_ptr<AidlTypeSpecifier>>(); 753 $$->emplace_back($1); 754 } 755 | type_args ',' type { 756 $1->emplace_back($3); 757 $$ = $1; 758 }; 759 760annotation_list 761 : 762 { $$ = new std::vector<std::unique_ptr<AidlAnnotation>>(); } 763 | annotation_list annotation 764 { 765 if ($2 != nullptr) { 766 $1->emplace_back(std::unique_ptr<AidlAnnotation>($2)); 767 } 768 $$ = $1; 769 }; 770 771parameter 772 : identifier '=' const_expr { 773 $$ = new AidlAnnotationParameter{$1->GetText(), std::unique_ptr<AidlConstantValue>($3)}; 774 delete $1; 775 }; 776 777parameter_list 778 : /*empty*/{ 779 $$ = new std::map<std::string, std::shared_ptr<AidlConstantValue>>(); 780 } 781 | parameter_non_empty_list { 782 $$ = $1; 783 }; 784 785parameter_non_empty_list 786 : parameter { 787 $$ = new std::map<std::string, std::shared_ptr<AidlConstantValue>>(); 788 $$->emplace(std::move($1->name), $1->value.release()); 789 delete $1; 790 } 791 | parameter_non_empty_list ',' parameter { 792 $$ = $1; 793 if ($$->find($3->name) != $$->end()) { 794 AIDL_ERROR(loc(@3)) << "Trying to redefine parameter " << $3->name << "."; 795 ps->AddError(); 796 } 797 $$->emplace(std::move($3->name), std::move($3->value)); 798 delete $3; 799 }; 800 801annotation 802 : ANNOTATION { 803 // release() returns nullptr if unique_ptr is empty. 804 $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), {}, $1->GetComments()).release(); 805 if (!$$) { 806 ps->AddError(); 807 } 808 delete $1; 809 } 810 | ANNOTATION '(' const_expr ')' { 811 auto value = std::shared_ptr<AidlConstantValue>($3); 812 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list {{"value" , value}}; 813 $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), std::move(parameter_list), $1->GetComments()).release(); 814 if (!$$) { 815 ps->AddError(); 816 } 817 delete $1; 818 } 819 | ANNOTATION '(' parameter_list ')' { 820 // release() returns nullptr if unique_ptr is empty. 821 $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), std::move(*$3), $1->GetComments()).release(); 822 if (!$$) { 823 ps->AddError(); 824 } 825 delete $1; 826 delete $3; 827 } 828 ; 829 830direction 831 : IN 832 { $$ = AidlArgument::IN_DIR; } 833 | OUT 834 { $$ = AidlArgument::OUT_DIR; } 835 | INOUT 836 { $$ = AidlArgument::INOUT_DIR; }; 837 838%% 839 840#include <ctype.h> 841#include <stdio.h> 842 843void yy::parser::error(const yy::parser::location_type& l, const std::string& errstr) { 844 AIDL_ERROR(loc(l)) << errstr; 845 // parser will return error value 846} 847