blob: 073139d62c8498ee01dfa4507ddbc7b638f405a6 [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
19#include "AST.h"
Timur Iskhakov505316c2017-08-05 03:38:59 +000020#include "Annotation.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070021#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"
Yifan Hongbf459bc2016-08-23 16:50:37 -070028#include "RefType.h"
Timur Iskhakov505316c2017-08-05 03:38:59 +000029#include "Scope.h"
30#include "TypeDef.h"
31#include "VectorType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070032
33#include "hidl-gen_y.h"
34
Andreas Huber709b62d2016-09-19 11:21:18 -070035#include <android-base/logging.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080036#include <hidl-util/FQName.h>
Yifan Hong27e85db2016-11-09 15:45:52 -080037#include <hidl-util/StringHelper.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070038#include <stdio.h>
39
40using namespace android;
41
Timur Iskhakov63f39902017-08-29 15:47:29 -070042extern int yylex(yy::parser::semantic_type*, yy::parser::location_type*, void*, Scope** const);
Andreas Huberc9410c72016-07-28 12:18:40 -070043
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070044void enterScope(AST* /* ast */, Scope** scope, Scope* container) {
45 CHECK(container->parent() == (*scope));
46 *scope = container;
47}
48
49void leaveScope(AST* ast, Scope** scope) {
50 CHECK((*scope) != ast->getRootScope());
51 *scope = (*scope)->parent();
52}
Andreas Huberc9410c72016-07-28 12:18:40 -070053
Yifan Honga4b53d02016-10-31 17:29:10 -070054::android::Location convertYYLoc(const yy::parser::location_type &loc) {
55 return ::android::Location(
56 ::android::Position(*(loc.begin.filename), loc.begin.line, loc.begin.column),
57 ::android::Position(*(loc.end.filename), loc.end.line, loc.end.column)
58 );
59}
60
Steven Moreland0184ce32017-05-26 14:39:38 -070061bool isValidInterfaceField(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -080062 static const std::vector<std::string> reserved({
Yifan Hongf3d3c732017-05-08 17:27:54 -070063 // Injected names to C++ interfaces by auto-generated code
Yifan Hongc8934042016-11-17 17:10:52 -080064 "isRemote", "descriptor", "hidlStaticBlock", "onTransact",
Yifan Hongf3d3c732017-05-08 17:27:54 -070065 "castFrom", "Proxy", "Stub", "getService",
66
67 // Injected names to Java interfaces by auto-generated code
68 "asInterface", "castFrom", "getService", "toString",
Yifan Hongb16199d2016-12-09 14:49:46 -080069
70 // Inherited methods from IBase is detected in addMethod. Not added here
71 // because we need hidl-gen to compile IBase.
Yifan Hong27e85db2016-11-09 15:45:52 -080072
73 // Inherited names by interfaces from IInterface / IBinder
74 "onAsBinder", "asBinder", "queryLocalInterface", "getInterfaceDescriptor", "isBinderAlive",
Martijn Coenen115d4282016-12-19 05:14:04 +010075 "pingBinder", "dump", "transact", "checkSubclass", "attachObject", "findObject",
76 "detachObject", "localBinder", "remoteBinder", "mImpl",
Yifan Hongf3d3c732017-05-08 17:27:54 -070077
78 // Inherited names from HidlInstrumentor
79 "InstrumentationEvent", "configureInstrumentation", "registerInstrumentationCallbacks",
80 "isInstrumentationLib", "mInstrumentationCal1lbacks", "mEnableInstrumentation",
81 "mInstrumentationLibPackage", "mInterfaceName",
82
83 // Collide with names in BsFoo
84 "mImpl", "addOnewayTask", "mOnewayQueue",
85
86 // Inherited names from Java IHwInterface
87 "asBinder",
Yifan Hong27e85db2016-11-09 15:45:52 -080088 });
Steven Moreland0184ce32017-05-26 14:39:38 -070089 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) {
90 *errorMsg = identifier + " cannot be a name inside an interface";
Yifan Hong27e85db2016-11-09 15:45:52 -080091 return false;
92 }
93 return true;
94}
95
Steven Moreland0184ce32017-05-26 14:39:38 -070096bool isValidStructField(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -080097 static const std::vector<std::string> reserved({
98 // Injected names to structs and unions by auto-generated code
99 "readEmbeddedFromParcel", "writeEmbeddedToParcel", "readVectorFromParcel",
100 "writeVectorToParcel", "writeEmbeddedToBlob",
101 });
Steven Moreland0184ce32017-05-26 14:39:38 -0700102 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) {
103 *errorMsg = identifier + " cannot be a name inside an struct or union";
Yifan Hong27e85db2016-11-09 15:45:52 -0800104 return false;
105 }
106 return true;
107}
108
Steven Moreland0184ce32017-05-26 14:39:38 -0700109bool isValidIdentifier(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -0800110 static const std::vector<std::string> keywords({
111 "uint8_t", "uint16_t", "uint32_t", "uint64_t",
112 "int8_t", "int16_t", "int32_t", "int64_t", "bool", "float", "double",
113 "interface", "struct", "union", "string", "vec", "enum", "ref", "handle",
114 "package", "import", "typedef", "generates", "oneway", "extends",
Hridya Valsarajua32bde82016-12-27 11:47:46 -0800115 "fmq_sync", "fmq_unsync",
Yifan Hong27e85db2016-11-09 15:45:52 -0800116 });
117 static const std::vector<std::string> cppKeywords({
118 "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit",
119 "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch",
120 "char", "char16_t", "char32_t", "class", "compl", "concept", "const", "constexpr",
121 "const_cast", "continue", "decltype", "default", "delete", "do", "double",
122 "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float",
123 "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable",
124 "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
125 "private", "protected", "public", "register", "reinterpret_cast", "requires", "return",
126 "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct",
127 "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try",
128 "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
129 "volatile", "wchar_t", "while", "xor", "xor_eq",
130 });
131 static const std::vector<std::string> javaKeywords({
132 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package",
133 "synchronized", "boolean", "do", "if", "private", "this", "break", "double",
134 "implements", "protected", "throw", "byte", "else", "import", "public", "throws",
135 "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int",
136 "short", "try", "char", "final", "interface", "static", "void", "class", "finally",
137 "long", "strictfp", "volatile", "const", "float", "native", "super", "while",
138 });
139 static const std::vector<std::string> cppCollide({
140 "size_t", "offsetof",
Yifan Hong27e85db2016-11-09 15:45:52 -0800141 });
142
143 // errors
Steven Moreland0184ce32017-05-26 14:39:38 -0700144 if (std::find(keywords.begin(), keywords.end(), identifier) != keywords.end()) {
145 *errorMsg = identifier + " is a HIDL 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(cppKeywords.begin(), cppKeywords.end(), identifier) != cppKeywords.end()) {
150 *errorMsg = identifier + " is a C++ keyword "
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 (std::find(javaKeywords.begin(), javaKeywords.end(), identifier) != javaKeywords.end()) {
155 *errorMsg = identifier + " is a Java keyword "
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 (std::find(cppCollide.begin(), cppCollide.end(), identifier) != cppCollide.end()) {
160 *errorMsg = identifier + " collides with reserved names in C++ code "
Yifan Hong27e85db2016-11-09 15:45:52 -0800161 "and is therefore not a valid identifier";
162 return false;
163 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700164 if (StringHelper::StartsWith(identifier, "_hidl_")) {
165 *errorMsg = identifier + " starts with _hidl_ "
Yifan Hong27e85db2016-11-09 15:45:52 -0800166 "and is therefore not a valid identifier";
167 return false;
168 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700169 if (StringHelper::StartsWith(identifier, "hidl_")) {
170 *errorMsg = identifier + " starts with hidl_ "
Yifan Hongf3d3c732017-05-08 17:27:54 -0700171 "and is therefore not a valid identifier";
172 return false;
173 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700174 if (StringHelper::EndsWith(identifier, "_cb")) {
175 *errorMsg = identifier + " ends with _cb "
Yifan Hong27e85db2016-11-09 15:45:52 -0800176 "and is therefore not a valid identifier";
177 return false;
178 }
179
Yifan Hongf3d3c732017-05-08 17:27:54 -0700180 return true;
181}
182
183// Return true if identifier is an acceptable name for an UDT.
Steven Moreland0184ce32017-05-26 14:39:38 -0700184bool isValidTypeName(const std::string& identifier, std::string *errorMsg) {
Yifan Hongf3d3c732017-05-08 17:27:54 -0700185 if (!isValidIdentifier(identifier, errorMsg)) {
186 return false;
Yifan Hong27e85db2016-11-09 15:45:52 -0800187 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700188
Steven Moreland0184ce32017-05-26 14:39:38 -0700189 if (identifier == "toString") {
190 *errorMsg = identifier + " is not a valid type name";
Yifan Hongf3d3c732017-05-08 17:27:54 -0700191 return false;
192 }
193
Yifan Hong27e85db2016-11-09 15:45:52 -0800194 return true;
195}
Yifan Honga4b53d02016-10-31 17:29:10 -0700196
Andreas Huberc9410c72016-07-28 12:18:40 -0700197%}
198
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700199%initial-action {
200 // Initialize the initial location.
201 @$.begin.filename = @$.end.filename =
202 const_cast<std::string *>(&ast->getFilename());
203}
204
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700205%parse-param { void* scanner }
206%parse-param { android::AST* const ast }
207%parse-param { android::Scope** const scope }
208%lex-param { void* scanner }
Timur Iskhakov63f39902017-08-29 15:47:29 -0700209%lex-param { android::Scope** const scope }
Andreas Huberc9410c72016-07-28 12:18:40 -0700210%pure-parser
Steven Moreland4ab9b792016-09-26 14:14:07 -0700211%glr-parser
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700212%skeleton "glr.cc"
Andreas Huberc9410c72016-07-28 12:18:40 -0700213
Steven Moreland4ab9b792016-09-26 14:14:07 -0700214%expect-rr 0
Steven Moreland0184ce32017-05-26 14:39:38 -0700215%error-verbose
Steven Moreland4ab9b792016-09-26 14:14:07 -0700216
Steven Morelande931e492017-09-07 09:52:18 -0700217%token<void> ENUM "keyword `enum`"
218%token<void> EXTENDS "keyword `extends`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700219%token<str> FQNAME "fully-qualified name"
Steven Morelande931e492017-09-07 09:52:18 -0700220%token<void> GENERATES "keyword `generates`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700221%token<str> IDENTIFIER "identifier"
Steven Morelande931e492017-09-07 09:52:18 -0700222%token<void> IMPORT "keyword `import`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700223%token<str> INTEGER "integer value"
224%token<str> FLOAT "float value"
Steven Morelande931e492017-09-07 09:52:18 -0700225%token<void> INTERFACE "keyword `interface`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700226%token<str> PACKAGE "keyword `package`"
227%token<type> TYPE "type"
Steven Morelande931e492017-09-07 09:52:18 -0700228%token<void> STRUCT "keyword `struct`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700229%token<str> STRING_LITERAL "string literal"
Steven Morelande931e492017-09-07 09:52:18 -0700230%token<void> TYPEDEF "keyword `typedef`"
231%token<void> UNION "keyword `union`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700232%token<templatedType> TEMPLATED "templated type"
233%token<void> ONEWAY "keyword `oneway`"
Steven Moreland7a4c6622017-09-07 10:32:20 -0700234%token<str> UNKNOWN "unknown character"
Andreas Huberc9410c72016-07-28 12:18:40 -0700235
Yifan Hong52165692016-08-12 18:06:40 -0700236/* Operator precedence and associativity, as per
237 * http://en.cppreference.com/w/cpp/language/operator_precedence */
238/* Precedence level 15 ternary operator */
239%right '?' ':'
240/* Precedence level 13 - 14, LTR, logical operators*/
241%left LOGICAL_OR
242%left LOGICAL_AND
243/* Precedence level 10 - 12, LTR, bitwise operators*/
244%left '|'
245%left '^'
246%left '&'
247/* Precedence level 9, LTR */
248%left EQUALITY NEQ
249/* Precedence level 8, LTR */
250%left '<' '>' LEQ GEQ
251/* Precedence level 7, LTR */
252%left LSHIFT RSHIFT
253/* Precedence level 6, LTR */
254%left '+' '-'
255/* Precedence level 5, LTR */
256%left '*' '/' '%'
257/* Precedence level 3, RTL; but we have to use %left here */
258%left UNARY_MINUS UNARY_PLUS '!' '~'
259
Steven Moreland5f809632017-05-17 13:24:36 -0700260%type<str> error_stmt error
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700261%type<str> package
Yifan Hongae16eed2016-09-23 13:25:25 -0700262%type<fqName> fqname
Timur Iskhakov505316c2017-08-05 03:38:59 +0000263%type<referenceToType> fqtype
Yifan Hongf3d3c732017-05-08 17:27:54 -0700264%type<str> valid_identifier valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700265
Timur Iskhakov505316c2017-08-05 03:38:59 +0000266%type<referenceToType> type enum_storage_type
267%type<referenceToType> array_type_base
Yifan Hongbd33e382016-11-02 13:30:17 -0700268%type<arrayType> array_type
Timur Iskhakov0344e612017-08-25 12:57:09 -0700269%type<referenceToType> opt_extends
Yifan Hong27e85db2016-11-09 15:45:52 -0800270%type<type> type_declaration type_declaration_body interface_declaration typedef_declaration
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700271%type<type> named_struct_or_union_declaration named_enum_declaration
272%type<type> compound_declaration annotated_compound_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700273
274%type<field> field_declaration
275%type<fields> field_declarations struct_or_union_body
Yifan Hong52165692016-08-12 18:06:40 -0700276%type<constantExpression> const_expr
Andreas Huberc9410c72016-07-28 12:18:40 -0700277%type<enumValue> enum_value
Yifan Hongf24fa852016-09-23 11:03:15 -0700278%type<enumValues> enum_values enum_declaration_body
Andreas Huberc9410c72016-07-28 12:18:40 -0700279%type<typedVars> typed_vars
280%type<typedVar> typed_var
281%type<method> method_declaration
282%type<compoundStyle> struct_or_union_keyword
Yifan Hongf24fa852016-09-23 11:03:15 -0700283%type<stringVec> annotation_string_values annotation_string_value
284%type<constExprVec> annotation_const_expr_values annotation_const_expr_value
Andreas Huber3599d922016-08-09 10:42:57 -0700285%type<annotationParam> annotation_param
286%type<annotationParams> opt_annotation_params annotation_params
287%type<annotation> annotation
288%type<annotations> opt_annotations
Andreas Huberc9410c72016-07-28 12:18:40 -0700289
290%start program
291
292%union {
293 const char *str;
Timur Iskhakov505316c2017-08-05 03:38:59 +0000294 android::Type* type;
295 android::Reference<android::Type>* referenceToType;
Yifan Hongbd33e382016-11-02 13:30:17 -0700296 android::ArrayType *arrayType;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700297 android::TemplatedType *templatedType;
Yifan Hongae16eed2016-09-23 13:25:25 -0700298 android::FQName *fqName;
Andreas Huberc9410c72016-07-28 12:18:40 -0700299 android::CompoundType *compoundType;
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700300 android::NamedReference<android::Type>* field;
301 std::vector<android::NamedReference<android::Type>*>* fields;
Andreas Huberc9410c72016-07-28 12:18:40 -0700302 android::EnumValue *enumValue;
Yifan Hong52165692016-08-12 18:06:40 -0700303 android::ConstantExpression *constantExpression;
Andreas Huber881227d2016-08-02 14:20:21 -0700304 std::vector<android::EnumValue *> *enumValues;
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700305 android::NamedReference<android::Type>* typedVar;
Yifan Hong7763ab32016-12-13 17:42:11 -0800306 android::TypedVarVector *typedVars;
Andreas Huberc9410c72016-07-28 12:18:40 -0700307 android::Method *method;
308 android::CompoundType::Style compoundStyle;
Andreas Huber3599d922016-08-09 10:42:57 -0700309 std::vector<std::string> *stringVec;
Yifan Hongf24fa852016-09-23 11:03:15 -0700310 std::vector<android::ConstantExpression *> *constExprVec;
Steven Morelandd537ab02016-09-12 10:32:01 -0700311 android::AnnotationParam *annotationParam;
312 android::AnnotationParamVector *annotationParams;
Andreas Huber3599d922016-08-09 10:42:57 -0700313 android::Annotation *annotation;
Steven Morelandd537ab02016-09-12 10:32:01 -0700314 std::vector<android::Annotation *> *annotations;
Andreas Huberc9410c72016-07-28 12:18:40 -0700315}
316
317%%
318
Steven Moreland2ee84322017-05-17 13:16:33 -0700319program
Steven Moreland5f809632017-05-17 13:24:36 -0700320 : package
Steven Moreland2ee84322017-05-17 13:16:33 -0700321 imports
Steven Moreland0184ce32017-05-26 14:39:38 -0700322 type_declarations
Steven Moreland2ee84322017-05-17 13:16:33 -0700323 ;
324
Yifan Hong27e85db2016-11-09 15:45:52 -0800325valid_identifier
326 : IDENTIFIER
327 {
328 std::string errorMsg;
329 if (!isValidIdentifier($1, &errorMsg)) {
330 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
331 YYERROR;
332 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700333 $$ = $1;
334 }
335 ;
336
337valid_type_name
338 : IDENTIFIER
339 {
340 std::string errorMsg;
341 if (!isValidTypeName($1, &errorMsg)) {
342 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
343 YYERROR;
Yifan Hong27e85db2016-11-09 15:45:52 -0800344 }
345 $$ = $1;
346 }
347 ;
348
Andreas Huber3599d922016-08-09 10:42:57 -0700349opt_annotations
350 : /* empty */
351 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700352 $$ = new std::vector<Annotation *>;
Andreas Huber3599d922016-08-09 10:42:57 -0700353 }
354 | opt_annotations annotation
355 {
356 $$ = $1;
Steven Morelandd537ab02016-09-12 10:32:01 -0700357 $$->push_back($2);
Andreas Huber3599d922016-08-09 10:42:57 -0700358 }
359 ;
360
361annotation
362 : '@' IDENTIFIER opt_annotation_params
363 {
364 $$ = new Annotation($2, $3);
365 }
366 ;
367
368opt_annotation_params
369 : /* empty */
370 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700371 $$ = new AnnotationParamVector;
Andreas Huber3599d922016-08-09 10:42:57 -0700372 }
373 | '(' annotation_params ')'
374 {
375 $$ = $2;
376 }
377 ;
378
379annotation_params
380 : annotation_param
381 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700382 $$ = new AnnotationParamVector;
383 $$->push_back($1);
Andreas Huber3599d922016-08-09 10:42:57 -0700384 }
385 | annotation_params ',' annotation_param
386 {
387 $$ = $1;
Steven Morelandd537ab02016-09-12 10:32:01 -0700388 $$->push_back($3);
Andreas Huber3599d922016-08-09 10:42:57 -0700389 }
390 ;
391
392annotation_param
Yifan Hongf24fa852016-09-23 11:03:15 -0700393 : IDENTIFIER '=' annotation_string_value
394 {
Timur Iskhakov7a85dc22017-08-10 19:06:41 -0700395 $$ = new StringAnnotationParam($1, $3);
Yifan Hongf24fa852016-09-23 11:03:15 -0700396 }
397 | IDENTIFIER '=' annotation_const_expr_value
Andreas Huber3599d922016-08-09 10:42:57 -0700398 {
Timur Iskhakov7a85dc22017-08-10 19:06:41 -0700399 $$ = new ConstantExpressionAnnotationParam($1, $3);
Andreas Huber3599d922016-08-09 10:42:57 -0700400 }
401 ;
402
Yifan Hongf24fa852016-09-23 11:03:15 -0700403annotation_string_value
Andreas Huber3599d922016-08-09 10:42:57 -0700404 : STRING_LITERAL
405 {
406 $$ = new std::vector<std::string>;
407 $$->push_back($1);
408 }
409 | '{' annotation_string_values '}' { $$ = $2; }
410 ;
411
412annotation_string_values
413 : STRING_LITERAL
414 {
415 $$ = new std::vector<std::string>;
416 $$->push_back($1);
417 }
418 | annotation_string_values ',' STRING_LITERAL
419 {
420 $$ = $1;
421 $$->push_back($3);
422 }
423 ;
424
Yifan Hongf24fa852016-09-23 11:03:15 -0700425annotation_const_expr_value
426 : const_expr
427 {
428 $$ = new std::vector<ConstantExpression *>;
429 $$->push_back($1);
430 }
431 | '{' annotation_const_expr_values '}' { $$ = $2; }
432 ;
433
434annotation_const_expr_values
435 : const_expr
436 {
437 $$ = new std::vector<ConstantExpression *>;
438 $$->push_back($1);
439 }
440 | annotation_const_expr_values ',' const_expr
441 {
442 $$ = $1;
443 $$->push_back($3);
444 }
445 ;
446
Yifan Hongbe627b32016-10-28 18:38:56 -0700447error_stmt
448 : error ';'
449 {
450 $$ = $1;
451 ast->addSyntaxError();
Yifan Hongbe627b32016-10-28 18:38:56 -0700452 }
453 ;
454
Yifan Hongbe627b32016-10-28 18:38:56 -0700455require_semicolon
456 : ';'
457 | /* empty */
458 {
459 std::cerr << "ERROR: missing ; at " << @$ << "\n";
460 ast->addSyntaxError();
461 }
462 ;
463
Andreas Huber84f89de2016-07-28 15:39:51 -0700464fqname
465 : FQNAME
466 {
Yifan Hongae16eed2016-09-23 13:25:25 -0700467 $$ = new FQName($1);
468 if(!$$->isValid()) {
469 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at "
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700470 << @1
Yifan Hongae16eed2016-09-23 13:25:25 -0700471 << ".\n";
Andreas Huber84f89de2016-07-28 15:39:51 -0700472 YYERROR;
473 }
474 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700475 | valid_type_name
Andreas Huber84f89de2016-07-28 15:39:51 -0700476 {
Yifan Hongae16eed2016-09-23 13:25:25 -0700477 $$ = new FQName($1);
478 if(!$$->isValid()) {
479 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at "
480 << @1
481 << ".\n";
482 YYERROR;
483 }
484 }
485 ;
486
487fqtype
488 : fqname
489 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000490 $$ = new Reference<Type>(*$1, convertYYLoc(@1));
Andreas Huber84f89de2016-07-28 15:39:51 -0700491 }
Hridya Valsarajucd91bf62016-10-25 12:41:04 -0700492 | TYPE
Timur Iskhakov505316c2017-08-05 03:38:59 +0000493 {
494 $$ = new Reference<Type>($1, convertYYLoc(@1));
495 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700496 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700497
498package
Yifan Hongbe627b32016-10-28 18:38:56 -0700499 : PACKAGE FQNAME require_semicolon
Andreas Hubereb1081f2016-07-28 13:13:24 -0700500 {
Andreas Huber84f89de2016-07-28 15:39:51 -0700501 if (!ast->setPackage($2)) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700502 std::cerr << "ERROR: Malformed package identifier '"
503 << $2
504 << "' at "
505 << @2
506 << "\n";
507
Andreas Huber84f89de2016-07-28 15:39:51 -0700508 YYERROR;
509 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700510 }
Steven Moreland5f809632017-05-17 13:24:36 -0700511 | error
512 {
513 std::cerr << "ERROR: Package statement must be at the beginning of the file (" << @1 << ")\n";
514 $$ = $1;
515 ast->addSyntaxError();
516 }
517 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700518
Yifan Hongbe627b32016-10-28 18:38:56 -0700519import_stmt
520 : IMPORT FQNAME require_semicolon
521 {
522 if (!ast->addImport($2)) {
523 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
524 << "\n";
525 ast->addSyntaxError();
526 }
527 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700528 | IMPORT valid_type_name require_semicolon
Yifan Hongbe627b32016-10-28 18:38:56 -0700529 {
530 if (!ast->addImport($2)) {
531 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
532 << "\n";
533 ast->addSyntaxError();
534 }
535 }
536 | IMPORT error_stmt
537 ;
538
539
Andreas Huberc9410c72016-07-28 12:18:40 -0700540imports
541 : /* empty */
Yifan Hongbe627b32016-10-28 18:38:56 -0700542 | imports import_stmt
Andreas Huberc9410c72016-07-28 12:18:40 -0700543 ;
544
545opt_extends
Timur Iskhakov0344e612017-08-25 12:57:09 -0700546 : /* empty */ { $$ = nullptr; }
547 | EXTENDS fqtype { $$ = $2; }
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700548 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700549
Andreas Huberc9410c72016-07-28 12:18:40 -0700550interface_declarations
551 : /* empty */
552 | interface_declarations type_declaration
Yifan Hong27e85db2016-11-09 15:45:52 -0800553 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700554 CHECK((*scope)->isInterface());
555
Yifan Hong27e85db2016-11-09 15:45:52 -0800556 std::string errorMsg;
Timur Iskhakov505316c2017-08-05 03:38:59 +0000557 if ($2 != nullptr && $2->isNamedType() &&
558 !isValidInterfaceField(static_cast<NamedType*>($2)->localName().c_str(),
Yifan Hong27e85db2016-11-09 15:45:52 -0800559 &errorMsg)) {
560 std::cerr << "ERROR: " << errorMsg << " at "
561 << @2 << "\n";
562 YYERROR;
563 }
564 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700565 | interface_declarations method_declaration
566 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700567 CHECK((*scope)->isInterface());
568
Yifan Hong27e85db2016-11-09 15:45:52 -0800569 std::string errorMsg;
570 if ($2 != nullptr &&
571 !isValidInterfaceField($2->name().c_str(), &errorMsg)) {
572 std::cerr << "ERROR: " << errorMsg << " at "
573 << @2 << "\n";
574 YYERROR;
575 }
576
Yifan Hongbe627b32016-10-28 18:38:56 -0700577 if ($2 != nullptr) {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000578 Interface *iface = static_cast<Interface*>(*scope);
Yifan Hongbe627b32016-10-28 18:38:56 -0700579 if (!iface->addMethod($2)) {
580 std::cerr << "ERROR: Unable to add method '" << $2->name()
581 << "' at " << @2 << "\n";
582
583 YYERROR;
584 }
Steven Moreland14ee6742016-10-18 12:58:28 -0700585 }
Yifan Hongbe627b32016-10-28 18:38:56 -0700586 // ignore if $2 is nullptr (from error recovery)
Andreas Huberc9410c72016-07-28 12:18:40 -0700587 }
588 ;
589
590type_declarations
Andreas Hubera2723d22016-07-29 15:36:07 -0700591 : /* empty */
Yifan Hongbe627b32016-10-28 18:38:56 -0700592 | error_stmt
Andreas Huberc9410c72016-07-28 12:18:40 -0700593 | type_declarations type_declaration
594 ;
595
596type_declaration
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700597 : opt_annotations type_declaration_body
598 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000599 if (!$2->isTypeDef()) {
Timur Iskhakove9ccfa22017-08-14 15:07:03 -0700600 CHECK($2->isScope());
601 static_cast<Scope*>($2)->setAnnotations($1);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700602 } else if (!$1->empty()) {
603 // Since typedefs are always resolved to their target it makes
604 // little sense to annotate them and have their annotations
605 // impose semantics other than their target type.
Timur Iskhakov76533c52017-08-25 13:02:05 -0700606 std::cerr << "ERROR: typedefs cannot be annotated at " << @2
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700607 << "\n";
608
609 YYERROR;
610 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800611 $$ = $2;
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700612 }
613 ;
614
615type_declaration_body
Yifan Hongbe627b32016-10-28 18:38:56 -0700616 : named_struct_or_union_declaration require_semicolon
617 | named_enum_declaration require_semicolon
618 | typedef_declaration require_semicolon
619 | interface_declaration require_semicolon
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700620 ;
621
622interface_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700623 : INTERFACE valid_type_name opt_extends
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700624 {
Timur Iskhakov0344e612017-08-25 12:57:09 -0700625 Reference<Type>* superType = $3;
Timur Iskhakov505316c2017-08-05 03:38:59 +0000626 bool isIBase = ast->package().package() == gIBasePackageFqName.string();
Yifan Hongc8934042016-11-17 17:10:52 -0800627
Timur Iskhakov505316c2017-08-05 03:38:59 +0000628 if (isIBase) {
629 if (superType != nullptr) {
Timur Iskhakov76533c52017-08-25 13:02:05 -0700630 std::cerr << "ERROR: IBase must not extend any interface at " << @3
Timur Iskhakov505316c2017-08-05 03:38:59 +0000631 << "\n";
632
633 YYERROR;
634 }
Timur Iskhakov0344e612017-08-25 12:57:09 -0700635 superType = new Reference<Type>();
Timur Iskhakov505316c2017-08-05 03:38:59 +0000636 } else {
Yifan Hongc8934042016-11-17 17:10:52 -0800637 if (!ast->addImport(gIBaseFqName.string().c_str())) {
638 std::cerr << "ERROR: Unable to automatically import '"
639 << gIBaseFqName.string()
640 << "' at " << @$
641 << "\n";
642 YYERROR;
643 }
Timur Iskhakov505316c2017-08-05 03:38:59 +0000644
645 if (superType == nullptr) {
Timur Iskhakov0344e612017-08-25 12:57:09 -0700646 superType = new Reference<Type>(gIBaseFqName, convertYYLoc(@$));
Yifan Hongc8934042016-11-17 17:10:52 -0800647 }
648 }
649
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700650 if ($2[0] != 'I') {
651 std::cerr << "ERROR: All interface names must start with an 'I' "
Timur Iskhakov76533c52017-08-25 13:02:05 -0700652 << "prefix at " << @2 << "\n";
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700653
654 YYERROR;
655 }
656
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700657 if (*scope != ast->getRootScope()) {
658 std::cerr << "ERROR: All interface must declared in "
Timur Iskhakov76533c52017-08-25 13:02:05 -0700659 << "global scope at " << @2 << "\n";
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700660
661 YYERROR;
662 }
663
664 Interface* iface = new Interface(
Timur Iskhakov565b0132017-09-06 18:07:11 -0700665 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *scope, *superType);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700666
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700667 enterScope(ast, scope, iface);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700668 }
669 '{' interface_declarations '}'
670 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700671 CHECK((*scope)->isInterface());
Yifan Hongbe627b32016-10-28 18:38:56 -0700672
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700673 Interface *iface = static_cast<Interface *>(*scope);
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700674 CHECK(iface->addAllReservedMethods());
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700675
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700676 leaveScope(ast, scope);
Timur Iskhakovb0664f22017-09-12 17:43:13 -0700677 ast->addScopedType(iface, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700678 $$ = iface;
679 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700680 ;
681
682typedef_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700683 : TYPEDEF type valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700684 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000685 // The reason we wrap the given type in a TypeDef is simply to suppress
686 // emitting any type definitions later on, since this is just an alias
687 // to a type defined elsewhere.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700688 TypeDef* typeDef = new TypeDef(
689 $3, ast->makeFullName($3, *scope), convertYYLoc(@2), *scope, *$2);
690 ast->addScopedType(typeDef, *scope);
Timur Iskhakov505316c2017-08-05 03:38:59 +0000691 $$ = typeDef;
Andreas Huberc9410c72016-07-28 12:18:40 -0700692 }
693 ;
694
Yifan Hong52165692016-08-12 18:06:40 -0700695const_expr
Timur Iskhakov7296af12017-08-09 21:52:48 +0000696 : INTEGER { $$ = new LiteralConstantExpression($1); }
Yifan Hongb44a6c82016-09-22 15:50:18 -0700697 | fqname
698 {
Yifan Hongf24fa852016-09-23 11:03:15 -0700699 if(!$1->isValidValueName()) {
700 std::cerr << "ERROR: '" << $1->string()
701 << "' does not refer to an enum value at "
702 << @1 << ".\n";
703 YYERROR;
704 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000705
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700706 $$ = new ReferenceConstantExpression(
707 Reference<LocalIdentifier>(*$1, convertYYLoc(@1)), $1->string());
Yifan Hongb44a6c82016-09-22 15:50:18 -0700708 }
Yifan Hong52165692016-08-12 18:06:40 -0700709 | const_expr '?' const_expr ':' const_expr
710 {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000711 $$ = new TernaryConstantExpression($1, $3, $5);
Yifan Hong52165692016-08-12 18:06:40 -0700712 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000713 | const_expr LOGICAL_OR const_expr { $$ = new BinaryConstantExpression($1, "||", $3); }
714 | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); }
715 | const_expr '|' const_expr { $$ = new BinaryConstantExpression($1, "|" , $3); }
716 | const_expr '^' const_expr { $$ = new BinaryConstantExpression($1, "^" , $3); }
717 | const_expr '&' const_expr { $$ = new BinaryConstantExpression($1, "&" , $3); }
718 | const_expr EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); }
719 | const_expr NEQ const_expr { $$ = new BinaryConstantExpression($1, "!=", $3); }
720 | const_expr '<' const_expr { $$ = new BinaryConstantExpression($1, "<" , $3); }
721 | const_expr '>' const_expr { $$ = new BinaryConstantExpression($1, ">" , $3); }
722 | const_expr LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); }
723 | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); }
724 | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); }
725 | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); }
726 | const_expr '+' const_expr { $$ = new BinaryConstantExpression($1, "+" , $3); }
727 | const_expr '-' const_expr { $$ = new BinaryConstantExpression($1, "-" , $3); }
728 | const_expr '*' const_expr { $$ = new BinaryConstantExpression($1, "*" , $3); }
729 | const_expr '/' const_expr { $$ = new BinaryConstantExpression($1, "/" , $3); }
730 | const_expr '%' const_expr { $$ = new BinaryConstantExpression($1, "%" , $3); }
731 | '+' const_expr %prec UNARY_PLUS { $$ = new UnaryConstantExpression("+", $2); }
732 | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); }
733 | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); }
734 | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); }
Yifan Hong52165692016-08-12 18:06:40 -0700735 | '(' const_expr ')' { $$ = $2; }
Yifan Hongbe627b32016-10-28 18:38:56 -0700736 | '(' error ')'
737 {
738 ast->addSyntaxError();
739 // to avoid segfaults
Timur Iskhakov7296af12017-08-09 21:52:48 +0000740 $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release();
Yifan Hongbe627b32016-10-28 18:38:56 -0700741 }
Yifan Hong52165692016-08-12 18:06:40 -0700742 ;
743
Andreas Huberc9410c72016-07-28 12:18:40 -0700744method_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700745 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800746 | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700747 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700748 $$ = new Method($2 /* name */,
749 $4 /* args */,
750 new std::vector<NamedReference<Type>*> /* results */,
751 false /* oneway */,
752 $1 /* annotations */,
753 convertYYLoc(@$));
Iliyan Malchev639bff82016-08-13 14:24:11 -0700754 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800755 | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon
Iliyan Malchev639bff82016-08-13 14:24:11 -0700756 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700757 $$ = new Method($3 /* name */,
758 $5 /* args */,
759 new std::vector<NamedReference<Type>*> /* results */,
760 true /* oneway */,
761 $1 /* annotations */,
762 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700763 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800764 | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700765 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700766 $$ = new Method($2 /* name */,
767 $4 /* args */,
768 $8 /* results */,
769 false /* oneway */,
770 $1 /* annotations */,
771 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700772 }
773 ;
774
775typed_vars
776 : /* empty */
777 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800778 $$ = new TypedVarVector();
Andreas Huberc9410c72016-07-28 12:18:40 -0700779 }
780 | typed_var
781 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800782 $$ = new TypedVarVector();
783 if (!$$->add($1)) {
784 std::cerr << "ERROR: duplicated argument or result name "
785 << $1->name() << " at " << @1 << "\n";
786 ast->addSyntaxError();
787 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700788 }
789 | typed_vars ',' typed_var
790 {
791 $$ = $1;
Yifan Hong7763ab32016-12-13 17:42:11 -0800792 if (!$$->add($3)) {
793 std::cerr << "ERROR: duplicated argument or result name "
794 << $3->name() << " at " << @3 << "\n";
795 ast->addSyntaxError();
796 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700797 }
798 ;
799
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700800typed_var
801 : type valid_identifier
802 {
803 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
804 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700805 ;
806
807
808struct_or_union_keyword
809 : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
810 | UNION { $$ = CompoundType::STYLE_UNION; }
811 ;
812
813named_struct_or_union_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700814 : struct_or_union_keyword valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700815 {
Timur Iskhakov565b0132017-09-06 18:07:11 -0700816 CompoundType *container = new CompoundType(
817 $1, $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *scope);
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700818 enterScope(ast, scope, container);
Andreas Huberc9410c72016-07-28 12:18:40 -0700819 }
820 struct_or_union_body
821 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700822 CHECK((*scope)->isCompoundType());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700823 CompoundType *container = static_cast<CompoundType *>(*scope);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700824 container->setFields($4);
Andreas Huber5a545442016-08-03 10:44:56 -0700825
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700826 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700827 ast->addScopedType(container, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700828 $$ = container;
Andreas Huberc9410c72016-07-28 12:18:40 -0700829 }
830 ;
831
Andreas Huberc9410c72016-07-28 12:18:40 -0700832struct_or_union_body
833 : '{' field_declarations '}' { $$ = $2; }
834 ;
835
836field_declarations
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700837 : /* empty */ { $$ = new std::vector<NamedReference<Type>*>; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700838 | field_declarations field_declaration
839 {
840 $$ = $1;
841
Timur Iskhakov505316c2017-08-05 03:38:59 +0000842 // Compound declaration or error
843 if ($2 != nullptr) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700844 $$->push_back($2);
845 }
846 }
847 ;
848
849field_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700850 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800851 | type valid_identifier require_semicolon
852 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700853 CHECK((*scope)->isCompoundType());
854
855 std::string errorMsg;
856 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
857 !isValidStructField($2, &errorMsg)) {
858 std::cerr << "ERROR: " << errorMsg << " at "
859 << @2 << "\n";
860 YYERROR;
861 }
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700862 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
Yifan Hong27e85db2016-11-09 15:45:52 -0800863 }
864 | annotated_compound_declaration ';'
865 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700866 CHECK((*scope)->isCompoundType());
867
868 std::string errorMsg;
869 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
870 $1 != nullptr && $1->isNamedType() &&
871 !isValidStructField(static_cast<NamedType*>($1)->localName().c_str(), &errorMsg)) {
872 std::cerr << "ERROR: " << errorMsg << " at "
873 << @2 << "\n";
874 YYERROR;
875 }
876 // Returns fields only
877 $$ = nullptr;
Yifan Hong27e85db2016-11-09 15:45:52 -0800878 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700879 ;
880
881annotated_compound_declaration
882 : opt_annotations compound_declaration
883 {
Timur Iskhakove9ccfa22017-08-14 15:07:03 -0700884 CHECK($2->isScope());
885 static_cast<Scope*>($2)->setAnnotations($1);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700886 $$ = $2;
887 }
888 ;
889
890compound_declaration
Yifan Honga2855012016-10-11 13:36:54 -0700891 : named_struct_or_union_declaration { $$ = $1; }
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700892 | named_enum_declaration { $$ = $1; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700893 ;
894
Steven Moreland1c71fd52016-11-29 14:03:33 -0800895enum_storage_type
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700896 : ':' fqtype { $$ = $2; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700897 ;
898
899opt_comma
900 : /* empty */
901 | ','
902 ;
903
904named_enum_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700905 : ENUM valid_type_name enum_storage_type
Andreas Huberc9410c72016-07-28 12:18:40 -0700906 {
Timur Iskhakov565b0132017-09-06 18:07:11 -0700907 EnumType* enumType = new EnumType(
908 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *$3, *scope);
909 enterScope(ast, scope, enumType);
Yifan Hongf24fa852016-09-23 11:03:15 -0700910 }
911 enum_declaration_body
912 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700913 CHECK((*scope)->isEnum());
Timur Iskhakov565b0132017-09-06 18:07:11 -0700914 EnumType* enumType = static_cast<EnumType*>(*scope);
Yifan Hongbe627b32016-10-28 18:38:56 -0700915
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700916 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700917 ast->addScopedType(enumType, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700918 $$ = enumType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700919 }
920 ;
921
Yifan Hongf24fa852016-09-23 11:03:15 -0700922enum_declaration_body
923 : '{' enum_values opt_comma '}' { $$ = $2; }
924 ;
925
Andreas Huberc9410c72016-07-28 12:18:40 -0700926enum_value
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700927 : valid_identifier
928 {
929 $$ = new EnumValue($1 /* name */, nullptr /* value */, convertYYLoc(@$));
930 }
931 | valid_identifier '=' const_expr
932 {
933 $$ = new EnumValue($1 /* name */, $3 /* value */, convertYYLoc(@$));
934 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700935 ;
936
937enum_values
938 : /* empty */
Yifan Hongf24fa852016-09-23 11:03:15 -0700939 { /* do nothing */ }
Andreas Huberc9410c72016-07-28 12:18:40 -0700940 | enum_value
941 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700942 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700943 static_cast<EnumType *>(*scope)->addValue($1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700944 }
945 | enum_values ',' enum_value
946 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700947 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700948 static_cast<EnumType *>(*scope)->addValue($3);
Andreas Huberc9410c72016-07-28 12:18:40 -0700949 }
Steven Moreland9ecf3732017-08-04 10:31:21 -0700950 | error ',' enum_value
951 {
952 ast->addSyntaxError();
953
954 CHECK((*scope)->isEnum());
955 static_cast<EnumType *>(*scope)->addValue($3);
956 }
957 | enum_values ',' error ',' enum_value
958 {
959 ast->addSyntaxError();
960
961 CHECK((*scope)->isEnum());
962 static_cast<EnumType *>(*scope)->addValue($5);
963 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700964 ;
965
Yifan Hongbd33e382016-11-02 13:30:17 -0700966array_type_base
Yifan Hongae16eed2016-09-23 13:25:25 -0700967 : fqtype { $$ = $1; }
Yifan Hongbf459bc2016-08-23 16:50:37 -0700968 | TEMPLATED '<' type '>'
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700969 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000970 $1->setElementType(*$3);
971 $$ = new Reference<Type>($1, convertYYLoc(@1));
Yifan Hongbf459bc2016-08-23 16:50:37 -0700972 }
973 | TEMPLATED '<' TEMPLATED '<' type RSHIFT
974 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000975 $3->setElementType(*$5);
Timur Iskhakov505316c2017-08-05 03:38:59 +0000976 $1->setElementType(Reference<Type>($3, convertYYLoc(@3)));
977 $$ = new Reference<Type>($1, convertYYLoc(@1));
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700978 }
Yifan Hongbd33e382016-11-02 13:30:17 -0700979 ;
980
981array_type
982 : array_type_base '[' const_expr ']'
983 {
Timur Iskhakov0737c2a2017-08-31 10:57:28 -0700984 $$ = new ArrayType(*$1, $3, *scope);
Yifan Hongbd33e382016-11-02 13:30:17 -0700985 }
986 | array_type '[' const_expr ']'
987 {
988 $$ = $1;
989 $$->appendDimension($3);
990 }
991 ;
992
993type
994 : array_type_base { $$ = $1; }
Timur Iskhakov505316c2017-08-05 03:38:59 +0000995 | array_type { $$ = new Reference<Type>($1, convertYYLoc(@1)); }
996 | annotated_compound_declaration
997 {
998 $$ = new Reference<Type>($1, convertYYLoc(@1));
999 }
Yifan Hongc8934042016-11-17 17:10:52 -08001000 | INTERFACE
1001 {
1002 // "interface" is a synonym of android.hidl.base@1.0::IBase
Timur Iskhakov505316c2017-08-05 03:38:59 +00001003 $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1));
Yifan Hongc8934042016-11-17 17:10:52 -08001004 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001005 ;
1006
Andreas Huberc9410c72016-07-28 12:18:40 -07001007%%
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001008
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001009void yy::parser::error(
1010 const yy::parser::location_type &where,
1011 const std::string &errstr) {
1012 std::cerr << "ERROR: " << errstr << " at " << where << "\n";
1013}
1014