blob: 005aa5951de6ab5b7be687a6aabc0697b9b2a882 [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 Iskhakov653caa42017-09-13 21:32:56 -0700266%type<referenceToType> type enum_storage_type type_or_inplace_compound_declaration
Timur Iskhakov505316c2017-08-05 03:38:59 +0000267%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 {
Steven Morelande1b157e2018-03-06 14:18:32 -0800467 $$ = new FQName();
468 if(!FQName::parse($1, $$)) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700469 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 {
Steven Morelande1b157e2018-03-06 14:18:32 -0800477 $$ = new FQName();
478 if(!FQName::parse($1, $$)) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700479 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;
Steven Morelande1b157e2018-03-06 14:18:32 -0800626 bool isIBase = ast->package().package() == gIBaseFqName.package();
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(
Steven Moreland04dea8d2018-02-06 13:11:24 -0800665 $2, ast->makeFullName($2, *scope), convertYYLoc(@2),
666 *scope, *superType, ast->getFileHash());
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700667
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700668 enterScope(ast, scope, iface);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700669 }
670 '{' interface_declarations '}'
671 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700672 CHECK((*scope)->isInterface());
Yifan Hongbe627b32016-10-28 18:38:56 -0700673
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700674 Interface *iface = static_cast<Interface *>(*scope);
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700675 CHECK(iface->addAllReservedMethods());
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700676
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700677 leaveScope(ast, scope);
Timur Iskhakovb0664f22017-09-12 17:43:13 -0700678 ast->addScopedType(iface, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700679 $$ = iface;
680 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700681 ;
682
683typedef_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700684 : TYPEDEF type valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700685 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000686 // The reason we wrap the given type in a TypeDef is simply to suppress
687 // emitting any type definitions later on, since this is just an alias
688 // to a type defined elsewhere.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700689 TypeDef* typeDef = new TypeDef(
690 $3, ast->makeFullName($3, *scope), convertYYLoc(@2), *scope, *$2);
691 ast->addScopedType(typeDef, *scope);
Timur Iskhakov505316c2017-08-05 03:38:59 +0000692 $$ = typeDef;
Andreas Huberc9410c72016-07-28 12:18:40 -0700693 }
694 ;
695
Yifan Hong52165692016-08-12 18:06:40 -0700696const_expr
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700697 : INTEGER {
698 $$ = LiteralConstantExpression::tryParse($1);
699
700 if ($$ == nullptr) {
701 std::cerr << "ERROR: Could not parse literal: "
702 << $1 << " at " << @1 << ".\n";
703 YYERROR;
704 }
705 }
Yifan Hongb44a6c82016-09-22 15:50:18 -0700706 | fqname
707 {
Yifan Hongf24fa852016-09-23 11:03:15 -0700708 if(!$1->isValidValueName()) {
709 std::cerr << "ERROR: '" << $1->string()
710 << "' does not refer to an enum value at "
711 << @1 << ".\n";
712 YYERROR;
713 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000714
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700715 $$ = new ReferenceConstantExpression(
716 Reference<LocalIdentifier>(*$1, convertYYLoc(@1)), $1->string());
Yifan Hongb44a6c82016-09-22 15:50:18 -0700717 }
Yifan Hong52165692016-08-12 18:06:40 -0700718 | const_expr '?' const_expr ':' const_expr
719 {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000720 $$ = new TernaryConstantExpression($1, $3, $5);
Yifan Hong52165692016-08-12 18:06:40 -0700721 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000722 | const_expr LOGICAL_OR const_expr { $$ = new BinaryConstantExpression($1, "||", $3); }
723 | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); }
724 | const_expr '|' const_expr { $$ = new BinaryConstantExpression($1, "|" , $3); }
725 | const_expr '^' const_expr { $$ = new BinaryConstantExpression($1, "^" , $3); }
726 | const_expr '&' const_expr { $$ = new BinaryConstantExpression($1, "&" , $3); }
727 | const_expr EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); }
728 | const_expr NEQ 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 LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); }
732 | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); }
733 | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); }
734 | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); }
735 | const_expr '+' const_expr { $$ = new BinaryConstantExpression($1, "+" , $3); }
736 | const_expr '-' const_expr { $$ = new BinaryConstantExpression($1, "-" , $3); }
737 | const_expr '*' const_expr { $$ = new BinaryConstantExpression($1, "*" , $3); }
738 | const_expr '/' const_expr { $$ = new BinaryConstantExpression($1, "/" , $3); }
739 | const_expr '%' const_expr { $$ = new BinaryConstantExpression($1, "%" , $3); }
740 | '+' const_expr %prec UNARY_PLUS { $$ = new UnaryConstantExpression("+", $2); }
741 | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); }
742 | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); }
743 | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); }
Yifan Hong52165692016-08-12 18:06:40 -0700744 | '(' const_expr ')' { $$ = $2; }
Yifan Hongbe627b32016-10-28 18:38:56 -0700745 | '(' error ')'
746 {
747 ast->addSyntaxError();
748 // to avoid segfaults
Timur Iskhakov7296af12017-08-09 21:52:48 +0000749 $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release();
Yifan Hongbe627b32016-10-28 18:38:56 -0700750 }
Yifan Hong52165692016-08-12 18:06:40 -0700751 ;
752
Andreas Huberc9410c72016-07-28 12:18:40 -0700753method_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700754 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800755 | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700756 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700757 $$ = new Method($2 /* name */,
758 $4 /* args */,
759 new std::vector<NamedReference<Type>*> /* results */,
760 false /* oneway */,
761 $1 /* annotations */,
762 convertYYLoc(@$));
Iliyan Malchev639bff82016-08-13 14:24:11 -0700763 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800764 | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon
Iliyan Malchev639bff82016-08-13 14:24:11 -0700765 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700766 $$ = new Method($3 /* name */,
767 $5 /* args */,
768 new std::vector<NamedReference<Type>*> /* results */,
769 true /* oneway */,
770 $1 /* annotations */,
771 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700772 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800773 | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700774 {
Steven Moreland1a4572c2018-01-03 14:20:36 -0800775 if ($8->empty()) {
776 std::cerr << "ERROR: generates clause used without result at " << @1 << "\n";
777 ast->addSyntaxError();
778 }
779
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700780 $$ = new Method($2 /* name */,
781 $4 /* args */,
782 $8 /* results */,
783 false /* oneway */,
784 $1 /* annotations */,
785 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700786 }
787 ;
788
789typed_vars
790 : /* empty */
791 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800792 $$ = new TypedVarVector();
Andreas Huberc9410c72016-07-28 12:18:40 -0700793 }
794 | typed_var
795 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800796 $$ = new TypedVarVector();
797 if (!$$->add($1)) {
798 std::cerr << "ERROR: duplicated argument or result name "
799 << $1->name() << " at " << @1 << "\n";
800 ast->addSyntaxError();
801 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700802 }
803 | typed_vars ',' typed_var
804 {
805 $$ = $1;
Yifan Hong7763ab32016-12-13 17:42:11 -0800806 if (!$$->add($3)) {
807 std::cerr << "ERROR: duplicated argument or result name "
808 << $3->name() << " at " << @3 << "\n";
809 ast->addSyntaxError();
810 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700811 }
812 ;
813
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700814typed_var
815 : type valid_identifier
816 {
817 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
818 }
Steven Morelandd623a9c2018-02-02 12:58:14 -0800819 | type
820 {
821 $$ = new NamedReference<Type>("", *$1, convertYYLoc(@1));
822
823 const std::string typeName = $$->isResolved()
824 ? $$->get()->typeName() : $$->getLookupFqName().string();
825
826 std::cerr << "ERROR: variable of type " << typeName
827 << " is missing a variable name at " << @1 << "\n";
828 ast->addSyntaxError();
829 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700830 ;
831
832
833struct_or_union_keyword
834 : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
835 | UNION { $$ = CompoundType::STYLE_UNION; }
836 ;
837
838named_struct_or_union_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700839 : struct_or_union_keyword valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700840 {
Timur Iskhakov565b0132017-09-06 18:07:11 -0700841 CompoundType *container = new CompoundType(
842 $1, $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *scope);
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700843 enterScope(ast, scope, container);
Andreas Huberc9410c72016-07-28 12:18:40 -0700844 }
845 struct_or_union_body
846 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700847 CHECK((*scope)->isCompoundType());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700848 CompoundType *container = static_cast<CompoundType *>(*scope);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700849 container->setFields($4);
Andreas Huber5a545442016-08-03 10:44:56 -0700850
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700851 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700852 ast->addScopedType(container, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700853 $$ = container;
Andreas Huberc9410c72016-07-28 12:18:40 -0700854 }
855 ;
856
Andreas Huberc9410c72016-07-28 12:18:40 -0700857struct_or_union_body
858 : '{' field_declarations '}' { $$ = $2; }
859 ;
860
861field_declarations
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700862 : /* empty */ { $$ = new std::vector<NamedReference<Type>*>; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700863 | field_declarations field_declaration
864 {
865 $$ = $1;
866
Timur Iskhakov505316c2017-08-05 03:38:59 +0000867 // Compound declaration or error
868 if ($2 != nullptr) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700869 $$->push_back($2);
870 }
871 }
872 ;
873
874field_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700875 : error_stmt { $$ = nullptr; }
Timur Iskhakov653caa42017-09-13 21:32:56 -0700876 | type_or_inplace_compound_declaration valid_identifier require_semicolon
Yifan Hong27e85db2016-11-09 15:45:52 -0800877 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700878 CHECK((*scope)->isCompoundType());
879
880 std::string errorMsg;
881 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
882 !isValidStructField($2, &errorMsg)) {
883 std::cerr << "ERROR: " << errorMsg << " at "
884 << @2 << "\n";
885 YYERROR;
886 }
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700887 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
Yifan Hong27e85db2016-11-09 15:45:52 -0800888 }
889 | annotated_compound_declaration ';'
890 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700891 CHECK((*scope)->isCompoundType());
892
893 std::string errorMsg;
894 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
895 $1 != nullptr && $1->isNamedType() &&
896 !isValidStructField(static_cast<NamedType*>($1)->localName().c_str(), &errorMsg)) {
897 std::cerr << "ERROR: " << errorMsg << " at "
898 << @2 << "\n";
899 YYERROR;
900 }
901 // Returns fields only
902 $$ = nullptr;
Yifan Hong27e85db2016-11-09 15:45:52 -0800903 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700904 ;
905
906annotated_compound_declaration
907 : opt_annotations compound_declaration
908 {
Timur Iskhakove9ccfa22017-08-14 15:07:03 -0700909 CHECK($2->isScope());
910 static_cast<Scope*>($2)->setAnnotations($1);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700911 $$ = $2;
912 }
913 ;
914
915compound_declaration
Yifan Honga2855012016-10-11 13:36:54 -0700916 : named_struct_or_union_declaration { $$ = $1; }
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700917 | named_enum_declaration { $$ = $1; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700918 ;
919
Steven Moreland1c71fd52016-11-29 14:03:33 -0800920enum_storage_type
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700921 : ':' fqtype { $$ = $2; }
Steven Moreland37d26112017-09-20 16:15:19 -0700922 | /* empty */ { $$ = nullptr; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700923 ;
924
925opt_comma
926 : /* empty */
927 | ','
928 ;
929
930named_enum_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700931 : ENUM valid_type_name enum_storage_type
Andreas Huberc9410c72016-07-28 12:18:40 -0700932 {
Steven Moreland37d26112017-09-20 16:15:19 -0700933 auto storageType = $3;
934
935 if (storageType == nullptr) {
936 std::cerr << "ERROR: Must explicitly specify enum storage type for "
937 << $2 << " at " << @2 << "\n";
938 ast->addSyntaxError();
939 storageType = new Reference<Type>(
940 new ScalarType(ScalarType::KIND_INT64, *scope), convertYYLoc(@2));
941 }
942
Timur Iskhakov565b0132017-09-06 18:07:11 -0700943 EnumType* enumType = new EnumType(
Steven Moreland37d26112017-09-20 16:15:19 -0700944 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *storageType, *scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700945 enterScope(ast, scope, enumType);
Yifan Hongf24fa852016-09-23 11:03:15 -0700946 }
947 enum_declaration_body
948 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700949 CHECK((*scope)->isEnum());
Timur Iskhakov565b0132017-09-06 18:07:11 -0700950 EnumType* enumType = static_cast<EnumType*>(*scope);
Yifan Hongbe627b32016-10-28 18:38:56 -0700951
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700952 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700953 ast->addScopedType(enumType, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700954 $$ = enumType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700955 }
956 ;
957
Yifan Hongf24fa852016-09-23 11:03:15 -0700958enum_declaration_body
959 : '{' enum_values opt_comma '}' { $$ = $2; }
960 ;
961
Andreas Huberc9410c72016-07-28 12:18:40 -0700962enum_value
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700963 : valid_identifier
964 {
965 $$ = new EnumValue($1 /* name */, nullptr /* value */, convertYYLoc(@$));
966 }
967 | valid_identifier '=' const_expr
968 {
969 $$ = new EnumValue($1 /* name */, $3 /* value */, convertYYLoc(@$));
970 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700971 ;
972
973enum_values
974 : /* empty */
Yifan Hongf24fa852016-09-23 11:03:15 -0700975 { /* do nothing */ }
Andreas Huberc9410c72016-07-28 12:18:40 -0700976 | enum_value
977 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700978 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700979 static_cast<EnumType *>(*scope)->addValue($1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700980 }
981 | enum_values ',' enum_value
982 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700983 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700984 static_cast<EnumType *>(*scope)->addValue($3);
Andreas Huberc9410c72016-07-28 12:18:40 -0700985 }
Steven Moreland9ecf3732017-08-04 10:31:21 -0700986 | error ',' enum_value
987 {
988 ast->addSyntaxError();
989
990 CHECK((*scope)->isEnum());
991 static_cast<EnumType *>(*scope)->addValue($3);
992 }
993 | enum_values ',' error ',' enum_value
994 {
995 ast->addSyntaxError();
996
997 CHECK((*scope)->isEnum());
998 static_cast<EnumType *>(*scope)->addValue($5);
999 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001000 ;
1001
Yifan Hongbd33e382016-11-02 13:30:17 -07001002array_type_base
Yifan Hongae16eed2016-09-23 13:25:25 -07001003 : fqtype { $$ = $1; }
Yifan Hongbf459bc2016-08-23 16:50:37 -07001004 | TEMPLATED '<' type '>'
Andreas Huberb95ea8a2016-08-15 15:35:42 -07001005 {
Timur Iskhakov505316c2017-08-05 03:38:59 +00001006 $1->setElementType(*$3);
1007 $$ = new Reference<Type>($1, convertYYLoc(@1));
Yifan Hongbf459bc2016-08-23 16:50:37 -07001008 }
1009 | TEMPLATED '<' TEMPLATED '<' type RSHIFT
1010 {
Timur Iskhakov505316c2017-08-05 03:38:59 +00001011 $3->setElementType(*$5);
Timur Iskhakov505316c2017-08-05 03:38:59 +00001012 $1->setElementType(Reference<Type>($3, convertYYLoc(@3)));
1013 $$ = new Reference<Type>($1, convertYYLoc(@1));
Andreas Huberb95ea8a2016-08-15 15:35:42 -07001014 }
Yifan Hongbd33e382016-11-02 13:30:17 -07001015 ;
1016
1017array_type
1018 : array_type_base '[' const_expr ']'
1019 {
Timur Iskhakov0737c2a2017-08-31 10:57:28 -07001020 $$ = new ArrayType(*$1, $3, *scope);
Yifan Hongbd33e382016-11-02 13:30:17 -07001021 }
1022 | array_type '[' const_expr ']'
1023 {
1024 $$ = $1;
1025 $$->appendDimension($3);
1026 }
1027 ;
1028
1029type
1030 : array_type_base { $$ = $1; }
Timur Iskhakov505316c2017-08-05 03:38:59 +00001031 | array_type { $$ = new Reference<Type>($1, convertYYLoc(@1)); }
Yifan Hongc8934042016-11-17 17:10:52 -08001032 | INTERFACE
1033 {
1034 // "interface" is a synonym of android.hidl.base@1.0::IBase
Timur Iskhakov505316c2017-08-05 03:38:59 +00001035 $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1));
Yifan Hongc8934042016-11-17 17:10:52 -08001036 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001037 ;
1038
Timur Iskhakov653caa42017-09-13 21:32:56 -07001039type_or_inplace_compound_declaration
1040 : type { $$ = $1; }
1041 | annotated_compound_declaration
1042 {
1043 $$ = new Reference<Type>($1, convertYYLoc(@1));
1044 }
1045 ;
1046
Andreas Huberc9410c72016-07-28 12:18:40 -07001047%%
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001048
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001049void yy::parser::error(
1050 const yy::parser::location_type &where,
1051 const std::string &errstr) {
1052 std::cerr << "ERROR: " << errstr << " at " << where << "\n";
1053}
1054