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 AidlAnnotation* annotation; 75 AidlAnnotationParameter* param; 76 std::map<std::string, std::shared_ptr<AidlConstantValue>>* param_list; 77 std::vector<AidlAnnotation>* annotation_list; 78 AidlTypeSpecifier* type; 79 AidlArgument* arg; 80 AidlArgument::Direction direction; 81 AidlConstantValue* const_expr; 82 AidlEnumerator* enumerator; 83 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators; 84 std::vector<std::unique_ptr<AidlConstantValue>>* constant_value_list; 85 std::vector<std::unique_ptr<AidlArgument>>* arg_list; 86 AidlVariableDeclaration* variable; 87 AidlMethod* method; 88 AidlMember* constant; 89 std::vector<std::unique_ptr<AidlMember>>* members; 90 AidlDefinedType* declaration; 91 std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args; 92 std::vector<std::string>* type_params; 93 std::vector<std::unique_ptr<AidlImport>>* imports; 94 AidlImport* import; 95 AidlPackage* package; 96 std::vector<std::unique_ptr<AidlDefinedType>>* declarations; 97} 98 99%destructor { } <direction> 100%destructor { delete ($$); } <*> 101 102%token<token> PACKAGE "package" 103%token<token> IMPORT "import" 104%token<token> ANNOTATION "annotation" 105%token<token> C_STR "string literal" 106%token<token> IDENTIFIER "identifier" 107%token<token> INTERFACE "interface" 108%token<token> PARCELABLE "parcelable" 109%token<token> ONEWAY "oneway" 110%token<token> ENUM "enum" 111%token<token> UNION "union" 112%token<token> CONST "const" 113 114%token<token> CHARVALUE "char literal" 115%token<token> FLOATVALUE "float literal" 116%token<token> HEXVALUE "hex literal" 117%token<token> INTVALUE "int literal" 118 119%token '(' ')' ',' '=' '[' ']' '.' '{' '}' ';' 120%token UNKNOWN "unrecognized character" 121%token<token> CPP_HEADER "cpp_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<imports> imports 179%type<import> import 180%type<package> package 181%type<declarations> decls 182%type<token> identifier error qualified_name 183 184%% 185 186document 187 : package imports decls { 188 Comments comments; 189 if ($1) { 190 comments = $1->GetComments(); 191 } else if (!$2->empty()) { 192 comments = $2->front()->GetComments(); 193 } 194 ps->SetDocument(std::make_unique<AidlDocument>(loc(@1), comments, std::move(*$2), std::move(*$3))); 195 delete $1; 196 delete $2; 197 delete $3; 198 } 199 ; 200 201/* A couple of tokens that are keywords elsewhere are identifiers when 202 * occurring in the identifier position. Therefore identifier is a 203 * non-terminal, which is either an IDENTIFIER token, or one of the 204 * aforementioned keyword tokens. 205 */ 206identifier 207 : IDENTIFIER 208 | CPP_HEADER 209 ; 210 211package 212 : { 213 $$ = nullptr; 214 } 215 | PACKAGE qualified_name ';' { 216 $$ = new AidlPackage(loc(@1, @3), $1->GetComments()); 217 ps->SetPackage($2->GetText()); 218 delete $1; 219 delete $2; 220 } 221 ; 222 223imports 224 : { $$ = new std::vector<std::unique_ptr<AidlImport>>(); } 225 | imports import 226 { 227 $$ = $1; 228 auto it = std::find_if($$->begin(), $$->end(), [&](const auto& i) { 229 return $2->GetNeededClass() == i->GetNeededClass(); 230 }); 231 if (it == $$->end()) { 232 $$->emplace_back($2); 233 } else { 234 delete $2; 235 } 236 } 237 238import 239 : IMPORT qualified_name ';' { 240 $$ = new AidlImport(loc(@2), $2->GetText(), $1->GetComments()); 241 delete $1; 242 delete $2; 243 }; 244 245qualified_name 246 : identifier { 247 $$ = $1; 248 } 249 | qualified_name '.' identifier 250 { $$ = $1; 251 $$->Append('.'); 252 $$->Append($3->GetText()); 253 delete $3; 254 }; 255 256decls 257 : decl 258 { $$ = new std::vector<std::unique_ptr<AidlDefinedType>>(); 259 if ($1 != nullptr) { 260 $$->emplace_back($1); 261 } 262 } 263 | decls decl 264 { $$ = $1; 265 if ($2 != nullptr) { 266 $$->emplace_back($2); 267 } 268 } 269 270decl 271 : annotation_list unannotated_decl 272 { 273 $$ = $2; 274 275 if ($1->size() > 0 && $$ != nullptr) { 276 // copy comments from annotation to decl 277 $$->SetComments($1->begin()->GetComments()); 278 $$->Annotate(std::move(*$1)); 279 } 280 281 delete $1; 282 } 283 ; 284 285unannotated_decl 286 : parcelable_decl 287 | interface_decl 288 | enum_decl 289 | union_decl 290 ; 291 292type_params 293 : identifier { 294 $$ = new std::vector<std::string>(); 295 $$->emplace_back($1->GetText()); 296 delete $1; 297 } 298 | type_params ',' identifier { 299 $1->emplace_back($3->GetText()); 300 $$ = $1; 301 delete $3; 302 }; 303 304 optional_type_params 305 : /* none */ { $$ = nullptr; } 306 | '<' type_params '>' { 307 $$ = $2; 308 }; 309 310parcelable_decl 311 : PARCELABLE qualified_name optional_type_params ';' { 312 $$ = new AidlParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), "", $3); 313 delete $1; 314 delete $2; 315 } 316 | PARCELABLE qualified_name optional_type_params '{' parcelable_members '}' { 317 $$ = new AidlStructuredParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5); 318 delete $1; 319 delete $2; 320 } 321 | PARCELABLE qualified_name CPP_HEADER C_STR ';' { 322 $$ = new AidlParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $4->GetText()); 323 delete $1; 324 delete $2; 325 delete $3; 326 delete $4; 327 } 328 | PARCELABLE error ';' { 329 ps->AddError(); 330 $$ = nullptr; 331 delete $1; 332 }; 333 334parcelable_members 335 : /* empty */ { 336 $$ = new std::vector<std::unique_ptr<AidlMember>>(); 337 } 338 | parcelable_members variable_decl { 339 $1->emplace_back($2); 340 $$ = $1; 341 } 342 | parcelable_members constant_decl { 343 $1->emplace_back($2); 344 $$ = $1; 345 } 346 | parcelable_members error ';' { 347 ps->AddError(); 348 $$ = $1; 349 }; 350 351variable_decl 352 : type identifier ';' { 353 $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText()); 354 delete $2; 355 } 356 | type identifier '=' const_expr ';' { 357 // TODO(b/123321528): Support enum type default assignments (TestEnum foo = TestEnum.FOO). 358 $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText(), $4); 359 delete $2; 360 } 361 ; 362 363interface_decl 364 : INTERFACE identifier '{' interface_members '}' { 365 $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), $4); 366 delete $1; 367 delete $2; 368 } 369 | ONEWAY INTERFACE identifier '{' interface_members '}' { 370 $$ = new AidlInterface(loc(@2), $3->GetText(), $1->GetComments(), true, ps->Package(), $5); 371 delete $1; 372 delete $2; 373 delete $3; 374 } 375 | INTERFACE error '{' interface_members '}' { 376 ps->AddError(); 377 $$ = nullptr; 378 delete $1; 379 delete $4; 380 }; 381 382interface_members 383 : 384 { $$ = new std::vector<std::unique_ptr<AidlMember>>(); } 385 | interface_members method_decl 386 { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; } 387 | interface_members constant_decl 388 { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; } 389 | interface_members error ';' { 390 ps->AddError(); 391 $$ = $1; 392 }; 393 394const_expr 395 : TRUE_LITERAL { $$ = AidlConstantValue::Boolean(loc(@1), true); } 396 | FALSE_LITERAL { $$ = AidlConstantValue::Boolean(loc(@1), false); } 397 | CHARVALUE { 398 $$ = AidlConstantValue::Character(loc(@1), $1->GetText()); 399 delete $1; 400 } 401 | INTVALUE { 402 $$ = AidlConstantValue::Integral(loc(@1), $1->GetText()); 403 if ($$ == nullptr) { 404 AIDL_ERROR(loc(@1)) << "Could not parse integer: " 405 << $1->GetText(); 406 ps->AddError(); 407 $$ = AidlConstantValue::Integral(loc(@1), "0"); 408 } 409 delete $1; 410 } 411 | FLOATVALUE { 412 $$ = AidlConstantValue::Floating(loc(@1), $1->GetText()); 413 delete $1; 414 } 415 | HEXVALUE { 416 $$ = AidlConstantValue::Integral(loc(@1), $1->GetText()); 417 if ($$ == nullptr) { 418 AIDL_ERROR(loc(@1)) << "Could not parse hexvalue: " 419 << $1->GetText(); 420 ps->AddError(); 421 $$ = AidlConstantValue::Integral(loc(@1), "0"); 422 } 423 delete $1; 424 } 425 | C_STR { 426 $$ = AidlConstantValue::String(loc(@1), $1->GetText()); 427 delete $1; 428 } 429 | qualified_name { 430 $$ = new AidlConstantReference(loc(@1), $1->GetText()); 431 delete $1; 432 } 433 | '{' constant_value_list '}' { 434 $$ = AidlConstantValue::Array(loc(@1), std::unique_ptr<vector<unique_ptr<AidlConstantValue>>>($2)); 435 } 436 | const_expr LOGICAL_OR const_expr { 437 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "||", std::unique_ptr<AidlConstantValue>($3)); 438 } 439 | const_expr LOGICAL_AND const_expr { 440 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "&&", std::unique_ptr<AidlConstantValue>($3)); 441 } 442 | const_expr '|' const_expr { 443 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "|" , std::unique_ptr<AidlConstantValue>($3)); 444 } 445 | const_expr '^' const_expr { 446 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "^" , std::unique_ptr<AidlConstantValue>($3)); 447 } 448 | const_expr '&' const_expr { 449 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "&" , std::unique_ptr<AidlConstantValue>($3)); 450 } 451 | const_expr EQUALITY const_expr { 452 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "==", std::unique_ptr<AidlConstantValue>($3)); 453 } 454 | const_expr NEQ const_expr { 455 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "!=", std::unique_ptr<AidlConstantValue>($3)); 456 } 457 | const_expr '<' const_expr { 458 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<" , std::unique_ptr<AidlConstantValue>($3)); 459 } 460 | const_expr '>' const_expr { 461 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">" , std::unique_ptr<AidlConstantValue>($3)); 462 } 463 | const_expr LEQ const_expr { 464 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<=", std::unique_ptr<AidlConstantValue>($3)); 465 } 466 | const_expr GEQ const_expr { 467 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">=", std::unique_ptr<AidlConstantValue>($3)); 468 } 469 | const_expr LSHIFT const_expr { 470 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<<", std::unique_ptr<AidlConstantValue>($3)); 471 } 472 | const_expr RSHIFT const_expr { 473 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">>", std::unique_ptr<AidlConstantValue>($3)); 474 } 475 | const_expr '+' const_expr { 476 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "+" , std::unique_ptr<AidlConstantValue>($3)); 477 } 478 | const_expr '-' const_expr { 479 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "-" , std::unique_ptr<AidlConstantValue>($3)); 480 } 481 | const_expr '*' const_expr { 482 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "*" , std::unique_ptr<AidlConstantValue>($3)); 483 } 484 | const_expr '/' const_expr { 485 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "/" , std::unique_ptr<AidlConstantValue>($3)); 486 } 487 | const_expr '%' const_expr { 488 $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "%" , std::unique_ptr<AidlConstantValue>($3)); 489 } 490 | '+' const_expr %prec UNARY_PLUS { 491 $$ = new AidlUnaryConstExpression(loc(@1), "+", std::unique_ptr<AidlConstantValue>($2)); 492 } 493 | '-' const_expr %prec UNARY_MINUS { 494 $$ = new AidlUnaryConstExpression(loc(@1), "-", std::unique_ptr<AidlConstantValue>($2)); 495 } 496 | '!' const_expr { 497 $$ = new AidlUnaryConstExpression(loc(@1), "!", std::unique_ptr<AidlConstantValue>($2)); 498 } 499 | '~' const_expr { 500 $$ = new AidlUnaryConstExpression(loc(@1), "~", std::unique_ptr<AidlConstantValue>($2)); 501 } 502 | '(' const_expr ')' 503 { 504 $$ = $2; 505 } 506 | '(' error ')' 507 { 508 AIDL_ERROR(loc(@1)) << "invalid const expression within parenthesis"; 509 ps->AddError(); 510 // to avoid segfaults 511 $$ = AidlConstantValue::Integral(loc(@1), "0"); 512 } 513 ; 514 515constant_value_list 516 : /* empty */ { 517 $$ = new std::vector<std::unique_ptr<AidlConstantValue>>; 518 } 519 | constant_value_non_empty_list { 520 $$ = $1; 521 } 522 | constant_value_non_empty_list ',' { 523 $$ = $1; 524 } 525 ; 526 527constant_value_non_empty_list 528 : const_expr { 529 $$ = new std::vector<std::unique_ptr<AidlConstantValue>>; 530 $$->push_back(std::unique_ptr<AidlConstantValue>($1)); 531 } 532 | constant_value_non_empty_list ',' const_expr { 533 $$ = $1; 534 $$->push_back(std::unique_ptr<AidlConstantValue>($3)); 535 } 536 ; 537 538constant_decl 539 : annotation_list CONST type identifier '=' const_expr ';' { 540 if ($1->size() > 0) { 541 $3->SetComments($1->begin()->GetComments()); 542 } else { 543 $3->SetComments($2->GetComments()); 544 } 545 // TODO(b/151102494) do not merge annotations. 546 $3->Annotate(std::move(*$1)); 547 $$ = new AidlConstantDeclaration(loc(@4), $3, $4->GetText(), $6); 548 delete $1; 549 delete $2; 550 delete $4; 551 } 552 ; 553 554enumerator 555 : identifier '=' const_expr { 556 $$ = new AidlEnumerator(loc(@1), $1->GetText(), $3, $1->GetComments()); 557 delete $1; 558 } 559 | identifier { 560 $$ = new AidlEnumerator(loc(@1), $1->GetText(), nullptr, $1->GetComments()); 561 delete $1; 562 } 563 ; 564 565enumerators 566 : enumerator { 567 $$ = new std::vector<std::unique_ptr<AidlEnumerator>>(); 568 $$->push_back(std::unique_ptr<AidlEnumerator>($1)); 569 } 570 | enumerators ',' enumerator { 571 $1->push_back(std::unique_ptr<AidlEnumerator>($3)); 572 $$ = $1; 573 } 574 ; 575 576enum_decl_body 577 : '{' enumerators '}' { $$ = $2; } 578 | '{' enumerators ',' '}' { $$ = $2; } 579 ; 580 581enum_decl 582 : ENUM identifier enum_decl_body { 583 $$ = new AidlEnumDeclaration(loc(@2), $2->GetText(), $3, ps->Package(), $1->GetComments()); 584 delete $1; 585 delete $2; 586 delete $3; 587 } 588 ; 589 590union_decl 591 : UNION qualified_name optional_type_params '{' parcelable_members '}' { 592 $$ = new AidlUnionDecl(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5); 593 delete $1; 594 delete $2; 595 } 596 ; 597 598method_decl 599 : type identifier '(' arg_list ')' ';' { 600 $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments()); 601 delete $2; 602 } 603 | annotation_list ONEWAY type identifier '(' arg_list ')' ';' { 604 const auto& comments = ($1->size() > 0) ? $1->begin()->GetComments() : $2->GetComments(); 605 $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments); 606 $3->Annotate(std::move(*$1)); 607 delete $1; 608 delete $2; 609 delete $4; 610 } 611 | type identifier '(' arg_list ')' '=' INTVALUE ';' { 612 int32_t serial = 0; 613 if (!android::base::ParseInt($7->GetText(), &serial)) { 614 AIDL_ERROR(loc(@7)) << "Could not parse int value: " << $7->GetText(); 615 ps->AddError(); 616 } 617 $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $1->GetComments(), serial); 618 delete $2; 619 delete $7; 620 } 621 | annotation_list ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' { 622 const auto& comments = ($1->size() > 0) ? $1->begin()->GetComments() : $2->GetComments(); 623 int32_t serial = 0; 624 if (!android::base::ParseInt($9->GetText(), &serial)) { 625 AIDL_ERROR(loc(@9)) << "Could not parse int value: " << $9->GetText(); 626 ps->AddError(); 627 } 628 $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments, serial); 629 $3->Annotate(std::move(*$1)); 630 delete $1; 631 delete $2; 632 delete $4; 633 delete $9; 634 }; 635 636arg_non_empty_list 637 : arg { 638 $$ = new std::vector<std::unique_ptr<AidlArgument>>(); 639 $$->push_back(std::unique_ptr<AidlArgument>($1)); 640 } 641 | arg_non_empty_list ',' arg { 642 $$ = $1; 643 $$->push_back(std::unique_ptr<AidlArgument>($3)); 644 }; 645 646arg_list 647 : /*empty*/ 648 { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); } 649 | arg_non_empty_list { $$ = $1; } 650 ; 651 652arg 653 : direction type identifier { 654 $$ = new AidlArgument(loc(@3), $1, $2, $3->GetText()); 655 delete $3; 656 } 657 | type identifier { 658 $$ = new AidlArgument(loc(@2), $1, $2->GetText()); 659 delete $2; 660 }; 661 662non_array_type 663 : annotation_list qualified_name { 664 $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), false, nullptr, $2->GetComments()); 665 ps->DeferResolution($$); 666 if (!$1->empty()) { 667 $$->SetComments($1->begin()->GetComments()); 668 $$->Annotate(std::move(*$1)); 669 } 670 delete $1; 671 delete $2; 672 } 673 | non_array_type '<' type_args '>' { 674 ps->SetTypeParameters($1, $3); 675 $$ = $1; 676 } 677 | non_array_type '<' non_array_type '<' type_args RSHIFT { 678 ps->SetTypeParameters($3, $5); 679 auto params = new std::vector<std::unique_ptr<AidlTypeSpecifier>>(); 680 params->emplace_back($3); 681 ps->SetTypeParameters($1, params); 682 $$ = $1; 683 } 684 | non_array_type '<' type_args ',' non_array_type '<' type_args RSHIFT { 685 ps->SetTypeParameters($5, $7); 686 $3->emplace_back($5); 687 ps->SetTypeParameters($1, $3); 688 $$ = $1; 689 }; 690 691type 692 : non_array_type 693 | type annotation_list '[' ']' { 694 if (!$2->empty()) { 695 AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported."; 696 ps->AddError(); 697 } 698 if (!$1->SetArray()) { 699 AIDL_ERROR(loc(@1)) << "Can only have one dimensional arrays."; 700 ps->AddError(); 701 } 702 $$ = $1; 703 delete $2; 704 } 705 ; 706 707type_args 708 : type { 709 if (!$1->GetAnnotations().empty()) { 710 AIDL_ERROR(loc(@1)) << "Annotations for type arguments are not supported."; 711 ps->AddError(); 712 } 713 $$ = new std::vector<std::unique_ptr<AidlTypeSpecifier>>(); 714 $$->emplace_back($1); 715 } 716 | type_args ',' type { 717 $1->emplace_back($3); 718 $$ = $1; 719 }; 720 721annotation_list 722 : 723 { $$ = new std::vector<AidlAnnotation>(); } 724 | annotation_list annotation 725 { 726 if ($2 != nullptr) { 727 $1->emplace_back(std::move(*$2)); 728 delete $2; 729 } 730 $$ = $1; 731 }; 732 733parameter 734 : identifier '=' const_expr { 735 $$ = new AidlAnnotationParameter{$1->GetText(), std::unique_ptr<AidlConstantValue>($3)}; 736 delete $1; 737 }; 738 739parameter_list 740 : /*empty*/{ 741 $$ = new std::map<std::string, std::shared_ptr<AidlConstantValue>>(); 742 } 743 | parameter_non_empty_list { 744 $$ = $1; 745 }; 746 747parameter_non_empty_list 748 : parameter { 749 $$ = new std::map<std::string, std::shared_ptr<AidlConstantValue>>(); 750 $$->emplace(std::move($1->name), $1->value.release()); 751 delete $1; 752 } 753 | parameter_non_empty_list ',' parameter { 754 $$ = $1; 755 if ($$->find($3->name) != $$->end()) { 756 AIDL_ERROR(loc(@3)) << "Trying to redefine parameter " << $3->name << "."; 757 ps->AddError(); 758 } 759 $$->emplace(std::move($3->name), std::move($3->value)); 760 delete $3; 761 }; 762 763annotation 764 : ANNOTATION { 765 $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), nullptr, $1->GetComments()); 766 if (!$$) { 767 ps->AddError(); 768 } 769 delete $1; 770 } 771 | ANNOTATION '(' parameter_list ')' { 772 $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), $3, $1->GetComments()); 773 if (!$$) { 774 ps->AddError(); 775 } 776 delete $1; 777 delete $3; 778 } 779 ; 780 781direction 782 : IN 783 { $$ = AidlArgument::IN_DIR; } 784 | OUT 785 { $$ = AidlArgument::OUT_DIR; } 786 | INOUT 787 { $$ = AidlArgument::INOUT_DIR; }; 788 789%% 790 791#include <ctype.h> 792#include <stdio.h> 793 794void yy::parser::error(const yy::parser::location_type& l, const std::string& errstr) { 795 AIDL_ERROR(loc(l)) << errstr; 796 // parser will return error value 797} 798