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 19 #include "AST.h" 20 #include "Annotation.h" 21 #include "ArrayType.h" 22 #include "CompoundType.h" 23 #include "ConstantExpression.h" 24 #include "DocComment.h" 25 #include "EnumType.h" 26 #include "Interface.h" 27 #include "Location.h" 28 #include "Method.h" 29 #include "RefType.h" 30 #include "Scope.h" 31 #include "TypeDef.h" 32 #include "VectorType.h" 33 34 #include "hidl-gen_y.h" 35 36 #include <android-base/logging.h> 37 #include <hidl-util/FQName.h> 38 #include <hidl-util/StringHelper.h> 39 #include <stdio.h> 40 41 using namespace android; 42 43 extern int yylex(yy::parser::semantic_type*, yy::parser::location_type*, void*, Scope** const); 44 45 void enterScope(AST* /* ast */, Scope** scope, Scope* container) { 46 CHECK(container->parent() == (*scope)); 47 *scope = container; 48 } 49 50 void leaveScope(AST* ast, Scope** scope) { 51 CHECK((*scope) != ast->getRootScope()); 52 *scope = (*scope)->parent(); 53 } 54 55 ::android::Location convertYYLoc(const yy::parser::location_type &loc) { 56 return ::android::Location( 57 ::android::Position(*(loc.begin.filename), loc.begin.line, loc.begin.column), 58 ::android::Position(*(loc.end.filename), loc.end.line, loc.end.column) 59 ); 60 } 61 62 bool isValidInterfaceField(const std::string& identifier, std::string *errorMsg) { 63 static const std::vector<std::string> reserved({ 64 // Injected names to C++ interfaces by auto-generated code 65 "isRemote", "descriptor", "hidlStaticBlock", "onTransact", 66 "castFrom", "Proxy", "Stub", "getService", 67 68 // Injected names to Java interfaces by auto-generated code 69 "asInterface", "castFrom", "getService", "toString", 70 71 // Inherited methods from IBase is detected in addMethod. Not added here 72 // because we need hidl-gen to compile IBase. 73 74 // Inherited names by interfaces from IInterface / IBinder 75 "onAsBinder", "asBinder", "queryLocalInterface", "getInterfaceDescriptor", "isBinderAlive", 76 "pingBinder", "dump", "transact", "checkSubclass", "attachObject", "findObject", 77 "detachObject", "localBinder", "remoteBinder", "mImpl", 78 79 // Inherited names from HidlInstrumentor 80 "InstrumentationEvent", "configureInstrumentation", "registerInstrumentationCallbacks", 81 "isInstrumentationLib", "mInstrumentationCal1lbacks", "mEnableInstrumentation", 82 "mInstrumentationLibPackage", "mInterfaceName", 83 84 // Collide with names in BsFoo 85 "mImpl", "addOnewayTask", "mOnewayQueue", 86 87 // Inherited names from Java IHwInterface 88 "asBinder", 89 }); 90 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) { 91 *errorMsg = identifier + " cannot be a name inside an interface"; 92 return false; 93 } 94 return true; 95 } 96 97 bool isValidStructField(const std::string& identifier, std::string *errorMsg) { 98 static const std::vector<std::string> reserved({ 99 // Injected names to structs and unions by auto-generated code 100 "readEmbeddedFromParcel", "writeEmbeddedToParcel", "readVectorFromParcel", 101 "writeVectorToParcel", "writeEmbeddedToBlob", 102 }); 103 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) { 104 *errorMsg = identifier + " cannot be a name inside an struct or union"; 105 return false; 106 } 107 return true; 108 } 109 110 bool isValidIdentifier(const std::string& identifier, std::string *errorMsg) { 111 static const std::vector<std::string> keywords({ 112 "uint8_t", "uint16_t", "uint32_t", "uint64_t", 113 "int8_t", "int16_t", "int32_t", "int64_t", "bool", "float", "double", 114 "interface", "struct", "union", "string", "vec", "enum", "ref", "handle", 115 "package", "import", "typedef", "generates", "oneway", "extends", 116 "fmq_sync", "fmq_unsync", 117 }); 118 static const std::vector<std::string> cppKeywords({ 119 "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit", 120 "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch", 121 "char", "char16_t", "char32_t", "class", "compl", "concept", "const", "constexpr", 122 "const_cast", "continue", "decltype", "default", "delete", "do", "double", 123 "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", 124 "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable", 125 "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", 126 "private", "protected", "public", "register", "reinterpret_cast", "requires", "return", 127 "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct", 128 "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try", 129 "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void", 130 "volatile", "wchar_t", "while", "xor", "xor_eq", 131 }); 132 static const std::vector<std::string> javaKeywords({ 133 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", 134 "synchronized", "boolean", "do", "if", "private", "this", "break", "double", 135 "implements", "protected", "throw", "byte", "else", "import", "public", "throws", 136 "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", 137 "short", "try", "char", "final", "interface", "static", "void", "class", "finally", 138 "long", "strictfp", "volatile", "const", "float", "native", "super", "while", 139 }); 140 static const std::vector<std::string> cppCollide({ 141 "size_t", "offsetof", 142 }); 143 144 // errors 145 if (std::find(keywords.begin(), keywords.end(), identifier) != keywords.end()) { 146 *errorMsg = identifier + " is a HIDL keyword " 147 "and is therefore not a valid identifier"; 148 return false; 149 } 150 if (std::find(cppKeywords.begin(), cppKeywords.end(), identifier) != cppKeywords.end()) { 151 *errorMsg = identifier + " is a C++ keyword " 152 "and is therefore not a valid identifier"; 153 return false; 154 } 155 if (std::find(javaKeywords.begin(), javaKeywords.end(), identifier) != javaKeywords.end()) { 156 *errorMsg = identifier + " is a Java keyword " 157 "and is therefore not a valid identifier"; 158 return false; 159 } 160 if (std::find(cppCollide.begin(), cppCollide.end(), identifier) != cppCollide.end()) { 161 *errorMsg = identifier + " collides with reserved names in C++ code " 162 "and is therefore not a valid identifier"; 163 return false; 164 } 165 if (StringHelper::StartsWith(identifier, "_hidl_")) { 166 *errorMsg = identifier + " starts with _hidl_ " 167 "and is therefore not a valid identifier"; 168 return false; 169 } 170 if (StringHelper::StartsWith(identifier, "hidl_")) { 171 *errorMsg = identifier + " starts with hidl_ " 172 "and is therefore not a valid identifier"; 173 return false; 174 } 175 if (StringHelper::EndsWith(identifier, "_cb")) { 176 *errorMsg = identifier + " ends with _cb " 177 "and is therefore not a valid identifier"; 178 return false; 179 } 180 181 return true; 182 } 183 184 // Return true if identifier is an acceptable name for an UDT. 185 bool isValidTypeName(const std::string& identifier, std::string *errorMsg) { 186 if (!isValidIdentifier(identifier, errorMsg)) { 187 return false; 188 } 189 190 if (identifier == "toString") { 191 *errorMsg = identifier + " is not a valid type name"; 192 return false; 193 } 194 195 return true; 196 } 197 198 %} 199 200 %initial-action { 201 // Initialize the initial location. 202 @$.begin.filename = @$.end.filename = 203 const_cast<std::string *>(&ast->getFilename()); 204 } 205 206 %parse-param { void* scanner } 207 %parse-param { android::AST* const ast } 208 %parse-param { android::Scope** const scope } 209 %lex-param { void* scanner } 210 %lex-param { android::Scope** const scope } 211 %pure-parser 212 %glr-parser 213 %skeleton "glr.cc" 214 215 %expect-rr 0 216 %error-verbose 217 218 %debug 219 220 %token<docComment> DOC_COMMENT "doc comment" 221 222 %token<void> ENUM "keyword `enum`" 223 %token<void> EXTENDS "keyword `extends`" 224 %token<str> FQNAME "fully-qualified name" 225 %token<void> GENERATES "keyword `generates`" 226 %token<str> IDENTIFIER "identifier" 227 %token<void> IMPORT "keyword `import`" 228 %token<str> INTEGER "integer value" 229 %token<str> FLOAT "float value" 230 %token<void> INTERFACE "keyword `interface`" 231 %token<str> PACKAGE "keyword `package`" 232 %token<type> TYPE "type" 233 %token<void> STRUCT "keyword `struct`" 234 %token<str> STRING_LITERAL "string literal" 235 %token<void> TYPEDEF "keyword `typedef`" 236 %token<void> UNION "keyword `union`" 237 %token<templatedType> TEMPLATED "templated type" 238 %token<void> ONEWAY "keyword `oneway`" 239 %token<str> UNKNOWN "unknown character" 240 241 /* Operator precedence and associativity, as per 242 * http://en.cppreference.com/w/cpp/language/operator_precedence */ 243 /* Precedence level 15 ternary operator */ 244 %right '?' ':' 245 /* Precedence level 13 - 14, LTR, logical operators*/ 246 %left LOGICAL_OR 247 %left LOGICAL_AND 248 /* Precedence level 10 - 12, LTR, bitwise operators*/ 249 %left '|' 250 %left '^' 251 %left '&' 252 /* Precedence level 9, LTR */ 253 %left EQUALITY NEQ 254 /* Precedence level 8, LTR */ 255 %left '<' '>' LEQ GEQ 256 /* Precedence level 7, LTR */ 257 %left LSHIFT RSHIFT 258 /* Precedence level 6, LTR */ 259 %left '+' '-' 260 /* Precedence level 5, LTR */ 261 %left '*' '/' '%' 262 /* Precedence level 3, RTL; but we have to use %left here */ 263 %left UNARY_MINUS UNARY_PLUS '!' '~' 264 265 %type<docComment> doc_comments 266 267 %type<str> error_stmt error 268 %type<str> package 269 %type<fqName> fqname 270 %type<referenceToType> fqtype 271 %type<str> valid_identifier valid_type_name 272 273 %type<referenceToType> type enum_storage_type type_or_inplace_compound_declaration 274 %type<referenceToType> array_type_base 275 %type<arrayType> array_type 276 %type<referenceToType> opt_extends 277 %type<type> type_declaration commentable_type_declaration type_declaration_body 278 %type<type> interface_declaration typedef_declaration 279 %type<type> named_struct_or_union_declaration named_enum_declaration 280 %type<type> compound_declaration annotated_compound_declaration 281 282 %type<field> field_declaration commentable_field_declaration 283 %type<fields> field_declarations struct_or_union_body 284 %type<constantExpression> const_expr 285 %type<enumValue> enum_value commentable_enum_value 286 %type<enumValues> enum_values enum_declaration_body 287 %type<typedVars> typed_vars 288 %type<typedVar> typed_var 289 %type<method> method_declaration commentable_method_declaration 290 %type<compoundStyle> struct_or_union_keyword 291 %type<stringVec> annotation_string_values annotation_string_value 292 %type<constExprVec> annotation_const_expr_values annotation_const_expr_value 293 %type<annotationParam> annotation_param 294 %type<annotationParams> opt_annotation_params annotation_params 295 %type<annotation> annotation 296 %type<annotations> opt_annotations 297 298 %start program 299 300 %union { 301 const char *str; 302 android::Type* type; 303 android::Reference<android::Type>* referenceToType; 304 android::ArrayType *arrayType; 305 android::TemplatedType *templatedType; 306 android::FQName *fqName; 307 android::CompoundType *compoundType; 308 android::NamedReference<android::Type>* field; 309 std::vector<android::NamedReference<android::Type>*>* fields; 310 android::EnumValue *enumValue; 311 android::ConstantExpression *constantExpression; 312 std::vector<android::EnumValue *> *enumValues; 313 android::NamedReference<android::Type>* typedVar; 314 android::TypedVarVector *typedVars; 315 android::Method *method; 316 android::CompoundType::Style compoundStyle; 317 std::vector<std::string> *stringVec; 318 std::vector<android::ConstantExpression *> *constExprVec; 319 android::AnnotationParam *annotationParam; 320 android::AnnotationParamVector *annotationParams; 321 android::Annotation *annotation; 322 std::vector<android::Annotation *> *annotations; 323 android::DocComment* docComment; 324 } 325 326 %% 327 328 program 329 // Don't care if license header is a doc comment or not 330 : DOC_COMMENT package imports type_declarations 331 | package imports type_declarations 332 ; 333 334 doc_comments 335 : DOC_COMMENT { $$ = $1; } 336 | doc_comments DOC_COMMENT 337 { 338 $1->merge($2); 339 $$ = $1; 340 } 341 | doc_comments '}' 342 { 343 std::cerr << "ERROR: Doc comments must preceed what they describe at " << @1 << "\n"; 344 YYERROR; 345 } 346 ; 347 348 valid_identifier 349 : IDENTIFIER 350 { 351 std::string errorMsg; 352 if (!isValidIdentifier($1, &errorMsg)) { 353 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n"; 354 YYERROR; 355 } 356 $$ = $1; 357 } 358 ; 359 360 valid_type_name 361 : IDENTIFIER 362 { 363 std::string errorMsg; 364 if (!isValidTypeName($1, &errorMsg)) { 365 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n"; 366 YYERROR; 367 } 368 $$ = $1; 369 } 370 ; 371 372 opt_annotations 373 : /* empty */ 374 { 375 $$ = new std::vector<Annotation *>; 376 } 377 | opt_annotations annotation 378 { 379 $$ = $1; 380 $$->push_back($2); 381 } 382 ; 383 384 annotation 385 : '@' IDENTIFIER opt_annotation_params 386 { 387 $$ = new Annotation($2, $3); 388 } 389 ; 390 391 opt_annotation_params 392 : /* empty */ 393 { 394 $$ = new AnnotationParamVector; 395 } 396 | '(' annotation_params ')' 397 { 398 $$ = $2; 399 } 400 ; 401 402 annotation_params 403 : annotation_param 404 { 405 $$ = new AnnotationParamVector; 406 $$->push_back($1); 407 } 408 | annotation_params ',' annotation_param 409 { 410 $$ = $1; 411 $$->push_back($3); 412 } 413 ; 414 415 annotation_param 416 : IDENTIFIER '=' annotation_string_value 417 { 418 $$ = new StringAnnotationParam($1, $3); 419 } 420 | IDENTIFIER '=' annotation_const_expr_value 421 { 422 $$ = new ConstantExpressionAnnotationParam($1, $3); 423 } 424 ; 425 426 annotation_string_value 427 : STRING_LITERAL 428 { 429 $$ = new std::vector<std::string>; 430 $$->push_back($1); 431 } 432 | '{' annotation_string_values '}' { $$ = $2; } 433 ; 434 435 annotation_string_values 436 : STRING_LITERAL 437 { 438 $$ = new std::vector<std::string>; 439 $$->push_back($1); 440 } 441 | annotation_string_values ',' STRING_LITERAL 442 { 443 $$ = $1; 444 $$->push_back($3); 445 } 446 ; 447 448 annotation_const_expr_value 449 : const_expr 450 { 451 $$ = new std::vector<ConstantExpression *>; 452 $$->push_back($1); 453 } 454 | '{' annotation_const_expr_values '}' { $$ = $2; } 455 ; 456 457 annotation_const_expr_values 458 : const_expr 459 { 460 $$ = new std::vector<ConstantExpression *>; 461 $$->push_back($1); 462 } 463 | annotation_const_expr_values ',' const_expr 464 { 465 $$ = $1; 466 $$->push_back($3); 467 } 468 ; 469 470 error_stmt 471 : error ';' 472 { 473 $$ = $1; 474 ast->addSyntaxError(); 475 } 476 ; 477 478 require_semicolon 479 : ';' 480 | /* empty */ 481 { 482 std::cerr << "ERROR: missing ; at " << @$ << "\n"; 483 ast->addSyntaxError(); 484 } 485 ; 486 487 fqname 488 : FQNAME 489 { 490 $$ = new FQName(); 491 if(!FQName::parse($1, $$)) { 492 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at " 493 << @1 494 << ".\n"; 495 YYERROR; 496 } 497 } 498 | valid_type_name 499 { 500 $$ = new FQName(); 501 if(!FQName::parse($1, $$)) { 502 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at " 503 << @1 504 << ".\n"; 505 YYERROR; 506 } 507 } 508 ; 509 510 fqtype 511 : fqname 512 { 513 $$ = new Reference<Type>(*$1, convertYYLoc(@1)); 514 } 515 | TYPE 516 { 517 $$ = new Reference<Type>($1, convertYYLoc(@1)); 518 } 519 ; 520 521 package 522 : PACKAGE FQNAME require_semicolon 523 { 524 if (!ast->setPackage($2)) { 525 std::cerr << "ERROR: Malformed package identifier '" 526 << $2 527 << "' at " 528 << @2 529 << "\n"; 530 531 YYERROR; 532 } 533 } 534 | error 535 { 536 std::cerr << "ERROR: Package statement must be at the beginning of the file (" << @1 << ")\n"; 537 $$ = $1; 538 ast->addSyntaxError(); 539 } 540 ; 541 542 import_stmt 543 : IMPORT FQNAME require_semicolon 544 { 545 if (!ast->addImport($2)) { 546 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2 547 << "\n"; 548 ast->addSyntaxError(); 549 } 550 } 551 | IMPORT valid_type_name require_semicolon 552 { 553 if (!ast->addImport($2)) { 554 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2 555 << "\n"; 556 ast->addSyntaxError(); 557 } 558 } 559 | IMPORT error_stmt 560 ; 561 562 563 imports 564 : /* empty */ 565 | imports import_stmt 566 ; 567 568 opt_extends 569 : /* empty */ { $$ = nullptr; } 570 | EXTENDS fqtype { $$ = $2; } 571 ; 572 573 interface_declarations 574 : /* empty */ 575 | interface_declarations commentable_type_declaration 576 { 577 CHECK((*scope)->isInterface()); 578 579 std::string errorMsg; 580 if ($2 != nullptr && $2->isNamedType() && 581 !isValidInterfaceField(static_cast<NamedType*>($2)->localName().c_str(), 582 &errorMsg)) { 583 std::cerr << "ERROR: " << errorMsg << " at " 584 << @2 << "\n"; 585 YYERROR; 586 } 587 } 588 | interface_declarations commentable_method_declaration 589 { 590 CHECK((*scope)->isInterface()); 591 592 std::string errorMsg; 593 if ($2 != nullptr && 594 !isValidInterfaceField($2->name().c_str(), &errorMsg)) { 595 std::cerr << "ERROR: " << errorMsg << " at " 596 << @2 << "\n"; 597 YYERROR; 598 } 599 600 if ($2 != nullptr) { 601 Interface *iface = static_cast<Interface*>(*scope); 602 if (!iface->addMethod($2)) { 603 std::cerr << "ERROR: Unable to add method '" << $2->name() 604 << "' at " << @2 << "\n"; 605 606 YYERROR; 607 } 608 } 609 // ignore if $2 is nullptr (from error recovery) 610 } 611 ; 612 613 type_declarations 614 : /* empty */ 615 | error_stmt 616 | type_declarations commentable_type_declaration 617 ; 618 619 commentable_type_declaration 620 : doc_comments type_declaration 621 { 622 $2->setDocComment($1); 623 $$ = $2; 624 } 625 | type_declaration { $$ = $1; } 626 ; 627 628 type_declaration 629 : opt_annotations type_declaration_body 630 { 631 if (!$2->isTypeDef()) { 632 CHECK($2->isScope()); 633 static_cast<Scope*>($2)->setAnnotations($1); 634 } else if (!$1->empty()) { 635 // Since typedefs are always resolved to their target it makes 636 // little sense to annotate them and have their annotations 637 // impose semantics other than their target type. 638 std::cerr << "ERROR: typedefs cannot be annotated at " << @2 639 << "\n"; 640 641 YYERROR; 642 } 643 $$ = $2; 644 } 645 ; 646 647 type_declaration_body 648 : named_struct_or_union_declaration require_semicolon 649 | named_enum_declaration require_semicolon 650 | typedef_declaration require_semicolon 651 | interface_declaration require_semicolon 652 ; 653 654 interface_declaration 655 : INTERFACE valid_type_name opt_extends 656 { 657 Reference<Type>* superType = $3; 658 bool isIBase = ast->package().package() == gIBaseFqName.package(); 659 660 if (isIBase) { 661 if (superType != nullptr) { 662 std::cerr << "ERROR: IBase must not extend any interface at " << @3 663 << "\n"; 664 665 YYERROR; 666 } 667 superType = new Reference<Type>(); 668 } else { 669 if (!ast->addImport(gIBaseFqName.string().c_str())) { 670 std::cerr << "ERROR: Unable to automatically import '" 671 << gIBaseFqName.string() 672 << "' at " << @$ 673 << "\n"; 674 YYERROR; 675 } 676 677 if (superType == nullptr) { 678 superType = new Reference<Type>(gIBaseFqName, convertYYLoc(@$)); 679 } 680 } 681 682 if ($2[0] != 'I') { 683 std::cerr << "ERROR: All interface names must start with an 'I' " 684 << "prefix at " << @2 << "\n"; 685 686 YYERROR; 687 } 688 689 if (*scope != ast->getRootScope()) { 690 std::cerr << "ERROR: All interface must declared in " 691 << "global scope at " << @2 << "\n"; 692 693 YYERROR; 694 } 695 696 Interface* iface = new Interface( 697 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), 698 *scope, *superType, ast->getFileHash()); 699 700 enterScope(ast, scope, iface); 701 } 702 '{' interface_declarations '}' 703 { 704 CHECK((*scope)->isInterface()); 705 706 Interface *iface = static_cast<Interface *>(*scope); 707 CHECK(iface->addAllReservedMethods()); 708 709 leaveScope(ast, scope); 710 ast->addScopedType(iface, *scope); 711 $$ = iface; 712 } 713 ; 714 715 typedef_declaration 716 : TYPEDEF type valid_type_name 717 { 718 // The reason we wrap the given type in a TypeDef is simply to suppress 719 // emitting any type definitions later on, since this is just an alias 720 // to a type defined elsewhere. 721 TypeDef* typeDef = new TypeDef( 722 $3, ast->makeFullName($3, *scope), convertYYLoc(@2), *scope, *$2); 723 ast->addScopedType(typeDef, *scope); 724 $$ = typeDef; 725 } 726 ; 727 728 const_expr 729 : INTEGER { 730 $$ = LiteralConstantExpression::tryParse($1); 731 732 if ($$ == nullptr) { 733 std::cerr << "ERROR: Could not parse literal: " 734 << $1 << " at " << @1 << ".\n"; 735 YYERROR; 736 } 737 } 738 | fqname 739 { 740 if(!$1->isValidValueName()) { 741 std::cerr << "ERROR: '" << $1->string() 742 << "' does not refer to an enum value at " 743 << @1 << ".\n"; 744 YYERROR; 745 } 746 747 $$ = new ReferenceConstantExpression( 748 Reference<LocalIdentifier>(*$1, convertYYLoc(@1)), $1->string()); 749 } 750 | const_expr '?' const_expr ':' const_expr 751 { 752 $$ = new TernaryConstantExpression($1, $3, $5); 753 } 754 | const_expr LOGICAL_OR const_expr { $$ = new BinaryConstantExpression($1, "||", $3); } 755 | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); } 756 | const_expr '|' const_expr { $$ = new BinaryConstantExpression($1, "|" , $3); } 757 | const_expr '^' const_expr { $$ = new BinaryConstantExpression($1, "^" , $3); } 758 | const_expr '&' const_expr { $$ = new BinaryConstantExpression($1, "&" , $3); } 759 | const_expr EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); } 760 | const_expr NEQ const_expr { $$ = new BinaryConstantExpression($1, "!=", $3); } 761 | const_expr '<' const_expr { $$ = new BinaryConstantExpression($1, "<" , $3); } 762 | const_expr '>' const_expr { $$ = new BinaryConstantExpression($1, ">" , $3); } 763 | const_expr LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); } 764 | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); } 765 | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); } 766 | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); } 767 | const_expr '+' const_expr { $$ = new BinaryConstantExpression($1, "+" , $3); } 768 | const_expr '-' const_expr { $$ = new BinaryConstantExpression($1, "-" , $3); } 769 | const_expr '*' const_expr { $$ = new BinaryConstantExpression($1, "*" , $3); } 770 | const_expr '/' const_expr { $$ = new BinaryConstantExpression($1, "/" , $3); } 771 | const_expr '%' const_expr { $$ = new BinaryConstantExpression($1, "%" , $3); } 772 | '+' const_expr %prec UNARY_PLUS { $$ = new UnaryConstantExpression("+", $2); } 773 | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); } 774 | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); } 775 | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); } 776 | '(' const_expr ')' { $$ = $2; } 777 | '(' error ')' 778 { 779 ast->addSyntaxError(); 780 // to avoid segfaults 781 $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release(); 782 } 783 ; 784 785 commentable_method_declaration 786 : doc_comments method_declaration 787 { 788 if ($2 != nullptr) $2->setDocComment($1); 789 $$ = $2; 790 } 791 | method_declaration 792 { 793 $$ = $1; 794 } 795 796 method_declaration 797 : error_stmt { $$ = nullptr; } 798 | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon 799 { 800 $$ = new Method($2 /* name */, 801 $4 /* args */, 802 new std::vector<NamedReference<Type>*> /* results */, 803 false /* oneway */, 804 $1 /* annotations */, 805 convertYYLoc(@$)); 806 } 807 | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon 808 { 809 $$ = new Method($3 /* name */, 810 $5 /* args */, 811 new std::vector<NamedReference<Type>*> /* results */, 812 true /* oneway */, 813 $1 /* annotations */, 814 convertYYLoc(@$)); 815 } 816 | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon 817 { 818 if ($8->empty()) { 819 std::cerr << "ERROR: generates clause used without result at " << @1 << "\n"; 820 ast->addSyntaxError(); 821 } 822 823 $$ = new Method($2 /* name */, 824 $4 /* args */, 825 $8 /* results */, 826 false /* oneway */, 827 $1 /* annotations */, 828 convertYYLoc(@$)); 829 } 830 ; 831 832 typed_vars 833 : /* empty */ 834 { 835 $$ = new TypedVarVector(); 836 } 837 | typed_var 838 { 839 $$ = new TypedVarVector(); 840 if (!$$->add($1)) { 841 std::cerr << "ERROR: duplicated argument or result name " 842 << $1->name() << " at " << @1 << "\n"; 843 ast->addSyntaxError(); 844 } 845 } 846 | typed_vars ',' typed_var 847 { 848 $$ = $1; 849 if (!$$->add($3)) { 850 std::cerr << "ERROR: duplicated argument or result name " 851 << $3->name() << " at " << @3 << "\n"; 852 ast->addSyntaxError(); 853 } 854 } 855 ; 856 857 typed_var 858 : type valid_identifier 859 { 860 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2)); 861 } 862 | type 863 { 864 $$ = new NamedReference<Type>("", *$1, convertYYLoc(@1)); 865 866 const std::string typeName = $$->isResolved() 867 ? $$->get()->typeName() : $$->getLookupFqName().string(); 868 869 std::cerr << "ERROR: variable of type " << typeName 870 << " is missing a variable name at " << @1 << "\n"; 871 ast->addSyntaxError(); 872 } 873 ; 874 875 876 struct_or_union_keyword 877 : STRUCT { $$ = CompoundType::STYLE_STRUCT; } 878 | UNION { $$ = CompoundType::STYLE_UNION; } 879 ; 880 881 named_struct_or_union_declaration 882 : struct_or_union_keyword valid_type_name 883 { 884 CompoundType *container = new CompoundType( 885 $1, $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *scope); 886 enterScope(ast, scope, container); 887 } 888 struct_or_union_body 889 { 890 CHECK((*scope)->isCompoundType()); 891 CompoundType *container = static_cast<CompoundType *>(*scope); 892 container->setFields($4); 893 894 leaveScope(ast, scope); 895 ast->addScopedType(container, *scope); 896 $$ = container; 897 } 898 ; 899 900 struct_or_union_body 901 : '{' field_declarations '}' { $$ = $2; } 902 ; 903 904 field_declarations 905 : /* empty */ { $$ = new std::vector<NamedReference<Type>*>; } 906 | field_declarations commentable_field_declaration 907 { 908 $$ = $1; 909 910 // Compound declaration or error 911 if ($2 != nullptr) { 912 $$->push_back($2); 913 } 914 } 915 ; 916 917 commentable_field_declaration 918 : doc_comments field_declaration 919 { 920 if ($2 != nullptr) $2->setDocComment($1); 921 $$ = $2; 922 } 923 | field_declaration { $$ = $1; } 924 925 field_declaration 926 : error_stmt { $$ = nullptr; } 927 | type_or_inplace_compound_declaration valid_identifier require_semicolon 928 { 929 CHECK((*scope)->isCompoundType()); 930 931 std::string errorMsg; 932 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT && 933 !isValidStructField($2, &errorMsg)) { 934 std::cerr << "ERROR: " << errorMsg << " at " 935 << @2 << "\n"; 936 YYERROR; 937 } 938 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2)); 939 } 940 | annotated_compound_declaration ';' 941 { 942 CHECK((*scope)->isCompoundType()); 943 944 std::string errorMsg; 945 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT && 946 $1 != nullptr && $1->isNamedType() && 947 !isValidStructField(static_cast<NamedType*>($1)->localName().c_str(), &errorMsg)) { 948 std::cerr << "ERROR: " << errorMsg << " at " 949 << @2 << "\n"; 950 YYERROR; 951 } 952 // Returns fields only 953 $$ = nullptr; 954 } 955 ; 956 957 annotated_compound_declaration 958 : opt_annotations compound_declaration 959 { 960 CHECK($2->isScope()); 961 static_cast<Scope*>($2)->setAnnotations($1); 962 $$ = $2; 963 } 964 ; 965 966 compound_declaration 967 : named_struct_or_union_declaration { $$ = $1; } 968 | named_enum_declaration { $$ = $1; } 969 ; 970 971 enum_storage_type 972 : ':' fqtype { $$ = $2; } 973 | /* empty */ { $$ = nullptr; } 974 ; 975 976 opt_comma 977 : /* empty */ 978 | ',' 979 ; 980 981 named_enum_declaration 982 : ENUM valid_type_name enum_storage_type 983 { 984 auto storageType = $3; 985 986 if (storageType == nullptr) { 987 std::cerr << "ERROR: Must explicitly specify enum storage type for " 988 << $2 << " at " << @2 << "\n"; 989 ast->addSyntaxError(); 990 storageType = new Reference<Type>( 991 new ScalarType(ScalarType::KIND_INT64, *scope), convertYYLoc(@2)); 992 } 993 994 EnumType* enumType = new EnumType( 995 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *storageType, *scope); 996 enterScope(ast, scope, enumType); 997 } 998 enum_declaration_body 999 { 1000 CHECK((*scope)->isEnum()); 1001 EnumType* enumType = static_cast<EnumType*>(*scope); 1002 1003 leaveScope(ast, scope); 1004 ast->addScopedType(enumType, *scope); 1005 $$ = enumType; 1006 } 1007 ; 1008 1009 enum_declaration_body 1010 : '{' enum_values opt_comma '}' { $$ = $2; } 1011 ; 1012 1013 commentable_enum_value 1014 : doc_comments enum_value 1015 { 1016 $2->setDocComment($1); 1017 $$ = $2; 1018 } 1019 | enum_value { $$ = $1; } 1020 ; 1021 1022 enum_value 1023 : valid_identifier 1024 { 1025 $$ = new EnumValue($1 /* name */, nullptr /* value */, convertYYLoc(@$)); 1026 } 1027 | valid_identifier '=' const_expr 1028 { 1029 $$ = new EnumValue($1 /* name */, $3 /* value */, convertYYLoc(@$)); 1030 } 1031 ; 1032 1033 enum_values 1034 : /* empty */ 1035 { /* do nothing */ } 1036 | commentable_enum_value 1037 { 1038 CHECK((*scope)->isEnum()); 1039 static_cast<EnumType *>(*scope)->addValue($1); 1040 } 1041 | enum_values ',' commentable_enum_value 1042 { 1043 CHECK((*scope)->isEnum()); 1044 static_cast<EnumType *>(*scope)->addValue($3); 1045 } 1046 | error ',' commentable_enum_value 1047 { 1048 ast->addSyntaxError(); 1049 1050 CHECK((*scope)->isEnum()); 1051 static_cast<EnumType *>(*scope)->addValue($3); 1052 } 1053 | enum_values ',' error ',' commentable_enum_value 1054 { 1055 ast->addSyntaxError(); 1056 1057 CHECK((*scope)->isEnum()); 1058 static_cast<EnumType *>(*scope)->addValue($5); 1059 } 1060 ; 1061 1062 array_type_base 1063 : fqtype { $$ = $1; } 1064 | TEMPLATED '<' type '>' 1065 { 1066 $1->setElementType(*$3); 1067 $$ = new Reference<Type>($1, convertYYLoc(@1)); 1068 } 1069 | TEMPLATED '<' TEMPLATED '<' type RSHIFT 1070 { 1071 $3->setElementType(*$5); 1072 $1->setElementType(Reference<Type>($3, convertYYLoc(@3))); 1073 $$ = new Reference<Type>($1, convertYYLoc(@1)); 1074 } 1075 ; 1076 1077 array_type 1078 : array_type_base '[' const_expr ']' 1079 { 1080 $$ = new ArrayType(*$1, $3, *scope); 1081 } 1082 | array_type '[' const_expr ']' 1083 { 1084 $$ = $1; 1085 $$->appendDimension($3); 1086 } 1087 ; 1088 1089 type 1090 : array_type_base { $$ = $1; } 1091 | array_type { $$ = new Reference<Type>($1, convertYYLoc(@1)); } 1092 | INTERFACE 1093 { 1094 // "interface" is a synonym of android.hidl.base (at) 1.0::IBase 1095 $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1)); 1096 } 1097 ; 1098 1099 type_or_inplace_compound_declaration 1100 : type { $$ = $1; } 1101 | annotated_compound_declaration 1102 { 1103 $$ = new Reference<Type>($1, convertYYLoc(@1)); 1104 } 1105 ; 1106 1107 %% 1108 1109 void yy::parser::error( 1110 const yy::parser::location_type &where, 1111 const std::string &errstr) { 1112 std::cerr << "ERROR: " << errstr << " at " << where << "\n"; 1113 } 1114 1115