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