Home | History | Annotate | Download | only in hidl
      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