blob: 35f74050c6660efbd4f49e2d3eee5c0b022f46ae [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huberc9410c72016-07-28 12:18:40 -070017%{
18
Andreas Huber3599d922016-08-09 10:42:57 -070019#include "Annotation.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070020#include "AST.h"
21#include "ArrayType.h"
22#include "CompoundType.h"
Yifan Hong52165692016-08-12 18:06:40 -070023#include "ConstantExpression.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070024#include "EnumType.h"
25#include "Interface.h"
Yifan Honga4b53d02016-10-31 17:29:10 -070026#include "Location.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070027#include "Method.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070028#include "VectorType.h"
Yifan Hongbf459bc2016-08-23 16:50:37 -070029#include "RefType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070030
31#include "hidl-gen_y.h"
32
Andreas Huber709b62d2016-09-19 11:21:18 -070033#include <android-base/logging.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080034#include <hidl-util/FQName.h>
Yifan Hong27e85db2016-11-09 15:45:52 -080035#include <hidl-util/StringHelper.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070036#include <stdio.h>
37
38using namespace android;
39
Andreas Huber0d0f9a22016-08-17 10:26:11 -070040extern int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
Andreas Huberc9410c72016-07-28 12:18:40 -070041
42#define scanner ast->scanner()
43
Yifan Honga4b53d02016-10-31 17:29:10 -070044::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
Steven Moreland0184ce32017-05-26 14:39:38 -070051bool isValidInterfaceField(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -080052 static const std::vector<std::string> reserved({
Yifan Hongf3d3c732017-05-08 17:27:54 -070053 // Injected names to C++ interfaces by auto-generated code
Yifan Hongc8934042016-11-17 17:10:52 -080054 "isRemote", "descriptor", "hidlStaticBlock", "onTransact",
Yifan Hongf3d3c732017-05-08 17:27:54 -070055 "castFrom", "Proxy", "Stub", "getService",
56
57 // Injected names to Java interfaces by auto-generated code
58 "asInterface", "castFrom", "getService", "toString",
Yifan Hongb16199d2016-12-09 14:49:46 -080059
60 // Inherited methods from IBase is detected in addMethod. Not added here
61 // because we need hidl-gen to compile IBase.
Yifan Hong27e85db2016-11-09 15:45:52 -080062
63 // Inherited names by interfaces from IInterface / IBinder
64 "onAsBinder", "asBinder", "queryLocalInterface", "getInterfaceDescriptor", "isBinderAlive",
Martijn Coenen115d4282016-12-19 05:14:04 +010065 "pingBinder", "dump", "transact", "checkSubclass", "attachObject", "findObject",
66 "detachObject", "localBinder", "remoteBinder", "mImpl",
Yifan Hongf3d3c732017-05-08 17:27:54 -070067
68 // Inherited names from HidlInstrumentor
69 "InstrumentationEvent", "configureInstrumentation", "registerInstrumentationCallbacks",
70 "isInstrumentationLib", "mInstrumentationCal1lbacks", "mEnableInstrumentation",
71 "mInstrumentationLibPackage", "mInterfaceName",
72
73 // Collide with names in BsFoo
74 "mImpl", "addOnewayTask", "mOnewayQueue",
75
76 // Inherited names from Java IHwInterface
77 "asBinder",
Yifan Hong27e85db2016-11-09 15:45:52 -080078 });
Steven Moreland0184ce32017-05-26 14:39:38 -070079 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) {
80 *errorMsg = identifier + " cannot be a name inside an interface";
Yifan Hong27e85db2016-11-09 15:45:52 -080081 return false;
82 }
83 return true;
84}
85
Steven Moreland0184ce32017-05-26 14:39:38 -070086bool isValidStructField(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -080087 static const std::vector<std::string> reserved({
88 // Injected names to structs and unions by auto-generated code
89 "readEmbeddedFromParcel", "writeEmbeddedToParcel", "readVectorFromParcel",
90 "writeVectorToParcel", "writeEmbeddedToBlob",
91 });
Steven Moreland0184ce32017-05-26 14:39:38 -070092 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) {
93 *errorMsg = identifier + " cannot be a name inside an struct or union";
Yifan Hong27e85db2016-11-09 15:45:52 -080094 return false;
95 }
96 return true;
97}
98
Steven Moreland0184ce32017-05-26 14:39:38 -070099bool isValidIdentifier(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -0800100 static const std::vector<std::string> keywords({
101 "uint8_t", "uint16_t", "uint32_t", "uint64_t",
102 "int8_t", "int16_t", "int32_t", "int64_t", "bool", "float", "double",
103 "interface", "struct", "union", "string", "vec", "enum", "ref", "handle",
104 "package", "import", "typedef", "generates", "oneway", "extends",
Hridya Valsarajua32bde82016-12-27 11:47:46 -0800105 "fmq_sync", "fmq_unsync",
Yifan Hong27e85db2016-11-09 15:45:52 -0800106 });
107 static const std::vector<std::string> cppKeywords({
108 "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit",
109 "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch",
110 "char", "char16_t", "char32_t", "class", "compl", "concept", "const", "constexpr",
111 "const_cast", "continue", "decltype", "default", "delete", "do", "double",
112 "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float",
113 "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable",
114 "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
115 "private", "protected", "public", "register", "reinterpret_cast", "requires", "return",
116 "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct",
117 "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try",
118 "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
119 "volatile", "wchar_t", "while", "xor", "xor_eq",
120 });
121 static const std::vector<std::string> javaKeywords({
122 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package",
123 "synchronized", "boolean", "do", "if", "private", "this", "break", "double",
124 "implements", "protected", "throw", "byte", "else", "import", "public", "throws",
125 "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int",
126 "short", "try", "char", "final", "interface", "static", "void", "class", "finally",
127 "long", "strictfp", "volatile", "const", "float", "native", "super", "while",
128 });
129 static const std::vector<std::string> cppCollide({
130 "size_t", "offsetof",
Yifan Hong27e85db2016-11-09 15:45:52 -0800131 });
132
133 // errors
Steven Moreland0184ce32017-05-26 14:39:38 -0700134 if (std::find(keywords.begin(), keywords.end(), identifier) != keywords.end()) {
135 *errorMsg = identifier + " is a HIDL keyword "
Yifan Hong27e85db2016-11-09 15:45:52 -0800136 "and is therefore not a valid identifier";
137 return false;
138 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700139 if (std::find(cppKeywords.begin(), cppKeywords.end(), identifier) != cppKeywords.end()) {
140 *errorMsg = identifier + " is a C++ keyword "
Yifan Hong27e85db2016-11-09 15:45:52 -0800141 "and is therefore not a valid identifier";
142 return false;
143 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700144 if (std::find(javaKeywords.begin(), javaKeywords.end(), identifier) != javaKeywords.end()) {
145 *errorMsg = identifier + " is a Java keyword "
Yifan Hong27e85db2016-11-09 15:45:52 -0800146 "and is therefore not a valid identifier";
147 return false;
148 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700149 if (std::find(cppCollide.begin(), cppCollide.end(), identifier) != cppCollide.end()) {
150 *errorMsg = identifier + " collides with reserved names in C++ code "
Yifan Hong27e85db2016-11-09 15:45:52 -0800151 "and is therefore not a valid identifier";
152 return false;
153 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700154 if (StringHelper::StartsWith(identifier, "_hidl_")) {
155 *errorMsg = identifier + " starts with _hidl_ "
Yifan Hong27e85db2016-11-09 15:45:52 -0800156 "and is therefore not a valid identifier";
157 return false;
158 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700159 if (StringHelper::StartsWith(identifier, "hidl_")) {
160 *errorMsg = identifier + " starts with hidl_ "
Yifan Hongf3d3c732017-05-08 17:27:54 -0700161 "and is therefore not a valid identifier";
162 return false;
163 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700164 if (StringHelper::EndsWith(identifier, "_cb")) {
165 *errorMsg = identifier + " ends with _cb "
Yifan Hong27e85db2016-11-09 15:45:52 -0800166 "and is therefore not a valid identifier";
167 return false;
168 }
169
Yifan Hongf3d3c732017-05-08 17:27:54 -0700170 return true;
171}
172
173// Return true if identifier is an acceptable name for an UDT.
Steven Moreland0184ce32017-05-26 14:39:38 -0700174bool isValidTypeName(const std::string& identifier, std::string *errorMsg) {
Yifan Hongf3d3c732017-05-08 17:27:54 -0700175 if (!isValidIdentifier(identifier, errorMsg)) {
176 return false;
Yifan Hong27e85db2016-11-09 15:45:52 -0800177 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700178
Steven Moreland0184ce32017-05-26 14:39:38 -0700179 if (identifier == "toString") {
180 *errorMsg = identifier + " is not a valid type name";
Yifan Hongf3d3c732017-05-08 17:27:54 -0700181 return false;
182 }
183
Yifan Hong27e85db2016-11-09 15:45:52 -0800184 return true;
185}
Yifan Honga4b53d02016-10-31 17:29:10 -0700186
Andreas Huberc9410c72016-07-28 12:18:40 -0700187%}
188
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700189%initial-action {
190 // Initialize the initial location.
191 @$.begin.filename = @$.end.filename =
192 const_cast<std::string *>(&ast->getFilename());
193}
194
Andreas Huberc9410c72016-07-28 12:18:40 -0700195%parse-param { android::AST *ast }
196%lex-param { void *scanner }
197%pure-parser
Steven Moreland4ab9b792016-09-26 14:14:07 -0700198%glr-parser
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700199%skeleton "glr.cc"
Andreas Huberc9410c72016-07-28 12:18:40 -0700200
Steven Moreland4ab9b792016-09-26 14:14:07 -0700201%expect-rr 0
Steven Moreland0184ce32017-05-26 14:39:38 -0700202%error-verbose
Steven Moreland4ab9b792016-09-26 14:14:07 -0700203
Steven Moreland0184ce32017-05-26 14:39:38 -0700204%token<str> ENUM "keyword `enum`"
205%token<str> EXTENDS "keyword `extends`"
206%token<str> FQNAME "fully-qualified name"
207%token<str> GENERATES "keyword `generates`"
208%token<str> IDENTIFIER "identifier"
209%token<str> IMPORT "keyword `import`"
210%token<str> INTEGER "integer value"
211%token<str> FLOAT "float value"
212%token<str> INTERFACE "keyword `interface`"
213%token<str> PACKAGE "keyword `package`"
214%token<type> TYPE "type"
215%token<str> STRUCT "keyword `struct`"
216%token<str> STRING_LITERAL "string literal"
217%token<str> TYPEDEF "keyword `typedef`"
218%token<str> UNION "keyword `union`"
219%token<templatedType> TEMPLATED "templated type"
220%token<void> ONEWAY "keyword `oneway`"
Andreas Huberc9410c72016-07-28 12:18:40 -0700221
Yifan Hong52165692016-08-12 18:06:40 -0700222/* Operator precedence and associativity, as per
223 * http://en.cppreference.com/w/cpp/language/operator_precedence */
224/* Precedence level 15 ternary operator */
225%right '?' ':'
226/* Precedence level 13 - 14, LTR, logical operators*/
227%left LOGICAL_OR
228%left LOGICAL_AND
229/* Precedence level 10 - 12, LTR, bitwise operators*/
230%left '|'
231%left '^'
232%left '&'
233/* Precedence level 9, LTR */
234%left EQUALITY NEQ
235/* Precedence level 8, LTR */
236%left '<' '>' LEQ GEQ
237/* Precedence level 7, LTR */
238%left LSHIFT RSHIFT
239/* Precedence level 6, LTR */
240%left '+' '-'
241/* Precedence level 5, LTR */
242%left '*' '/' '%'
243/* Precedence level 3, RTL; but we have to use %left here */
244%left UNARY_MINUS UNARY_PLUS '!' '~'
245
Steven Moreland5f809632017-05-17 13:24:36 -0700246%type<str> error_stmt error
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700247%type<str> package
Yifan Hongae16eed2016-09-23 13:25:25 -0700248%type<fqName> fqname
249%type<type> fqtype
Yifan Hongf3d3c732017-05-08 17:27:54 -0700250%type<str> valid_identifier valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700251
Steven Moreland1c71fd52016-11-29 14:03:33 -0800252%type<type> type enum_storage_type
Yifan Hongbd33e382016-11-02 13:30:17 -0700253%type<type> array_type_base
254%type<arrayType> array_type
Andreas Huberc9410c72016-07-28 12:18:40 -0700255%type<type> opt_extends
Yifan Hong27e85db2016-11-09 15:45:52 -0800256%type<type> type_declaration type_declaration_body interface_declaration typedef_declaration
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700257%type<type> named_struct_or_union_declaration named_enum_declaration
258%type<type> compound_declaration annotated_compound_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700259
260%type<field> field_declaration
261%type<fields> field_declarations struct_or_union_body
Yifan Hong52165692016-08-12 18:06:40 -0700262%type<constantExpression> const_expr
Andreas Huberc9410c72016-07-28 12:18:40 -0700263%type<enumValue> enum_value
Yifan Hongf24fa852016-09-23 11:03:15 -0700264%type<enumValues> enum_values enum_declaration_body
Andreas Huberc9410c72016-07-28 12:18:40 -0700265%type<typedVars> typed_vars
266%type<typedVar> typed_var
267%type<method> method_declaration
268%type<compoundStyle> struct_or_union_keyword
Yifan Hongf24fa852016-09-23 11:03:15 -0700269%type<stringVec> annotation_string_values annotation_string_value
270%type<constExprVec> annotation_const_expr_values annotation_const_expr_value
Andreas Huber3599d922016-08-09 10:42:57 -0700271%type<annotationParam> annotation_param
272%type<annotationParams> opt_annotation_params annotation_params
273%type<annotation> annotation
274%type<annotations> opt_annotations
Andreas Huberc9410c72016-07-28 12:18:40 -0700275
276%start program
277
278%union {
279 const char *str;
280 android::Type *type;
Yifan Hongbd33e382016-11-02 13:30:17 -0700281 android::ArrayType *arrayType;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700282 android::TemplatedType *templatedType;
Yifan Hongae16eed2016-09-23 13:25:25 -0700283 android::FQName *fqName;
Andreas Huberc9410c72016-07-28 12:18:40 -0700284 android::CompoundType *compoundType;
285 android::CompoundField *field;
Andreas Huber881227d2016-08-02 14:20:21 -0700286 std::vector<android::CompoundField *> *fields;
Andreas Huberc9410c72016-07-28 12:18:40 -0700287 android::EnumValue *enumValue;
Yifan Hong52165692016-08-12 18:06:40 -0700288 android::ConstantExpression *constantExpression;
Andreas Huber881227d2016-08-02 14:20:21 -0700289 std::vector<android::EnumValue *> *enumValues;
Andreas Huberc9410c72016-07-28 12:18:40 -0700290 android::TypedVar *typedVar;
Yifan Hong7763ab32016-12-13 17:42:11 -0800291 android::TypedVarVector *typedVars;
Andreas Huberc9410c72016-07-28 12:18:40 -0700292 android::Method *method;
293 android::CompoundType::Style compoundStyle;
Andreas Huber3599d922016-08-09 10:42:57 -0700294 std::vector<std::string> *stringVec;
Yifan Hongf24fa852016-09-23 11:03:15 -0700295 std::vector<android::ConstantExpression *> *constExprVec;
Steven Morelandd537ab02016-09-12 10:32:01 -0700296 android::AnnotationParam *annotationParam;
297 android::AnnotationParamVector *annotationParams;
Andreas Huber3599d922016-08-09 10:42:57 -0700298 android::Annotation *annotation;
Steven Morelandd537ab02016-09-12 10:32:01 -0700299 std::vector<android::Annotation *> *annotations;
Andreas Huberc9410c72016-07-28 12:18:40 -0700300}
301
302%%
303
Steven Moreland2ee84322017-05-17 13:16:33 -0700304program
Steven Moreland5f809632017-05-17 13:24:36 -0700305 : package
Steven Moreland2ee84322017-05-17 13:16:33 -0700306 imports
Steven Moreland0184ce32017-05-26 14:39:38 -0700307 type_declarations
Steven Moreland2ee84322017-05-17 13:16:33 -0700308 ;
309
Yifan Hong27e85db2016-11-09 15:45:52 -0800310valid_identifier
311 : IDENTIFIER
312 {
313 std::string errorMsg;
314 if (!isValidIdentifier($1, &errorMsg)) {
315 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
316 YYERROR;
317 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700318 $$ = $1;
319 }
320 ;
321
322valid_type_name
323 : IDENTIFIER
324 {
325 std::string errorMsg;
326 if (!isValidTypeName($1, &errorMsg)) {
327 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
328 YYERROR;
Yifan Hong27e85db2016-11-09 15:45:52 -0800329 }
330 $$ = $1;
331 }
332 ;
333
Andreas Huber3599d922016-08-09 10:42:57 -0700334opt_annotations
335 : /* empty */
336 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700337 $$ = new std::vector<Annotation *>;
Andreas Huber3599d922016-08-09 10:42:57 -0700338 }
339 | opt_annotations annotation
340 {
341 $$ = $1;
Steven Morelandd537ab02016-09-12 10:32:01 -0700342 $$->push_back($2);
Andreas Huber3599d922016-08-09 10:42:57 -0700343 }
344 ;
345
346annotation
347 : '@' IDENTIFIER opt_annotation_params
348 {
349 $$ = new Annotation($2, $3);
350 }
351 ;
352
353opt_annotation_params
354 : /* empty */
355 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700356 $$ = new AnnotationParamVector;
Andreas Huber3599d922016-08-09 10:42:57 -0700357 }
358 | '(' annotation_params ')'
359 {
360 $$ = $2;
361 }
362 ;
363
364annotation_params
365 : annotation_param
366 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700367 $$ = new AnnotationParamVector;
368 $$->push_back($1);
Andreas Huber3599d922016-08-09 10:42:57 -0700369 }
370 | annotation_params ',' annotation_param
371 {
372 $$ = $1;
Steven Morelandd537ab02016-09-12 10:32:01 -0700373 $$->push_back($3);
Andreas Huber3599d922016-08-09 10:42:57 -0700374 }
375 ;
376
377annotation_param
Yifan Hongf24fa852016-09-23 11:03:15 -0700378 : IDENTIFIER '=' annotation_string_value
379 {
380 $$ = new AnnotationParam($1, $3);
381 }
382 | IDENTIFIER '=' annotation_const_expr_value
Andreas Huber3599d922016-08-09 10:42:57 -0700383 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700384 $$ = new AnnotationParam($1, $3);
Andreas Huber3599d922016-08-09 10:42:57 -0700385 }
386 ;
387
Yifan Hongf24fa852016-09-23 11:03:15 -0700388annotation_string_value
Andreas Huber3599d922016-08-09 10:42:57 -0700389 : STRING_LITERAL
390 {
391 $$ = new std::vector<std::string>;
392 $$->push_back($1);
393 }
394 | '{' annotation_string_values '}' { $$ = $2; }
395 ;
396
397annotation_string_values
398 : STRING_LITERAL
399 {
400 $$ = new std::vector<std::string>;
401 $$->push_back($1);
402 }
403 | annotation_string_values ',' STRING_LITERAL
404 {
405 $$ = $1;
406 $$->push_back($3);
407 }
408 ;
409
Yifan Hongf24fa852016-09-23 11:03:15 -0700410annotation_const_expr_value
411 : const_expr
412 {
413 $$ = new std::vector<ConstantExpression *>;
414 $$->push_back($1);
415 }
416 | '{' annotation_const_expr_values '}' { $$ = $2; }
417 ;
418
419annotation_const_expr_values
420 : const_expr
421 {
422 $$ = new std::vector<ConstantExpression *>;
423 $$->push_back($1);
424 }
425 | annotation_const_expr_values ',' const_expr
426 {
427 $$ = $1;
428 $$->push_back($3);
429 }
430 ;
431
Yifan Hongbe627b32016-10-28 18:38:56 -0700432error_stmt
433 : error ';'
434 {
435 $$ = $1;
436 ast->addSyntaxError();
Yifan Hongbe627b32016-10-28 18:38:56 -0700437 }
438 ;
439
Yifan Hongbe627b32016-10-28 18:38:56 -0700440require_semicolon
441 : ';'
442 | /* empty */
443 {
444 std::cerr << "ERROR: missing ; at " << @$ << "\n";
445 ast->addSyntaxError();
446 }
447 ;
448
Andreas Huber84f89de2016-07-28 15:39:51 -0700449fqname
450 : FQNAME
451 {
Yifan Hongae16eed2016-09-23 13:25:25 -0700452 $$ = new FQName($1);
453 if(!$$->isValid()) {
454 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at "
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700455 << @1
Yifan Hongae16eed2016-09-23 13:25:25 -0700456 << ".\n";
Andreas Huber84f89de2016-07-28 15:39:51 -0700457 YYERROR;
458 }
459 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700460 | valid_type_name
Andreas Huber84f89de2016-07-28 15:39:51 -0700461 {
Yifan Hongae16eed2016-09-23 13:25:25 -0700462 $$ = new FQName($1);
463 if(!$$->isValid()) {
464 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at "
465 << @1
466 << ".\n";
467 YYERROR;
468 }
469 }
470 ;
471
472fqtype
473 : fqname
474 {
475 $$ = ast->lookupType(*($1));
Andreas Huber84f89de2016-07-28 15:39:51 -0700476 if ($$ == NULL) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700477 std::cerr << "ERROR: Failed to lookup type '" << $1->string() << "' at "
478 << @1
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700479 << "\n";
480
Andreas Huber84f89de2016-07-28 15:39:51 -0700481 YYERROR;
482 }
483 }
Hridya Valsarajucd91bf62016-10-25 12:41:04 -0700484 | TYPE
Andreas Huber84f89de2016-07-28 15:39:51 -0700485 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700486
487package
Yifan Hongbe627b32016-10-28 18:38:56 -0700488 : PACKAGE FQNAME require_semicolon
Andreas Hubereb1081f2016-07-28 13:13:24 -0700489 {
Andreas Huber84f89de2016-07-28 15:39:51 -0700490 if (!ast->setPackage($2)) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700491 std::cerr << "ERROR: Malformed package identifier '"
492 << $2
493 << "' at "
494 << @2
495 << "\n";
496
Andreas Huber84f89de2016-07-28 15:39:51 -0700497 YYERROR;
498 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700499 }
Steven Moreland5f809632017-05-17 13:24:36 -0700500 | error
501 {
502 std::cerr << "ERROR: Package statement must be at the beginning of the file (" << @1 << ")\n";
503 $$ = $1;
504 ast->addSyntaxError();
505 }
506 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700507
Yifan Hongbe627b32016-10-28 18:38:56 -0700508import_stmt
509 : IMPORT FQNAME require_semicolon
510 {
511 if (!ast->addImport($2)) {
512 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
513 << "\n";
514 ast->addSyntaxError();
515 }
516 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700517 | IMPORT valid_type_name require_semicolon
Yifan Hongbe627b32016-10-28 18:38:56 -0700518 {
519 if (!ast->addImport($2)) {
520 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
521 << "\n";
522 ast->addSyntaxError();
523 }
524 }
525 | IMPORT error_stmt
526 ;
527
528
Andreas Huberc9410c72016-07-28 12:18:40 -0700529imports
530 : /* empty */
Yifan Hongbe627b32016-10-28 18:38:56 -0700531 | imports import_stmt
Andreas Huberc9410c72016-07-28 12:18:40 -0700532 ;
533
534opt_extends
535 : /* empty */ { $$ = NULL; }
Yifan Hongae16eed2016-09-23 13:25:25 -0700536 | EXTENDS fqtype { $$ = $2; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700537
Andreas Huberc9410c72016-07-28 12:18:40 -0700538interface_declarations
539 : /* empty */
540 | interface_declarations type_declaration
Yifan Hong27e85db2016-11-09 15:45:52 -0800541 {
542 std::string errorMsg;
543 if ($2 != nullptr &&
544 $2->isNamedType() &&
545 !isValidInterfaceField(static_cast<NamedType *>($2)->localName().c_str(),
546 &errorMsg)) {
547 std::cerr << "ERROR: " << errorMsg << " at "
548 << @2 << "\n";
549 YYERROR;
550 }
551 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700552 | interface_declarations method_declaration
553 {
Yifan Hong27e85db2016-11-09 15:45:52 -0800554 std::string errorMsg;
555 if ($2 != nullptr &&
556 !isValidInterfaceField($2->name().c_str(), &errorMsg)) {
557 std::cerr << "ERROR: " << errorMsg << " at "
558 << @2 << "\n";
559 YYERROR;
560 }
561
Yifan Hongbe627b32016-10-28 18:38:56 -0700562 if ($2 != nullptr) {
563 if (!ast->scope()->isInterface()) {
564 std::cerr << "ERROR: unknown error in interface declaration at "
565 << @2 << "\n";
566 YYERROR;
567 }
Steven Moreland14ee6742016-10-18 12:58:28 -0700568
Yifan Hongbe627b32016-10-28 18:38:56 -0700569 Interface *iface = static_cast<Interface *>(ast->scope());
570 if (!iface->addMethod($2)) {
571 std::cerr << "ERROR: Unable to add method '" << $2->name()
572 << "' at " << @2 << "\n";
573
574 YYERROR;
575 }
Steven Moreland14ee6742016-10-18 12:58:28 -0700576 }
Yifan Hongbe627b32016-10-28 18:38:56 -0700577 // ignore if $2 is nullptr (from error recovery)
Andreas Huberc9410c72016-07-28 12:18:40 -0700578 }
579 ;
580
581type_declarations
Andreas Hubera2723d22016-07-29 15:36:07 -0700582 : /* empty */
Yifan Hongbe627b32016-10-28 18:38:56 -0700583 | error_stmt
Andreas Huberc9410c72016-07-28 12:18:40 -0700584 | type_declarations type_declaration
585 ;
586
587type_declaration
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700588 : opt_annotations type_declaration_body
589 {
590 if ($2 != nullptr) {
591 $2->setAnnotations($1);
592 } else if (!$1->empty()) {
593 // Since typedefs are always resolved to their target it makes
594 // little sense to annotate them and have their annotations
595 // impose semantics other than their target type.
596 std::cerr << "ERROR: typedefs cannot be annotated. at " << @2
597 << "\n";
598
599 YYERROR;
600 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800601 $$ = $2;
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700602 }
603 ;
604
605type_declaration_body
Yifan Hongbe627b32016-10-28 18:38:56 -0700606 : named_struct_or_union_declaration require_semicolon
607 | named_enum_declaration require_semicolon
608 | typedef_declaration require_semicolon
609 | interface_declaration require_semicolon
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700610 ;
611
612interface_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700613 : INTERFACE valid_type_name opt_extends
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700614 {
Yifan Hongc8934042016-11-17 17:10:52 -0800615 Type *parent = $3;
616
617 if (ast->package() != gIBasePackageFqName) {
618 if (!ast->addImport(gIBaseFqName.string().c_str())) {
619 std::cerr << "ERROR: Unable to automatically import '"
620 << gIBaseFqName.string()
621 << "' at " << @$
622 << "\n";
623 YYERROR;
624 }
625 if (parent == nullptr) {
626 parent = ast->lookupType(gIBaseFqName);
627 }
628 }
629
630 if (parent != NULL && !parent->isInterface()) {
Yifan Hongbe627b32016-10-28 18:38:56 -0700631 std::cerr << "ERROR: You can only extend interfaces. at " << @3
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700632 << "\n";
633
634 YYERROR;
635 }
636
637 if ($2[0] != 'I') {
638 std::cerr << "ERROR: All interface names must start with an 'I' "
639 << "prefix. at " << @2 << "\n";
640
641 YYERROR;
642 }
643
Yifan Hongc8934042016-11-17 17:10:52 -0800644 Interface *iface = new Interface($2, convertYYLoc(@2), static_cast<Interface *>(parent));
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700645
646 // Register interface immediately so it can be referenced inside
647 // definition.
648 std::string errorMsg;
649 if (!ast->addScopedType(iface, &errorMsg)) {
650 std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
651 YYERROR;
652 }
653
654 ast->enterScope(iface);
655 }
656 '{' interface_declarations '}'
657 {
Yifan Hongbe627b32016-10-28 18:38:56 -0700658 if (!ast->scope()->isInterface()) {
659 std::cerr << "ERROR: unknown error in interface declaration at "
660 << @5 << "\n";
661 YYERROR;
662 }
663
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700664 Interface *iface = static_cast<Interface *>(ast->scope());
Yifan Hongffa91392017-01-31 13:41:23 -0800665 if (!iface->addAllReservedMethods()) {
666 std::cerr << "ERROR: unknown error in adding reserved methods at "
667 << @5 << "\n";
668 YYERROR;
669 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700670
671 ast->leaveScope();
672
673 $$ = iface;
674 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700675 ;
676
677typedef_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700678 : TYPEDEF type valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700679 {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700680 std::string errorMsg;
Yifan Honga4b53d02016-10-31 17:29:10 -0700681 if (!ast->addTypeDef($3, $2, convertYYLoc(@3), &errorMsg)) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700682 std::cerr << "ERROR: " << errorMsg << " at " << @3 << "\n";
Andreas Huber5a545442016-08-03 10:44:56 -0700683 YYERROR;
684 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700685
686 $$ = nullptr;
Andreas Huberc9410c72016-07-28 12:18:40 -0700687 }
688 ;
689
Yifan Hong52165692016-08-12 18:06:40 -0700690const_expr
Yifan Hongf24fa852016-09-23 11:03:15 -0700691 : INTEGER { $$ = new ConstantExpression($1); }
Yifan Hongb44a6c82016-09-22 15:50:18 -0700692 | fqname
693 {
Yifan Hongf24fa852016-09-23 11:03:15 -0700694 if(!$1->isValidValueName()) {
695 std::cerr << "ERROR: '" << $1->string()
696 << "' does not refer to an enum value at "
697 << @1 << ".\n";
698 YYERROR;
699 }
700 if($1->isIdentifier()) {
701 std::string identifier = $1->name();
702 LocalIdentifier *iden = ast->scope()->lookupIdentifier(identifier);
703 if(!iden) {
Yifan Hongbe627b32016-10-28 18:38:56 -0700704 std::cerr << "ERROR: identifier " << $1->string()
705 << " could not be found at " << @1 << ".\n";
Yifan Hongf24fa852016-09-23 11:03:15 -0700706 YYERROR;
707 }
708 if(!iden->isEnumValue()) {
Yifan Hongbe627b32016-10-28 18:38:56 -0700709 std::cerr << "ERROR: identifier " << $1->string()
710 << " is not an enum value at " << @1 << ".\n";
Yifan Hongf24fa852016-09-23 11:03:15 -0700711 YYERROR;
712 }
713 $$ = new ConstantExpression(
714 *(static_cast<EnumValue *>(iden)->constExpr()), $1->string());
715 } else {
716 std::string errorMsg;
717 EnumValue *v = ast->lookupEnumValue(*($1), &errorMsg);
718 if(v == nullptr) {
719 std::cerr << "ERROR: " << errorMsg << " at " << @1 << ".\n";
720 YYERROR;
721 }
722 $$ = new ConstantExpression(*(v->constExpr()), $1->string());
723 }
Yifan Hongb44a6c82016-09-22 15:50:18 -0700724 }
Yifan Hong52165692016-08-12 18:06:40 -0700725 | const_expr '?' const_expr ':' const_expr
726 {
Yifan Hongb44a6c82016-09-22 15:50:18 -0700727 $$ = new ConstantExpression($1, $3, $5);
Yifan Hong52165692016-08-12 18:06:40 -0700728 }
729 | const_expr LOGICAL_OR const_expr { $$ = new ConstantExpression($1, "||", $3); }
730 | const_expr LOGICAL_AND const_expr { $$ = new ConstantExpression($1, "&&", $3); }
731 | const_expr '|' const_expr { $$ = new ConstantExpression($1, "|" , $3); }
732 | const_expr '^' const_expr { $$ = new ConstantExpression($1, "^" , $3); }
733 | const_expr '&' const_expr { $$ = new ConstantExpression($1, "&" , $3); }
734 | const_expr EQUALITY const_expr { $$ = new ConstantExpression($1, "==", $3); }
735 | const_expr NEQ const_expr { $$ = new ConstantExpression($1, "!=", $3); }
736 | const_expr '<' const_expr { $$ = new ConstantExpression($1, "<" , $3); }
737 | const_expr '>' const_expr { $$ = new ConstantExpression($1, ">" , $3); }
738 | const_expr LEQ const_expr { $$ = new ConstantExpression($1, "<=", $3); }
739 | const_expr GEQ const_expr { $$ = new ConstantExpression($1, ">=", $3); }
740 | const_expr LSHIFT const_expr { $$ = new ConstantExpression($1, "<<", $3); }
741 | const_expr RSHIFT const_expr { $$ = new ConstantExpression($1, ">>", $3); }
742 | const_expr '+' const_expr { $$ = new ConstantExpression($1, "+" , $3); }
743 | const_expr '-' const_expr { $$ = new ConstantExpression($1, "-" , $3); }
744 | const_expr '*' const_expr { $$ = new ConstantExpression($1, "*" , $3); }
745 | const_expr '/' const_expr { $$ = new ConstantExpression($1, "/" , $3); }
746 | const_expr '%' const_expr { $$ = new ConstantExpression($1, "%" , $3); }
747 | '+' const_expr %prec UNARY_PLUS { $$ = new ConstantExpression("+", $2); }
748 | '-' const_expr %prec UNARY_MINUS { $$ = new ConstantExpression("-", $2); }
749 | '!' const_expr { $$ = new ConstantExpression("!", $2); }
750 | '~' const_expr { $$ = new ConstantExpression("~", $2); }
751 | '(' const_expr ')' { $$ = $2; }
Yifan Hongbe627b32016-10-28 18:38:56 -0700752 | '(' error ')'
753 {
754 ast->addSyntaxError();
755 // to avoid segfaults
756 $$ = new ConstantExpression(ConstantExpression::Zero(ScalarType::KIND_INT32));
757 }
Yifan Hong52165692016-08-12 18:06:40 -0700758 ;
759
Andreas Huberc9410c72016-07-28 12:18:40 -0700760method_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700761 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800762 | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700763 {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700764 $$ = new Method($2, $4, new std::vector<TypedVar *>, false, $1);
765 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800766 | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon
Iliyan Malchev639bff82016-08-13 14:24:11 -0700767 {
768 $$ = new Method($3, $5, new std::vector<TypedVar *>, true, $1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700769 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800770 | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700771 {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700772 $$ = new Method($2, $4, $8, false, $1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700773 }
774 ;
775
776typed_vars
777 : /* empty */
778 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800779 $$ = new TypedVarVector();
Andreas Huberc9410c72016-07-28 12:18:40 -0700780 }
781 | typed_var
782 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800783 $$ = new TypedVarVector();
784 if (!$$->add($1)) {
785 std::cerr << "ERROR: duplicated argument or result name "
786 << $1->name() << " at " << @1 << "\n";
787 ast->addSyntaxError();
788 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700789 }
790 | typed_vars ',' typed_var
791 {
792 $$ = $1;
Yifan Hong7763ab32016-12-13 17:42:11 -0800793 if (!$$->add($3)) {
794 std::cerr << "ERROR: duplicated argument or result name "
795 << $3->name() << " at " << @3 << "\n";
796 ast->addSyntaxError();
797 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700798 }
799 ;
800
Yifan Hong27e85db2016-11-09 15:45:52 -0800801typed_var : type valid_identifier { $$ = new TypedVar($2, $1); }
Andreas Huberc9410c72016-07-28 12:18:40 -0700802 ;
803
804
805struct_or_union_keyword
806 : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
807 | UNION { $$ = CompoundType::STYLE_UNION; }
808 ;
809
810named_struct_or_union_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700811 : struct_or_union_keyword valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700812 {
Yifan Honga4b53d02016-10-31 17:29:10 -0700813 CompoundType *container = new CompoundType($1, $2, convertYYLoc(@2));
Andreas Huberc9410c72016-07-28 12:18:40 -0700814 ast->enterScope(container);
815 }
816 struct_or_union_body
817 {
Yifan Hongbe627b32016-10-28 18:38:56 -0700818 if (!ast->scope()->isCompoundType()) {
819 std::cerr << "ERROR: unknown error in struct or union declaration at "
820 << @4 << "\n";
821 YYERROR;
822 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700823 CompoundType *container = static_cast<CompoundType *>(ast->scope());
824
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700825 std::string errorMsg;
826 if (!container->setFields($4, &errorMsg)) {
827 std::cerr << "ERROR: " << errorMsg << " at " << @4 << "\n";
Andreas Huber5a545442016-08-03 10:44:56 -0700828 YYERROR;
829 }
830
Andreas Huberc9410c72016-07-28 12:18:40 -0700831 ast->leaveScope();
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700832
Andreas Huber9ed827c2016-08-22 12:31:13 -0700833 if (!ast->addScopedType(container, &errorMsg)) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700834 std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
Andreas Huber5a545442016-08-03 10:44:56 -0700835 YYERROR;
836 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700837
838 $$ = container;
Andreas Huberc9410c72016-07-28 12:18:40 -0700839 }
840 ;
841
Andreas Huberc9410c72016-07-28 12:18:40 -0700842struct_or_union_body
843 : '{' field_declarations '}' { $$ = $2; }
844 ;
845
846field_declarations
Andreas Huber881227d2016-08-02 14:20:21 -0700847 : /* empty */ { $$ = new std::vector<CompoundField *>; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700848 | field_declarations field_declaration
849 {
850 $$ = $1;
851
852 if ($2 != NULL) {
853 $$->push_back($2);
854 }
855 }
856 ;
857
858field_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700859 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800860 | type valid_identifier require_semicolon
861 {
862 std::string errorMsg;
863 if (ast->scope()->isCompoundType() &&
864 static_cast<CompoundType *>(ast->scope())->style() == CompoundType::STYLE_STRUCT &&
865 !isValidStructField($2, &errorMsg)) {
866 std::cerr << "ERROR: " << errorMsg << " at "
867 << @2 << "\n";
868 YYERROR;
869 }
870 $$ = new CompoundField($2, $1);
871 }
872 | annotated_compound_declaration ';'
873 {
874 std::string errorMsg;
875 if (ast->scope()->isCompoundType() &&
876 static_cast<CompoundType *>(ast->scope())->style() == CompoundType::STYLE_STRUCT &&
877 $1 != nullptr &&
878 $1->isNamedType() &&
879 !isValidStructField(static_cast<NamedType *>($1)->localName().c_str(), &errorMsg)) {
880 std::cerr << "ERROR: " << errorMsg << " at "
881 << @2 << "\n";
882 YYERROR;
883 }
884 $$ = NULL;
885 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700886 ;
887
888annotated_compound_declaration
889 : opt_annotations compound_declaration
890 {
891 $2->setAnnotations($1);
892 $$ = $2;
893 }
894 ;
895
896compound_declaration
Yifan Honga2855012016-10-11 13:36:54 -0700897 : named_struct_or_union_declaration { $$ = $1; }
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700898 | named_enum_declaration { $$ = $1; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700899 ;
900
Steven Moreland1c71fd52016-11-29 14:03:33 -0800901enum_storage_type
902 : ':' fqtype
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700903 {
904 $$ = $2;
905
906 if ($$ != NULL && !$$->isValidEnumStorageType()) {
Steven Moreland3effa832017-06-16 16:17:41 -0700907 std::cerr << "ERROR: Invalid enum storage type ("
908 << $2->typeName()
909 << ") specified. at "
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700910 << @2 << "\n";
911
Yifan Hongbe627b32016-10-28 18:38:56 -0700912 YYERROR;
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700913 }
914 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700915 ;
916
917opt_comma
918 : /* empty */
919 | ','
920 ;
921
922named_enum_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700923 : ENUM valid_type_name enum_storage_type
Andreas Huberc9410c72016-07-28 12:18:40 -0700924 {
Yifan Honga4b53d02016-10-31 17:29:10 -0700925 ast->enterScope(new EnumType($2, convertYYLoc(@2), $3));
Yifan Hongf24fa852016-09-23 11:03:15 -0700926 }
927 enum_declaration_body
928 {
Yifan Hongbe627b32016-10-28 18:38:56 -0700929 if (!ast->scope()->isEnum()) {
930 std::cerr << "ERROR: unknown error in enum declaration at "
931 << @5 << "\n";
932 YYERROR;
933 }
934
Yifan Hongf24fa852016-09-23 11:03:15 -0700935 EnumType *enumType = static_cast<EnumType *>(ast->scope());
936 ast->leaveScope();
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700937
938 std::string errorMsg;
Andreas Huber9ed827c2016-08-22 12:31:13 -0700939 if (!ast->addScopedType(enumType, &errorMsg)) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700940 std::cerr << "ERROR: " << errorMsg << " at " << @2 << "\n";
Andreas Huber5a545442016-08-03 10:44:56 -0700941 YYERROR;
942 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700943
944 $$ = enumType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700945 }
946 ;
947
Yifan Hongf24fa852016-09-23 11:03:15 -0700948enum_declaration_body
949 : '{' enum_values opt_comma '}' { $$ = $2; }
950 ;
951
Andreas Huberc9410c72016-07-28 12:18:40 -0700952enum_value
Yifan Hong27e85db2016-11-09 15:45:52 -0800953 : valid_identifier { $$ = new EnumValue($1); }
954 | valid_identifier '=' const_expr { $$ = new EnumValue($1, $3); }
Andreas Huberc9410c72016-07-28 12:18:40 -0700955 ;
956
957enum_values
958 : /* empty */
Yifan Hongf24fa852016-09-23 11:03:15 -0700959 { /* do nothing */ }
Andreas Huberc9410c72016-07-28 12:18:40 -0700960 | enum_value
961 {
Yifan Hongbe627b32016-10-28 18:38:56 -0700962 if (!ast->scope()->isEnum()) {
963 std::cerr << "ERROR: unknown error in enum declaration at "
964 << @1 << "\n";
965 YYERROR;
966 }
967
Yifan Hongf24fa852016-09-23 11:03:15 -0700968 static_cast<EnumType *>(ast->scope())->addValue($1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700969 }
970 | enum_values ',' enum_value
971 {
Yifan Hongbe627b32016-10-28 18:38:56 -0700972 if (!ast->scope()->isEnum()) {
973 std::cerr << "ERROR: unknown error in enum declaration at "
974 << @3 << "\n";
975 YYERROR;
976 }
977
Yifan Hongf24fa852016-09-23 11:03:15 -0700978 static_cast<EnumType *>(ast->scope())->addValue($3);
Andreas Huberc9410c72016-07-28 12:18:40 -0700979 }
980 ;
981
Yifan Hongbd33e382016-11-02 13:30:17 -0700982array_type_base
Yifan Hongae16eed2016-09-23 13:25:25 -0700983 : fqtype { $$ = $1; }
Yifan Hongbf459bc2016-08-23 16:50:37 -0700984 | TEMPLATED '<' type '>'
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700985 {
Steven Moreland30bb6a82016-11-30 09:18:34 -0800986 if (!$1->isCompatibleElementType($3)) {
987 std::cerr << "ERROR: " << $1->typeName() << " of " << $3->typeName()
988 << " is not supported. at " << @3 << "\n";
Andreas Huber70a59e12016-08-16 12:57:01 -0700989
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700990 YYERROR;
991 }
Yifan Hongbf459bc2016-08-23 16:50:37 -0700992 $1->setElementType($3);
993 $$ = $1;
994 }
995 | TEMPLATED '<' TEMPLATED '<' type RSHIFT
996 {
Steven Moreland30bb6a82016-11-30 09:18:34 -0800997 if (!$3->isCompatibleElementType($5)) {
998 std::cerr << "ERROR: " << $3->typeName() << " of " << $5->typeName()
999 << " is not supported. at " << @3 << "\n";
Andreas Huberb95ea8a2016-08-15 15:35:42 -07001000
Yifan Hongbf459bc2016-08-23 16:50:37 -07001001 YYERROR;
1002 }
1003 $3->setElementType($5);
Steven Moreland30bb6a82016-11-30 09:18:34 -08001004 if (!$1->isCompatibleElementType($3)) {
1005 std::cerr << "ERROR: " << $1->typeName() << " of " << $3->typeName()
1006 << " is not supported. at " << @3 << "\n";
1007
1008 YYERROR;
1009 }
Yifan Hongbf459bc2016-08-23 16:50:37 -07001010 $1->setElementType($3);
1011 $$ = $1;
Andreas Huberb95ea8a2016-08-15 15:35:42 -07001012 }
Yifan Hongbd33e382016-11-02 13:30:17 -07001013 ;
1014
1015array_type
1016 : array_type_base '[' const_expr ']'
1017 {
1018 if ($1->isBinder()) {
1019 std::cerr << "ERROR: Arrays of interface types are not supported."
1020 << " at " << @1 << "\n";
1021
1022 YYERROR;
1023 }
1024 if ($1->isArray()) {
1025 $$ = new ArrayType(static_cast<ArrayType *>($1), $3);
1026 } else {
1027 $$ = new ArrayType($1, $3);
1028 }
1029 }
1030 | array_type '[' const_expr ']'
1031 {
1032 $$ = $1;
1033 $$->appendDimension($3);
1034 }
1035 ;
1036
1037type
1038 : array_type_base { $$ = $1; }
1039 | array_type { $$ = $1; }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -07001040 | annotated_compound_declaration { $$ = $1; }
Yifan Hongc8934042016-11-17 17:10:52 -08001041 | INTERFACE
1042 {
1043 // "interface" is a synonym of android.hidl.base@1.0::IBase
1044 $$ = ast->lookupType(gIBaseFqName);
1045 if ($$ == nullptr) {
Steven Moreland0184ce32017-05-26 14:39:38 -07001046 std::cerr << "ERROR: Cannot find "
Yifan Hongc8934042016-11-17 17:10:52 -08001047 << gIBaseFqName.string()
1048 << " at " << @1 << "\n";
1049
1050 YYERROR;
1051 }
1052 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001053 ;
1054
Andreas Huberc9410c72016-07-28 12:18:40 -07001055%%
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001056
1057#include <android-base/logging.h>
1058
1059void yy::parser::error(
1060 const yy::parser::location_type &where,
1061 const std::string &errstr) {
1062 std::cerr << "ERROR: " << errstr << " at " << where << "\n";
1063}
1064