blob: f872e434d8981549afdb82c1cb2fa068b6dbbfe3 [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 {
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
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700696 : INTEGER {
697 $$ = LiteralConstantExpression::tryParse($1);
698
699 if ($$ == nullptr) {
700 std::cerr << "ERROR: Could not parse literal: "
701 << $1 << " at " << @1 << ".\n";
702 YYERROR;
703 }
704 }
Yifan Hongb44a6c82016-09-22 15:50:18 -0700705 | fqname
706 {
Yifan Hongf24fa852016-09-23 11:03:15 -0700707 if(!$1->isValidValueName()) {
708 std::cerr << "ERROR: '" << $1->string()
709 << "' does not refer to an enum value at "
710 << @1 << ".\n";
711 YYERROR;
712 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000713
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700714 $$ = new ReferenceConstantExpression(
715 Reference<LocalIdentifier>(*$1, convertYYLoc(@1)), $1->string());
Yifan Hongb44a6c82016-09-22 15:50:18 -0700716 }
Yifan Hong52165692016-08-12 18:06:40 -0700717 | const_expr '?' const_expr ':' const_expr
718 {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000719 $$ = new TernaryConstantExpression($1, $3, $5);
Yifan Hong52165692016-08-12 18:06:40 -0700720 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000721 | const_expr LOGICAL_OR const_expr { $$ = new BinaryConstantExpression($1, "||", $3); }
722 | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); }
723 | const_expr '|' 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 EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); }
727 | const_expr NEQ 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 LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); }
731 | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); }
732 | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); }
733 | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); }
734 | const_expr '+' 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 %prec UNARY_PLUS { $$ = new UnaryConstantExpression("+", $2); }
740 | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); }
741 | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); }
742 | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); }
Yifan Hong52165692016-08-12 18:06:40 -0700743 | '(' const_expr ')' { $$ = $2; }
Yifan Hongbe627b32016-10-28 18:38:56 -0700744 | '(' error ')'
745 {
746 ast->addSyntaxError();
747 // to avoid segfaults
Timur Iskhakov7296af12017-08-09 21:52:48 +0000748 $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release();
Yifan Hongbe627b32016-10-28 18:38:56 -0700749 }
Yifan Hong52165692016-08-12 18:06:40 -0700750 ;
751
Andreas Huberc9410c72016-07-28 12:18:40 -0700752method_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700753 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800754 | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700755 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700756 $$ = new Method($2 /* name */,
757 $4 /* args */,
758 new std::vector<NamedReference<Type>*> /* results */,
759 false /* oneway */,
760 $1 /* annotations */,
761 convertYYLoc(@$));
Iliyan Malchev639bff82016-08-13 14:24:11 -0700762 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800763 | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon
Iliyan Malchev639bff82016-08-13 14:24:11 -0700764 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700765 $$ = new Method($3 /* name */,
766 $5 /* args */,
767 new std::vector<NamedReference<Type>*> /* results */,
768 true /* oneway */,
769 $1 /* annotations */,
770 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700771 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800772 | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700773 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700774 $$ = new Method($2 /* name */,
775 $4 /* args */,
776 $8 /* results */,
777 false /* oneway */,
778 $1 /* annotations */,
779 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700780 }
781 ;
782
783typed_vars
784 : /* empty */
785 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800786 $$ = new TypedVarVector();
Andreas Huberc9410c72016-07-28 12:18:40 -0700787 }
788 | typed_var
789 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800790 $$ = new TypedVarVector();
791 if (!$$->add($1)) {
792 std::cerr << "ERROR: duplicated argument or result name "
793 << $1->name() << " at " << @1 << "\n";
794 ast->addSyntaxError();
795 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700796 }
797 | typed_vars ',' typed_var
798 {
799 $$ = $1;
Yifan Hong7763ab32016-12-13 17:42:11 -0800800 if (!$$->add($3)) {
801 std::cerr << "ERROR: duplicated argument or result name "
802 << $3->name() << " at " << @3 << "\n";
803 ast->addSyntaxError();
804 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700805 }
806 ;
807
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700808typed_var
809 : type valid_identifier
810 {
811 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
812 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700813 ;
814
815
816struct_or_union_keyword
817 : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
818 | UNION { $$ = CompoundType::STYLE_UNION; }
819 ;
820
821named_struct_or_union_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700822 : struct_or_union_keyword valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700823 {
Timur Iskhakov565b0132017-09-06 18:07:11 -0700824 CompoundType *container = new CompoundType(
825 $1, $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *scope);
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700826 enterScope(ast, scope, container);
Andreas Huberc9410c72016-07-28 12:18:40 -0700827 }
828 struct_or_union_body
829 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700830 CHECK((*scope)->isCompoundType());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700831 CompoundType *container = static_cast<CompoundType *>(*scope);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700832 container->setFields($4);
Andreas Huber5a545442016-08-03 10:44:56 -0700833
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700834 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700835 ast->addScopedType(container, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700836 $$ = container;
Andreas Huberc9410c72016-07-28 12:18:40 -0700837 }
838 ;
839
Andreas Huberc9410c72016-07-28 12:18:40 -0700840struct_or_union_body
841 : '{' field_declarations '}' { $$ = $2; }
842 ;
843
844field_declarations
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700845 : /* empty */ { $$ = new std::vector<NamedReference<Type>*>; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700846 | field_declarations field_declaration
847 {
848 $$ = $1;
849
Timur Iskhakov505316c2017-08-05 03:38:59 +0000850 // Compound declaration or error
851 if ($2 != nullptr) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700852 $$->push_back($2);
853 }
854 }
855 ;
856
857field_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700858 : error_stmt { $$ = nullptr; }
Timur Iskhakov653caa42017-09-13 21:32:56 -0700859 | type_or_inplace_compound_declaration valid_identifier require_semicolon
Yifan Hong27e85db2016-11-09 15:45:52 -0800860 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700861 CHECK((*scope)->isCompoundType());
862
863 std::string errorMsg;
864 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
865 !isValidStructField($2, &errorMsg)) {
866 std::cerr << "ERROR: " << errorMsg << " at "
867 << @2 << "\n";
868 YYERROR;
869 }
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700870 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
Yifan Hong27e85db2016-11-09 15:45:52 -0800871 }
872 | annotated_compound_declaration ';'
873 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700874 CHECK((*scope)->isCompoundType());
875
876 std::string errorMsg;
877 if (static_cast<CompoundType *>(*scope)->style() == CompoundType::STYLE_STRUCT &&
878 $1 != nullptr && $1->isNamedType() &&
879 !isValidStructField(static_cast<NamedType*>($1)->localName().c_str(), &errorMsg)) {
880 std::cerr << "ERROR: " << errorMsg << " at "
881 << @2 << "\n";
882 YYERROR;
883 }
884 // Returns fields only
885 $$ = nullptr;
Yifan Hong27e85db2016-11-09 15:45:52 -0800886 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700887 ;
888
889annotated_compound_declaration
890 : opt_annotations compound_declaration
891 {
Timur Iskhakove9ccfa22017-08-14 15:07:03 -0700892 CHECK($2->isScope());
893 static_cast<Scope*>($2)->setAnnotations($1);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700894 $$ = $2;
895 }
896 ;
897
898compound_declaration
Yifan Honga2855012016-10-11 13:36:54 -0700899 : named_struct_or_union_declaration { $$ = $1; }
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700900 | named_enum_declaration { $$ = $1; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700901 ;
902
Steven Moreland1c71fd52016-11-29 14:03:33 -0800903enum_storage_type
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700904 : ':' fqtype { $$ = $2; }
Steven Moreland37d26112017-09-20 16:15:19 -0700905 | /* empty */ { $$ = nullptr; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700906 ;
907
908opt_comma
909 : /* empty */
910 | ','
911 ;
912
913named_enum_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700914 : ENUM valid_type_name enum_storage_type
Andreas Huberc9410c72016-07-28 12:18:40 -0700915 {
Steven Moreland37d26112017-09-20 16:15:19 -0700916 auto storageType = $3;
917
918 if (storageType == nullptr) {
919 std::cerr << "ERROR: Must explicitly specify enum storage type for "
920 << $2 << " at " << @2 << "\n";
921 ast->addSyntaxError();
922 storageType = new Reference<Type>(
923 new ScalarType(ScalarType::KIND_INT64, *scope), convertYYLoc(@2));
924 }
925
Timur Iskhakov565b0132017-09-06 18:07:11 -0700926 EnumType* enumType = new EnumType(
Steven Moreland37d26112017-09-20 16:15:19 -0700927 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *storageType, *scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700928 enterScope(ast, scope, enumType);
Yifan Hongf24fa852016-09-23 11:03:15 -0700929 }
930 enum_declaration_body
931 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700932 CHECK((*scope)->isEnum());
Timur Iskhakov565b0132017-09-06 18:07:11 -0700933 EnumType* enumType = static_cast<EnumType*>(*scope);
Yifan Hongbe627b32016-10-28 18:38:56 -0700934
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700935 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700936 ast->addScopedType(enumType, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700937 $$ = enumType;
Andreas Huberc9410c72016-07-28 12:18:40 -0700938 }
939 ;
940
Yifan Hongf24fa852016-09-23 11:03:15 -0700941enum_declaration_body
942 : '{' enum_values opt_comma '}' { $$ = $2; }
943 ;
944
Andreas Huberc9410c72016-07-28 12:18:40 -0700945enum_value
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700946 : valid_identifier
947 {
948 $$ = new EnumValue($1 /* name */, nullptr /* value */, convertYYLoc(@$));
949 }
950 | valid_identifier '=' const_expr
951 {
952 $$ = new EnumValue($1 /* name */, $3 /* value */, convertYYLoc(@$));
953 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700954 ;
955
956enum_values
957 : /* empty */
Yifan Hongf24fa852016-09-23 11:03:15 -0700958 { /* do nothing */ }
Andreas Huberc9410c72016-07-28 12:18:40 -0700959 | enum_value
960 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700961 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700962 static_cast<EnumType *>(*scope)->addValue($1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700963 }
964 | enum_values ',' enum_value
965 {
Steven Moreland9ecf3732017-08-04 10:31:21 -0700966 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700967 static_cast<EnumType *>(*scope)->addValue($3);
Andreas Huberc9410c72016-07-28 12:18:40 -0700968 }
Steven Moreland9ecf3732017-08-04 10:31:21 -0700969 | error ',' enum_value
970 {
971 ast->addSyntaxError();
972
973 CHECK((*scope)->isEnum());
974 static_cast<EnumType *>(*scope)->addValue($3);
975 }
976 | enum_values ',' error ',' enum_value
977 {
978 ast->addSyntaxError();
979
980 CHECK((*scope)->isEnum());
981 static_cast<EnumType *>(*scope)->addValue($5);
982 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700983 ;
984
Yifan Hongbd33e382016-11-02 13:30:17 -0700985array_type_base
Yifan Hongae16eed2016-09-23 13:25:25 -0700986 : fqtype { $$ = $1; }
Yifan Hongbf459bc2016-08-23 16:50:37 -0700987 | TEMPLATED '<' type '>'
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700988 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000989 $1->setElementType(*$3);
990 $$ = new Reference<Type>($1, convertYYLoc(@1));
Yifan Hongbf459bc2016-08-23 16:50:37 -0700991 }
992 | TEMPLATED '<' TEMPLATED '<' type RSHIFT
993 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000994 $3->setElementType(*$5);
Timur Iskhakov505316c2017-08-05 03:38:59 +0000995 $1->setElementType(Reference<Type>($3, convertYYLoc(@3)));
996 $$ = new Reference<Type>($1, convertYYLoc(@1));
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700997 }
Yifan Hongbd33e382016-11-02 13:30:17 -0700998 ;
999
1000array_type
1001 : array_type_base '[' const_expr ']'
1002 {
Timur Iskhakov0737c2a2017-08-31 10:57:28 -07001003 $$ = new ArrayType(*$1, $3, *scope);
Yifan Hongbd33e382016-11-02 13:30:17 -07001004 }
1005 | array_type '[' const_expr ']'
1006 {
1007 $$ = $1;
1008 $$->appendDimension($3);
1009 }
1010 ;
1011
1012type
1013 : array_type_base { $$ = $1; }
Timur Iskhakov505316c2017-08-05 03:38:59 +00001014 | array_type { $$ = new Reference<Type>($1, convertYYLoc(@1)); }
Yifan Hongc8934042016-11-17 17:10:52 -08001015 | INTERFACE
1016 {
1017 // "interface" is a synonym of android.hidl.base@1.0::IBase
Timur Iskhakov505316c2017-08-05 03:38:59 +00001018 $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1));
Yifan Hongc8934042016-11-17 17:10:52 -08001019 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001020 ;
1021
Timur Iskhakov653caa42017-09-13 21:32:56 -07001022type_or_inplace_compound_declaration
1023 : type { $$ = $1; }
1024 | annotated_compound_declaration
1025 {
1026 $$ = new Reference<Type>($1, convertYYLoc(@1));
1027 }
1028 ;
1029
Andreas Huberc9410c72016-07-28 12:18:40 -07001030%%
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001031
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001032void yy::parser::error(
1033 const yy::parser::location_type &where,
1034 const std::string &errstr) {
1035 std::cerr << "ERROR: " << errstr << " at " << where << "\n";
1036}
1037