blob: 65f432323bf24c066dc917d18b03cf6ca88d258b [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"
Steven Moreland073269e2018-05-17 15:45:26 -070024#include "DocComment.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070025#include "EnumType.h"
26#include "Interface.h"
Yifan Honga4b53d02016-10-31 17:29:10 -070027#include "Location.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070028#include "Method.h"
Yifan Hongbf459bc2016-08-23 16:50:37 -070029#include "RefType.h"
Timur Iskhakov505316c2017-08-05 03:38:59 +000030#include "Scope.h"
31#include "TypeDef.h"
32#include "VectorType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070033
34#include "hidl-gen_y.h"
35
Andreas Huber709b62d2016-09-19 11:21:18 -070036#include <android-base/logging.h>
Steven Moreland7ae3d542017-01-18 16:46:01 -080037#include <hidl-util/FQName.h>
Yifan Hong27e85db2016-11-09 15:45:52 -080038#include <hidl-util/StringHelper.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070039#include <stdio.h>
40
41using namespace android;
42
Timur Iskhakov63f39902017-08-29 15:47:29 -070043extern int yylex(yy::parser::semantic_type*, yy::parser::location_type*, void*, Scope** const);
Andreas Huberc9410c72016-07-28 12:18:40 -070044
Timur Iskhakovcb0ba522017-07-17 20:01:37 -070045void enterScope(AST* /* ast */, Scope** scope, Scope* container) {
46 CHECK(container->parent() == (*scope));
47 *scope = container;
48}
49
50void leaveScope(AST* ast, Scope** scope) {
51 CHECK((*scope) != ast->getRootScope());
52 *scope = (*scope)->parent();
53}
Andreas Huberc9410c72016-07-28 12:18:40 -070054
Yifan Honga4b53d02016-10-31 17:29:10 -070055::android::Location convertYYLoc(const yy::parser::location_type &loc) {
56 return ::android::Location(
57 ::android::Position(*(loc.begin.filename), loc.begin.line, loc.begin.column),
58 ::android::Position(*(loc.end.filename), loc.end.line, loc.end.column)
59 );
60}
61
Steven Moreland0184ce32017-05-26 14:39:38 -070062bool isValidInterfaceField(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -080063 static const std::vector<std::string> reserved({
Yifan Hongf3d3c732017-05-08 17:27:54 -070064 // Injected names to C++ interfaces by auto-generated code
Yifan Hongc8934042016-11-17 17:10:52 -080065 "isRemote", "descriptor", "hidlStaticBlock", "onTransact",
Yifan Hongf3d3c732017-05-08 17:27:54 -070066 "castFrom", "Proxy", "Stub", "getService",
67
68 // Injected names to Java interfaces by auto-generated code
69 "asInterface", "castFrom", "getService", "toString",
Yifan Hongb16199d2016-12-09 14:49:46 -080070
71 // Inherited methods from IBase is detected in addMethod. Not added here
72 // because we need hidl-gen to compile IBase.
Yifan Hong27e85db2016-11-09 15:45:52 -080073
74 // Inherited names by interfaces from IInterface / IBinder
75 "onAsBinder", "asBinder", "queryLocalInterface", "getInterfaceDescriptor", "isBinderAlive",
Martijn Coenen115d4282016-12-19 05:14:04 +010076 "pingBinder", "dump", "transact", "checkSubclass", "attachObject", "findObject",
77 "detachObject", "localBinder", "remoteBinder", "mImpl",
Yifan Hongf3d3c732017-05-08 17:27:54 -070078
79 // Inherited names from HidlInstrumentor
80 "InstrumentationEvent", "configureInstrumentation", "registerInstrumentationCallbacks",
81 "isInstrumentationLib", "mInstrumentationCal1lbacks", "mEnableInstrumentation",
82 "mInstrumentationLibPackage", "mInterfaceName",
83
84 // Collide with names in BsFoo
85 "mImpl", "addOnewayTask", "mOnewayQueue",
86
87 // Inherited names from Java IHwInterface
88 "asBinder",
Yifan Hong27e85db2016-11-09 15:45:52 -080089 });
Steven Moreland0184ce32017-05-26 14:39:38 -070090 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) {
91 *errorMsg = identifier + " cannot be a name inside an interface";
Yifan Hong27e85db2016-11-09 15:45:52 -080092 return false;
93 }
94 return true;
95}
96
Steven Moreland0184ce32017-05-26 14:39:38 -070097bool isValidStructField(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -080098 static const std::vector<std::string> reserved({
99 // Injected names to structs and unions by auto-generated code
100 "readEmbeddedFromParcel", "writeEmbeddedToParcel", "readVectorFromParcel",
101 "writeVectorToParcel", "writeEmbeddedToBlob",
102 });
Steven Moreland0184ce32017-05-26 14:39:38 -0700103 if (std::find(reserved.begin(), reserved.end(), identifier) != reserved.end()) {
104 *errorMsg = identifier + " cannot be a name inside an struct or union";
Yifan Hong27e85db2016-11-09 15:45:52 -0800105 return false;
106 }
107 return true;
108}
109
Nirav Atre0ab82652018-06-04 11:49:14 -0700110bool isValidCompoundTypeField(CompoundType::Style style, const std::string& identifier,
111 std::string *errorMsg) {
112 // Unions don't support fix-up types; as such, they can't
113 // have name collisions with embedded read/write methods.
114 if (style == CompoundType::STYLE_UNION) { return true; }
115
116 return isValidStructField(identifier, errorMsg);;
117}
118
Steven Moreland0184ce32017-05-26 14:39:38 -0700119bool isValidIdentifier(const std::string& identifier, std::string *errorMsg) {
Yifan Hong27e85db2016-11-09 15:45:52 -0800120 static const std::vector<std::string> keywords({
121 "uint8_t", "uint16_t", "uint32_t", "uint64_t",
122 "int8_t", "int16_t", "int32_t", "int64_t", "bool", "float", "double",
123 "interface", "struct", "union", "string", "vec", "enum", "ref", "handle",
124 "package", "import", "typedef", "generates", "oneway", "extends",
Nirav Atrefd184e82018-06-01 13:35:13 -0700125 "fmq_sync", "fmq_unsync", "safe_union",
Yifan Hong27e85db2016-11-09 15:45:52 -0800126 });
127 static const std::vector<std::string> cppKeywords({
128 "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit",
129 "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch",
130 "char", "char16_t", "char32_t", "class", "compl", "concept", "const", "constexpr",
131 "const_cast", "continue", "decltype", "default", "delete", "do", "double",
132 "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float",
133 "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable",
134 "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
135 "private", "protected", "public", "register", "reinterpret_cast", "requires", "return",
136 "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct",
137 "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try",
138 "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
139 "volatile", "wchar_t", "while", "xor", "xor_eq",
140 });
141 static const std::vector<std::string> javaKeywords({
142 "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package",
143 "synchronized", "boolean", "do", "if", "private", "this", "break", "double",
144 "implements", "protected", "throw", "byte", "else", "import", "public", "throws",
145 "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int",
146 "short", "try", "char", "final", "interface", "static", "void", "class", "finally",
147 "long", "strictfp", "volatile", "const", "float", "native", "super", "while",
148 });
149 static const std::vector<std::string> cppCollide({
150 "size_t", "offsetof",
Yifan Hong27e85db2016-11-09 15:45:52 -0800151 });
152
153 // errors
Steven Moreland0184ce32017-05-26 14:39:38 -0700154 if (std::find(keywords.begin(), keywords.end(), identifier) != keywords.end()) {
155 *errorMsg = identifier + " is a HIDL 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(cppKeywords.begin(), cppKeywords.end(), identifier) != cppKeywords.end()) {
160 *errorMsg = identifier + " is a C++ keyword "
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 (std::find(javaKeywords.begin(), javaKeywords.end(), identifier) != javaKeywords.end()) {
165 *errorMsg = identifier + " is a Java keyword "
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 (std::find(cppCollide.begin(), cppCollide.end(), identifier) != cppCollide.end()) {
170 *errorMsg = identifier + " collides with reserved names in C++ code "
Yifan Hong27e85db2016-11-09 15:45:52 -0800171 "and is therefore not a valid identifier";
172 return false;
173 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700174 if (StringHelper::StartsWith(identifier, "_hidl_")) {
175 *errorMsg = identifier + " starts with _hidl_ "
Yifan Hong27e85db2016-11-09 15:45:52 -0800176 "and is therefore not a valid identifier";
177 return false;
178 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700179 if (StringHelper::StartsWith(identifier, "hidl_")) {
180 *errorMsg = identifier + " starts with hidl_ "
Yifan Hongf3d3c732017-05-08 17:27:54 -0700181 "and is therefore not a valid identifier";
182 return false;
183 }
Steven Moreland0184ce32017-05-26 14:39:38 -0700184 if (StringHelper::EndsWith(identifier, "_cb")) {
185 *errorMsg = identifier + " ends with _cb "
Yifan Hong27e85db2016-11-09 15:45:52 -0800186 "and is therefore not a valid identifier";
187 return false;
188 }
189
Yifan Hongf3d3c732017-05-08 17:27:54 -0700190 return true;
191}
192
193// Return true if identifier is an acceptable name for an UDT.
Steven Moreland0184ce32017-05-26 14:39:38 -0700194bool isValidTypeName(const std::string& identifier, std::string *errorMsg) {
Yifan Hongf3d3c732017-05-08 17:27:54 -0700195 if (!isValidIdentifier(identifier, errorMsg)) {
196 return false;
Yifan Hong27e85db2016-11-09 15:45:52 -0800197 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700198
Steven Moreland0184ce32017-05-26 14:39:38 -0700199 if (identifier == "toString") {
200 *errorMsg = identifier + " is not a valid type name";
Yifan Hongf3d3c732017-05-08 17:27:54 -0700201 return false;
202 }
203
Yifan Hong27e85db2016-11-09 15:45:52 -0800204 return true;
205}
Yifan Honga4b53d02016-10-31 17:29:10 -0700206
Andreas Huberc9410c72016-07-28 12:18:40 -0700207%}
208
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700209%initial-action {
210 // Initialize the initial location.
211 @$.begin.filename = @$.end.filename =
212 const_cast<std::string *>(&ast->getFilename());
213}
214
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700215%parse-param { void* scanner }
216%parse-param { android::AST* const ast }
217%parse-param { android::Scope** const scope }
218%lex-param { void* scanner }
Timur Iskhakov63f39902017-08-29 15:47:29 -0700219%lex-param { android::Scope** const scope }
Andreas Huberc9410c72016-07-28 12:18:40 -0700220%pure-parser
Steven Moreland4ab9b792016-09-26 14:14:07 -0700221%glr-parser
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700222%skeleton "glr.cc"
Andreas Huberc9410c72016-07-28 12:18:40 -0700223
Steven Moreland4ab9b792016-09-26 14:14:07 -0700224%expect-rr 0
Steven Moreland0184ce32017-05-26 14:39:38 -0700225%error-verbose
Steven Moreland4ab9b792016-09-26 14:14:07 -0700226
Steven Moreland073269e2018-05-17 15:45:26 -0700227%debug
228
229%token<docComment> DOC_COMMENT "doc comment"
230
Steven Morelande931e492017-09-07 09:52:18 -0700231%token<void> ENUM "keyword `enum`"
232%token<void> EXTENDS "keyword `extends`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700233%token<str> FQNAME "fully-qualified name"
Steven Morelande931e492017-09-07 09:52:18 -0700234%token<void> GENERATES "keyword `generates`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700235%token<str> IDENTIFIER "identifier"
Steven Morelande931e492017-09-07 09:52:18 -0700236%token<void> IMPORT "keyword `import`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700237%token<str> INTEGER "integer value"
238%token<str> FLOAT "float value"
Steven Morelande931e492017-09-07 09:52:18 -0700239%token<void> INTERFACE "keyword `interface`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700240%token<str> PACKAGE "keyword `package`"
241%token<type> TYPE "type"
Steven Morelande931e492017-09-07 09:52:18 -0700242%token<void> STRUCT "keyword `struct`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700243%token<str> STRING_LITERAL "string literal"
Steven Morelande931e492017-09-07 09:52:18 -0700244%token<void> TYPEDEF "keyword `typedef`"
245%token<void> UNION "keyword `union`"
Nirav Atrefd184e82018-06-01 13:35:13 -0700246%token<void> SAFE_UNION "keyword `safe_union`"
Steven Moreland0184ce32017-05-26 14:39:38 -0700247%token<templatedType> TEMPLATED "templated type"
248%token<void> ONEWAY "keyword `oneway`"
Steven Moreland7a4c6622017-09-07 10:32:20 -0700249%token<str> UNKNOWN "unknown character"
Andreas Huberc9410c72016-07-28 12:18:40 -0700250
Yifan Hong52165692016-08-12 18:06:40 -0700251/* Operator precedence and associativity, as per
252 * http://en.cppreference.com/w/cpp/language/operator_precedence */
253/* Precedence level 15 ternary operator */
254%right '?' ':'
255/* Precedence level 13 - 14, LTR, logical operators*/
256%left LOGICAL_OR
257%left LOGICAL_AND
258/* Precedence level 10 - 12, LTR, bitwise operators*/
259%left '|'
260%left '^'
261%left '&'
262/* Precedence level 9, LTR */
263%left EQUALITY NEQ
264/* Precedence level 8, LTR */
265%left '<' '>' LEQ GEQ
266/* Precedence level 7, LTR */
267%left LSHIFT RSHIFT
268/* Precedence level 6, LTR */
269%left '+' '-'
270/* Precedence level 5, LTR */
271%left '*' '/' '%'
272/* Precedence level 3, RTL; but we have to use %left here */
273%left UNARY_MINUS UNARY_PLUS '!' '~'
274
Steven Moreland12f0ab12018-11-02 17:27:37 -0700275%token '#'
276
Steven Moreland073269e2018-05-17 15:45:26 -0700277%type<docComment> doc_comments
278
Steven Moreland5f809632017-05-17 13:24:36 -0700279%type<str> error_stmt error
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700280%type<str> package
Yifan Hongae16eed2016-09-23 13:25:25 -0700281%type<fqName> fqname
Timur Iskhakov505316c2017-08-05 03:38:59 +0000282%type<referenceToType> fqtype
Yifan Hongf3d3c732017-05-08 17:27:54 -0700283%type<str> valid_identifier valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700284
Timur Iskhakov653caa42017-09-13 21:32:56 -0700285%type<referenceToType> type enum_storage_type type_or_inplace_compound_declaration
Timur Iskhakov505316c2017-08-05 03:38:59 +0000286%type<referenceToType> array_type_base
Yifan Hongbd33e382016-11-02 13:30:17 -0700287%type<arrayType> array_type
Timur Iskhakov0344e612017-08-25 12:57:09 -0700288%type<referenceToType> opt_extends
Steven Moreland073269e2018-05-17 15:45:26 -0700289%type<type> type_declaration commentable_type_declaration type_declaration_body
290%type<type> interface_declaration typedef_declaration
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700291%type<type> named_struct_or_union_declaration named_enum_declaration
292%type<type> compound_declaration annotated_compound_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700293
Steven Moreland073269e2018-05-17 15:45:26 -0700294%type<field> field_declaration commentable_field_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700295%type<fields> field_declarations struct_or_union_body
Yifan Hong52165692016-08-12 18:06:40 -0700296%type<constantExpression> const_expr
Steven Moreland073269e2018-05-17 15:45:26 -0700297%type<enumValue> enum_value commentable_enum_value
Yifan Hongf24fa852016-09-23 11:03:15 -0700298%type<enumValues> enum_values enum_declaration_body
Yifan Hong1a77a4a2018-10-04 17:15:00 -0700299%type<typedVars> typed_vars non_empty_typed_vars
Andreas Huberc9410c72016-07-28 12:18:40 -0700300%type<typedVar> typed_var
Steven Moreland073269e2018-05-17 15:45:26 -0700301%type<method> method_declaration commentable_method_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700302%type<compoundStyle> struct_or_union_keyword
Yifan Hongf24fa852016-09-23 11:03:15 -0700303%type<stringVec> annotation_string_values annotation_string_value
304%type<constExprVec> annotation_const_expr_values annotation_const_expr_value
Andreas Huber3599d922016-08-09 10:42:57 -0700305%type<annotationParam> annotation_param
306%type<annotationParams> opt_annotation_params annotation_params
307%type<annotation> annotation
308%type<annotations> opt_annotations
Andreas Huberc9410c72016-07-28 12:18:40 -0700309
310%start program
311
312%union {
313 const char *str;
Timur Iskhakov505316c2017-08-05 03:38:59 +0000314 android::Type* type;
315 android::Reference<android::Type>* referenceToType;
Yifan Hongbd33e382016-11-02 13:30:17 -0700316 android::ArrayType *arrayType;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700317 android::TemplatedType *templatedType;
Yifan Hongae16eed2016-09-23 13:25:25 -0700318 android::FQName *fqName;
Andreas Huberc9410c72016-07-28 12:18:40 -0700319 android::CompoundType *compoundType;
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700320 android::NamedReference<android::Type>* field;
321 std::vector<android::NamedReference<android::Type>*>* fields;
Andreas Huberc9410c72016-07-28 12:18:40 -0700322 android::EnumValue *enumValue;
Yifan Hong52165692016-08-12 18:06:40 -0700323 android::ConstantExpression *constantExpression;
Andreas Huber881227d2016-08-02 14:20:21 -0700324 std::vector<android::EnumValue *> *enumValues;
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700325 android::NamedReference<android::Type>* typedVar;
Yifan Hong7763ab32016-12-13 17:42:11 -0800326 android::TypedVarVector *typedVars;
Andreas Huberc9410c72016-07-28 12:18:40 -0700327 android::Method *method;
328 android::CompoundType::Style compoundStyle;
Andreas Huber3599d922016-08-09 10:42:57 -0700329 std::vector<std::string> *stringVec;
Yifan Hongf24fa852016-09-23 11:03:15 -0700330 std::vector<android::ConstantExpression *> *constExprVec;
Steven Morelandd537ab02016-09-12 10:32:01 -0700331 android::AnnotationParam *annotationParam;
332 android::AnnotationParamVector *annotationParams;
Andreas Huber3599d922016-08-09 10:42:57 -0700333 android::Annotation *annotation;
Steven Morelandd537ab02016-09-12 10:32:01 -0700334 std::vector<android::Annotation *> *annotations;
Steven Moreland073269e2018-05-17 15:45:26 -0700335 android::DocComment* docComment;
Andreas Huberc9410c72016-07-28 12:18:40 -0700336}
337
338%%
339
Steven Moreland2ee84322017-05-17 13:16:33 -0700340program
Steven Moreland073269e2018-05-17 15:45:26 -0700341 // Don't care if license header is a doc comment or not
342 : DOC_COMMENT package imports type_declarations
343 | package imports type_declarations
344 ;
345
346doc_comments
347 : DOC_COMMENT { $$ = $1; }
348 | doc_comments DOC_COMMENT
349 {
350 $1->merge($2);
351 $$ = $1;
352 }
Steven Morelanda421b312018-06-04 09:43:07 -0700353 | doc_comments '}'
354 {
355 std::cerr << "ERROR: Doc comments must preceed what they describe at " << @1 << "\n";
356 YYERROR;
357 }
Steven Moreland2ee84322017-05-17 13:16:33 -0700358 ;
359
Yifan Hong27e85db2016-11-09 15:45:52 -0800360valid_identifier
361 : IDENTIFIER
362 {
363 std::string errorMsg;
364 if (!isValidIdentifier($1, &errorMsg)) {
365 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
366 YYERROR;
367 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700368 $$ = $1;
369 }
370 ;
371
372valid_type_name
373 : IDENTIFIER
374 {
375 std::string errorMsg;
376 if (!isValidTypeName($1, &errorMsg)) {
377 std::cerr << "ERROR: " << errorMsg << " at " << @1 << "\n";
378 YYERROR;
Yifan Hong27e85db2016-11-09 15:45:52 -0800379 }
380 $$ = $1;
381 }
382 ;
383
Andreas Huber3599d922016-08-09 10:42:57 -0700384opt_annotations
385 : /* empty */
386 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700387 $$ = new std::vector<Annotation *>;
Andreas Huber3599d922016-08-09 10:42:57 -0700388 }
389 | opt_annotations annotation
390 {
391 $$ = $1;
Steven Morelandd537ab02016-09-12 10:32:01 -0700392 $$->push_back($2);
Andreas Huber3599d922016-08-09 10:42:57 -0700393 }
394 ;
395
396annotation
397 : '@' IDENTIFIER opt_annotation_params
398 {
399 $$ = new Annotation($2, $3);
400 }
401 ;
402
403opt_annotation_params
404 : /* empty */
405 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700406 $$ = new AnnotationParamVector;
Andreas Huber3599d922016-08-09 10:42:57 -0700407 }
408 | '(' annotation_params ')'
409 {
410 $$ = $2;
411 }
412 ;
413
414annotation_params
415 : annotation_param
416 {
Steven Morelandd537ab02016-09-12 10:32:01 -0700417 $$ = new AnnotationParamVector;
418 $$->push_back($1);
Andreas Huber3599d922016-08-09 10:42:57 -0700419 }
420 | annotation_params ',' annotation_param
421 {
422 $$ = $1;
Steven Morelandd537ab02016-09-12 10:32:01 -0700423 $$->push_back($3);
Andreas Huber3599d922016-08-09 10:42:57 -0700424 }
425 ;
426
427annotation_param
Yifan Hongf24fa852016-09-23 11:03:15 -0700428 : IDENTIFIER '=' annotation_string_value
429 {
Timur Iskhakov7a85dc22017-08-10 19:06:41 -0700430 $$ = new StringAnnotationParam($1, $3);
Yifan Hongf24fa852016-09-23 11:03:15 -0700431 }
432 | IDENTIFIER '=' annotation_const_expr_value
Andreas Huber3599d922016-08-09 10:42:57 -0700433 {
Timur Iskhakov7a85dc22017-08-10 19:06:41 -0700434 $$ = new ConstantExpressionAnnotationParam($1, $3);
Andreas Huber3599d922016-08-09 10:42:57 -0700435 }
436 ;
437
Yifan Hongf24fa852016-09-23 11:03:15 -0700438annotation_string_value
Andreas Huber3599d922016-08-09 10:42:57 -0700439 : STRING_LITERAL
440 {
441 $$ = new std::vector<std::string>;
442 $$->push_back($1);
443 }
444 | '{' annotation_string_values '}' { $$ = $2; }
445 ;
446
447annotation_string_values
448 : STRING_LITERAL
449 {
450 $$ = new std::vector<std::string>;
451 $$->push_back($1);
452 }
453 | annotation_string_values ',' STRING_LITERAL
454 {
455 $$ = $1;
456 $$->push_back($3);
457 }
458 ;
459
Yifan Hongf24fa852016-09-23 11:03:15 -0700460annotation_const_expr_value
461 : const_expr
462 {
463 $$ = new std::vector<ConstantExpression *>;
464 $$->push_back($1);
465 }
466 | '{' annotation_const_expr_values '}' { $$ = $2; }
467 ;
468
469annotation_const_expr_values
470 : const_expr
471 {
472 $$ = new std::vector<ConstantExpression *>;
473 $$->push_back($1);
474 }
475 | annotation_const_expr_values ',' const_expr
476 {
477 $$ = $1;
478 $$->push_back($3);
479 }
480 ;
481
Yifan Hongbe627b32016-10-28 18:38:56 -0700482error_stmt
483 : error ';'
484 {
485 $$ = $1;
486 ast->addSyntaxError();
Yifan Hongbe627b32016-10-28 18:38:56 -0700487 }
488 ;
489
Yifan Hongbe627b32016-10-28 18:38:56 -0700490require_semicolon
491 : ';'
492 | /* empty */
493 {
494 std::cerr << "ERROR: missing ; at " << @$ << "\n";
495 ast->addSyntaxError();
496 }
497 ;
498
Andreas Huber84f89de2016-07-28 15:39:51 -0700499fqname
500 : FQNAME
501 {
Steven Morelande1b157e2018-03-06 14:18:32 -0800502 $$ = new FQName();
503 if(!FQName::parse($1, $$)) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700504 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at "
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700505 << @1
Yifan Hongae16eed2016-09-23 13:25:25 -0700506 << ".\n";
Andreas Huber84f89de2016-07-28 15:39:51 -0700507 YYERROR;
508 }
509 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700510 | valid_type_name
Andreas Huber84f89de2016-07-28 15:39:51 -0700511 {
Steven Morelande1b157e2018-03-06 14:18:32 -0800512 $$ = new FQName();
513 if(!FQName::parse($1, $$)) {
Yifan Hongae16eed2016-09-23 13:25:25 -0700514 std::cerr << "ERROR: FQName '" << $1 << "' is not valid at "
515 << @1
516 << ".\n";
517 YYERROR;
518 }
519 }
520 ;
521
522fqtype
523 : fqname
524 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000525 $$ = new Reference<Type>(*$1, convertYYLoc(@1));
Andreas Huber84f89de2016-07-28 15:39:51 -0700526 }
Hridya Valsarajucd91bf62016-10-25 12:41:04 -0700527 | TYPE
Timur Iskhakov505316c2017-08-05 03:38:59 +0000528 {
529 $$ = new Reference<Type>($1, convertYYLoc(@1));
530 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700531 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700532
533package
Yifan Hongbe627b32016-10-28 18:38:56 -0700534 : PACKAGE FQNAME require_semicolon
Andreas Hubereb1081f2016-07-28 13:13:24 -0700535 {
Andreas Huber84f89de2016-07-28 15:39:51 -0700536 if (!ast->setPackage($2)) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -0700537 std::cerr << "ERROR: Malformed package identifier '"
538 << $2
539 << "' at "
540 << @2
541 << "\n";
542
Andreas Huber84f89de2016-07-28 15:39:51 -0700543 YYERROR;
544 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700545 }
Steven Moreland5f809632017-05-17 13:24:36 -0700546 | error
547 {
548 std::cerr << "ERROR: Package statement must be at the beginning of the file (" << @1 << ")\n";
549 $$ = $1;
550 ast->addSyntaxError();
551 }
552 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700553
Yifan Hongbe627b32016-10-28 18:38:56 -0700554import_stmt
555 : IMPORT FQNAME require_semicolon
556 {
557 if (!ast->addImport($2)) {
558 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
559 << "\n";
560 ast->addSyntaxError();
561 }
562 }
Yifan Hongf3d3c732017-05-08 17:27:54 -0700563 | IMPORT valid_type_name require_semicolon
Yifan Hongbe627b32016-10-28 18:38:56 -0700564 {
565 if (!ast->addImport($2)) {
566 std::cerr << "ERROR: Unable to import '" << $2 << "' at " << @2
567 << "\n";
568 ast->addSyntaxError();
569 }
570 }
571 | IMPORT error_stmt
572 ;
573
574
Andreas Huberc9410c72016-07-28 12:18:40 -0700575imports
576 : /* empty */
Yifan Hongbe627b32016-10-28 18:38:56 -0700577 | imports import_stmt
Andreas Huberc9410c72016-07-28 12:18:40 -0700578 ;
579
580opt_extends
Timur Iskhakov0344e612017-08-25 12:57:09 -0700581 : /* empty */ { $$ = nullptr; }
582 | EXTENDS fqtype { $$ = $2; }
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700583 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700584
Andreas Huberc9410c72016-07-28 12:18:40 -0700585interface_declarations
586 : /* empty */
Steven Moreland073269e2018-05-17 15:45:26 -0700587 | interface_declarations commentable_type_declaration
Yifan Hong27e85db2016-11-09 15:45:52 -0800588 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700589 CHECK((*scope)->isInterface());
590
Yifan Hong27e85db2016-11-09 15:45:52 -0800591 std::string errorMsg;
Timur Iskhakov505316c2017-08-05 03:38:59 +0000592 if ($2 != nullptr && $2->isNamedType() &&
593 !isValidInterfaceField(static_cast<NamedType*>($2)->localName().c_str(),
Yifan Hong27e85db2016-11-09 15:45:52 -0800594 &errorMsg)) {
595 std::cerr << "ERROR: " << errorMsg << " at "
596 << @2 << "\n";
597 YYERROR;
598 }
599 }
Steven Moreland073269e2018-05-17 15:45:26 -0700600 | interface_declarations commentable_method_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700601 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700602 CHECK((*scope)->isInterface());
603
Yifan Hong27e85db2016-11-09 15:45:52 -0800604 std::string errorMsg;
605 if ($2 != nullptr &&
606 !isValidInterfaceField($2->name().c_str(), &errorMsg)) {
607 std::cerr << "ERROR: " << errorMsg << " at "
608 << @2 << "\n";
609 YYERROR;
610 }
611
Yifan Hongbe627b32016-10-28 18:38:56 -0700612 if ($2 != nullptr) {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000613 Interface *iface = static_cast<Interface*>(*scope);
Yifan Hongbe627b32016-10-28 18:38:56 -0700614 if (!iface->addMethod($2)) {
615 std::cerr << "ERROR: Unable to add method '" << $2->name()
616 << "' at " << @2 << "\n";
617
618 YYERROR;
619 }
Steven Moreland14ee6742016-10-18 12:58:28 -0700620 }
Yifan Hongbe627b32016-10-28 18:38:56 -0700621 // ignore if $2 is nullptr (from error recovery)
Andreas Huberc9410c72016-07-28 12:18:40 -0700622 }
623 ;
624
625type_declarations
Andreas Hubera2723d22016-07-29 15:36:07 -0700626 : /* empty */
Yifan Hongbe627b32016-10-28 18:38:56 -0700627 | error_stmt
Steven Moreland073269e2018-05-17 15:45:26 -0700628 | type_declarations commentable_type_declaration
629 ;
630
631commentable_type_declaration
632 : doc_comments type_declaration
633 {
634 $2->setDocComment($1);
635 $$ = $2;
636 }
637 | type_declaration { $$ = $1; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700638 ;
639
640type_declaration
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700641 : opt_annotations type_declaration_body
642 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000643 if (!$2->isTypeDef()) {
Timur Iskhakove9ccfa22017-08-14 15:07:03 -0700644 CHECK($2->isScope());
645 static_cast<Scope*>($2)->setAnnotations($1);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700646 } else if (!$1->empty()) {
647 // Since typedefs are always resolved to their target it makes
648 // little sense to annotate them and have their annotations
649 // impose semantics other than their target type.
Timur Iskhakov76533c52017-08-25 13:02:05 -0700650 std::cerr << "ERROR: typedefs cannot be annotated at " << @2
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700651 << "\n";
652
653 YYERROR;
654 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800655 $$ = $2;
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700656 }
657 ;
658
659type_declaration_body
Yifan Hongbe627b32016-10-28 18:38:56 -0700660 : named_struct_or_union_declaration require_semicolon
661 | named_enum_declaration require_semicolon
662 | typedef_declaration require_semicolon
663 | interface_declaration require_semicolon
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700664 ;
665
666interface_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700667 : INTERFACE valid_type_name opt_extends
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700668 {
Timur Iskhakov0344e612017-08-25 12:57:09 -0700669 Reference<Type>* superType = $3;
Steven Morelande1b157e2018-03-06 14:18:32 -0800670 bool isIBase = ast->package().package() == gIBaseFqName.package();
Yifan Hongc8934042016-11-17 17:10:52 -0800671
Timur Iskhakov505316c2017-08-05 03:38:59 +0000672 if (isIBase) {
673 if (superType != nullptr) {
Timur Iskhakov76533c52017-08-25 13:02:05 -0700674 std::cerr << "ERROR: IBase must not extend any interface at " << @3
Timur Iskhakov505316c2017-08-05 03:38:59 +0000675 << "\n";
676
677 YYERROR;
678 }
Timur Iskhakov0344e612017-08-25 12:57:09 -0700679 superType = new Reference<Type>();
Timur Iskhakov505316c2017-08-05 03:38:59 +0000680 } else {
Yifan Hongc8934042016-11-17 17:10:52 -0800681 if (!ast->addImport(gIBaseFqName.string().c_str())) {
682 std::cerr << "ERROR: Unable to automatically import '"
683 << gIBaseFqName.string()
684 << "' at " << @$
685 << "\n";
686 YYERROR;
687 }
Timur Iskhakov505316c2017-08-05 03:38:59 +0000688
689 if (superType == nullptr) {
Timur Iskhakov0344e612017-08-25 12:57:09 -0700690 superType = new Reference<Type>(gIBaseFqName, convertYYLoc(@$));
Yifan Hongc8934042016-11-17 17:10:52 -0800691 }
692 }
693
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700694 if ($2[0] != 'I') {
695 std::cerr << "ERROR: All interface names must start with an 'I' "
Timur Iskhakov76533c52017-08-25 13:02:05 -0700696 << "prefix at " << @2 << "\n";
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700697
698 YYERROR;
699 }
700
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700701 if (*scope != ast->getRootScope()) {
702 std::cerr << "ERROR: All interface must declared in "
Timur Iskhakov76533c52017-08-25 13:02:05 -0700703 << "global scope at " << @2 << "\n";
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700704
705 YYERROR;
706 }
707
708 Interface* iface = new Interface(
Steven Moreland04dea8d2018-02-06 13:11:24 -0800709 $2, ast->makeFullName($2, *scope), convertYYLoc(@2),
710 *scope, *superType, ast->getFileHash());
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700711
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700712 enterScope(ast, scope, iface);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700713 }
714 '{' interface_declarations '}'
715 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700716 CHECK((*scope)->isInterface());
Yifan Hongbe627b32016-10-28 18:38:56 -0700717
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700718 Interface *iface = static_cast<Interface *>(*scope);
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700719 CHECK(iface->addAllReservedMethods());
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700720
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700721 leaveScope(ast, scope);
Timur Iskhakovb0664f22017-09-12 17:43:13 -0700722 ast->addScopedType(iface, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700723 $$ = iface;
724 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700725 ;
726
727typedef_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700728 : TYPEDEF type valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700729 {
Timur Iskhakov505316c2017-08-05 03:38:59 +0000730 // The reason we wrap the given type in a TypeDef is simply to suppress
731 // emitting any type definitions later on, since this is just an alias
732 // to a type defined elsewhere.
Timur Iskhakov565b0132017-09-06 18:07:11 -0700733 TypeDef* typeDef = new TypeDef(
734 $3, ast->makeFullName($3, *scope), convertYYLoc(@2), *scope, *$2);
735 ast->addScopedType(typeDef, *scope);
Timur Iskhakov505316c2017-08-05 03:38:59 +0000736 $$ = typeDef;
Andreas Huberc9410c72016-07-28 12:18:40 -0700737 }
738 ;
739
Yifan Hong52165692016-08-12 18:06:40 -0700740const_expr
Steven Moreland12f0ab12018-11-02 17:27:37 -0700741 : INTEGER
742 {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700743 $$ = LiteralConstantExpression::tryParse($1);
744
745 if ($$ == nullptr) {
746 std::cerr << "ERROR: Could not parse literal: "
747 << $1 << " at " << @1 << ".\n";
748 YYERROR;
749 }
750 }
Yifan Hongb44a6c82016-09-22 15:50:18 -0700751 | fqname
752 {
Yifan Hongf24fa852016-09-23 11:03:15 -0700753 if(!$1->isValidValueName()) {
754 std::cerr << "ERROR: '" << $1->string()
755 << "' does not refer to an enum value at "
756 << @1 << ".\n";
757 YYERROR;
758 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000759
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700760 $$ = new ReferenceConstantExpression(
761 Reference<LocalIdentifier>(*$1, convertYYLoc(@1)), $1->string());
Yifan Hongb44a6c82016-09-22 15:50:18 -0700762 }
Steven Moreland12f0ab12018-11-02 17:27:37 -0700763 | fqname '#' IDENTIFIER
764 {
765 $$ = new AttributeConstantExpression(
766 Reference<Type>(*$1, convertYYLoc(@1)), $1->string(), $3);
767 }
Yifan Hong52165692016-08-12 18:06:40 -0700768 | const_expr '?' const_expr ':' const_expr
769 {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000770 $$ = new TernaryConstantExpression($1, $3, $5);
Yifan Hong52165692016-08-12 18:06:40 -0700771 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000772 | const_expr LOGICAL_OR const_expr { $$ = new BinaryConstantExpression($1, "||", $3); }
773 | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); }
774 | const_expr '|' const_expr { $$ = new BinaryConstantExpression($1, "|" , $3); }
775 | const_expr '^' const_expr { $$ = new BinaryConstantExpression($1, "^" , $3); }
776 | const_expr '&' const_expr { $$ = new BinaryConstantExpression($1, "&" , $3); }
777 | const_expr EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); }
778 | const_expr NEQ const_expr { $$ = new BinaryConstantExpression($1, "!=", $3); }
779 | const_expr '<' const_expr { $$ = new BinaryConstantExpression($1, "<" , $3); }
780 | const_expr '>' const_expr { $$ = new BinaryConstantExpression($1, ">" , $3); }
781 | const_expr LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); }
782 | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); }
783 | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); }
784 | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); }
785 | const_expr '+' const_expr { $$ = new BinaryConstantExpression($1, "+" , $3); }
786 | const_expr '-' const_expr { $$ = new BinaryConstantExpression($1, "-" , $3); }
787 | const_expr '*' const_expr { $$ = new BinaryConstantExpression($1, "*" , $3); }
788 | const_expr '/' const_expr { $$ = new BinaryConstantExpression($1, "/" , $3); }
789 | const_expr '%' const_expr { $$ = new BinaryConstantExpression($1, "%" , $3); }
790 | '+' const_expr %prec UNARY_PLUS { $$ = new UnaryConstantExpression("+", $2); }
791 | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); }
792 | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); }
793 | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); }
Yifan Hong52165692016-08-12 18:06:40 -0700794 | '(' const_expr ')' { $$ = $2; }
Yifan Hongbe627b32016-10-28 18:38:56 -0700795 | '(' error ')'
796 {
797 ast->addSyntaxError();
798 // to avoid segfaults
Timur Iskhakov7296af12017-08-09 21:52:48 +0000799 $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release();
Yifan Hongbe627b32016-10-28 18:38:56 -0700800 }
Yifan Hong52165692016-08-12 18:06:40 -0700801 ;
802
Steven Moreland073269e2018-05-17 15:45:26 -0700803commentable_method_declaration
804 : doc_comments method_declaration
805 {
806 if ($2 != nullptr) $2->setDocComment($1);
807 $$ = $2;
808 }
809 | method_declaration
810 {
811 $$ = $1;
812 }
813
Andreas Huberc9410c72016-07-28 12:18:40 -0700814method_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700815 : error_stmt { $$ = nullptr; }
Yifan Hong27e85db2016-11-09 15:45:52 -0800816 | opt_annotations valid_identifier '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700817 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700818 $$ = new Method($2 /* name */,
819 $4 /* args */,
820 new std::vector<NamedReference<Type>*> /* results */,
821 false /* oneway */,
822 $1 /* annotations */,
823 convertYYLoc(@$));
Iliyan Malchev639bff82016-08-13 14:24:11 -0700824 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800825 | opt_annotations ONEWAY valid_identifier '(' typed_vars ')' require_semicolon
Iliyan Malchev639bff82016-08-13 14:24:11 -0700826 {
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700827 $$ = new Method($3 /* name */,
828 $5 /* args */,
829 new std::vector<NamedReference<Type>*> /* results */,
830 true /* oneway */,
831 $1 /* annotations */,
832 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700833 }
Yifan Hong27e85db2016-11-09 15:45:52 -0800834 | opt_annotations valid_identifier '(' typed_vars ')' GENERATES '(' typed_vars ')' require_semicolon
Andreas Huberc9410c72016-07-28 12:18:40 -0700835 {
Steven Moreland1a4572c2018-01-03 14:20:36 -0800836 if ($8->empty()) {
837 std::cerr << "ERROR: generates clause used without result at " << @1 << "\n";
838 ast->addSyntaxError();
839 }
840
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700841 $$ = new Method($2 /* name */,
842 $4 /* args */,
843 $8 /* results */,
844 false /* oneway */,
845 $1 /* annotations */,
846 convertYYLoc(@$));
Andreas Huberc9410c72016-07-28 12:18:40 -0700847 }
848 ;
849
850typed_vars
851 : /* empty */
852 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800853 $$ = new TypedVarVector();
Andreas Huberc9410c72016-07-28 12:18:40 -0700854 }
Yifan Hong1a77a4a2018-10-04 17:15:00 -0700855 | non_empty_typed_vars
856 {
857 $$ = $1;
858 }
859 ;
860
861non_empty_typed_vars
862 : typed_var
Andreas Huberc9410c72016-07-28 12:18:40 -0700863 {
Yifan Hong7763ab32016-12-13 17:42:11 -0800864 $$ = new TypedVarVector();
865 if (!$$->add($1)) {
866 std::cerr << "ERROR: duplicated argument or result name "
867 << $1->name() << " at " << @1 << "\n";
868 ast->addSyntaxError();
869 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700870 }
Yifan Hong1a77a4a2018-10-04 17:15:00 -0700871 | non_empty_typed_vars ',' typed_var
Andreas Huberc9410c72016-07-28 12:18:40 -0700872 {
873 $$ = $1;
Yifan Hong7763ab32016-12-13 17:42:11 -0800874 if (!$$->add($3)) {
875 std::cerr << "ERROR: duplicated argument or result name "
876 << $3->name() << " at " << @3 << "\n";
877 ast->addSyntaxError();
878 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700879 }
880 ;
881
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700882typed_var
883 : type valid_identifier
884 {
885 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
886 }
Steven Morelandd623a9c2018-02-02 12:58:14 -0800887 | type
888 {
889 $$ = new NamedReference<Type>("", *$1, convertYYLoc(@1));
890
891 const std::string typeName = $$->isResolved()
892 ? $$->get()->typeName() : $$->getLookupFqName().string();
893
894 std::cerr << "ERROR: variable of type " << typeName
895 << " is missing a variable name at " << @1 << "\n";
896 ast->addSyntaxError();
897 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700898 ;
899
900
901struct_or_union_keyword
902 : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
903 | UNION { $$ = CompoundType::STYLE_UNION; }
Nirav Atre0ab82652018-06-04 11:49:14 -0700904 | SAFE_UNION { $$ = CompoundType::STYLE_SAFE_UNION; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700905 ;
906
907named_struct_or_union_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -0700908 : struct_or_union_keyword valid_type_name
Andreas Huberc9410c72016-07-28 12:18:40 -0700909 {
Timur Iskhakov565b0132017-09-06 18:07:11 -0700910 CompoundType *container = new CompoundType(
911 $1, $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *scope);
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700912 enterScope(ast, scope, container);
Andreas Huberc9410c72016-07-28 12:18:40 -0700913 }
914 struct_or_union_body
915 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700916 CHECK((*scope)->isCompoundType());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700917 CompoundType *container = static_cast<CompoundType *>(*scope);
Timur Iskhakovcec46c42017-08-09 00:22:02 -0700918 container->setFields($4);
Andreas Huber5a545442016-08-03 10:44:56 -0700919
Timur Iskhakovcb0ba522017-07-17 20:01:37 -0700920 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -0700921 ast->addScopedType(container, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700922 $$ = container;
Andreas Huberc9410c72016-07-28 12:18:40 -0700923 }
924 ;
925
Andreas Huberc9410c72016-07-28 12:18:40 -0700926struct_or_union_body
927 : '{' field_declarations '}' { $$ = $2; }
928 ;
929
930field_declarations
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700931 : /* empty */ { $$ = new std::vector<NamedReference<Type>*>; }
Steven Moreland073269e2018-05-17 15:45:26 -0700932 | field_declarations commentable_field_declaration
Andreas Huberc9410c72016-07-28 12:18:40 -0700933 {
934 $$ = $1;
935
Timur Iskhakov505316c2017-08-05 03:38:59 +0000936 // Compound declaration or error
937 if ($2 != nullptr) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700938 $$->push_back($2);
939 }
940 }
941 ;
942
Steven Moreland073269e2018-05-17 15:45:26 -0700943commentable_field_declaration
944 : doc_comments field_declaration
945 {
946 if ($2 != nullptr) $2->setDocComment($1);
947 $$ = $2;
948 }
949 | field_declaration { $$ = $1; }
950
Andreas Huberc9410c72016-07-28 12:18:40 -0700951field_declaration
Yifan Hongbe627b32016-10-28 18:38:56 -0700952 : error_stmt { $$ = nullptr; }
Timur Iskhakov653caa42017-09-13 21:32:56 -0700953 | type_or_inplace_compound_declaration valid_identifier require_semicolon
Yifan Hong27e85db2016-11-09 15:45:52 -0800954 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700955 CHECK((*scope)->isCompoundType());
956
957 std::string errorMsg;
Nirav Atre0ab82652018-06-04 11:49:14 -0700958 auto style = static_cast<CompoundType *>(*scope)->style();
959
960 if (!isValidCompoundTypeField(style, $2, &errorMsg)) {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700961 std::cerr << "ERROR: " << errorMsg << " at "
962 << @2 << "\n";
963 YYERROR;
964 }
Timur Iskhakova48a4d92017-09-09 20:34:53 -0700965 $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2));
Yifan Hong27e85db2016-11-09 15:45:52 -0800966 }
967 | annotated_compound_declaration ';'
968 {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700969 CHECK((*scope)->isCompoundType());
970
971 std::string errorMsg;
Nirav Atre0ab82652018-06-04 11:49:14 -0700972 auto style = static_cast<CompoundType *>(*scope)->style();
973
974 if ($1 != nullptr && $1->isNamedType() &&
975 !isValidCompoundTypeField(style, static_cast<NamedType*>(
976 $1)->localName().c_str(), &errorMsg)) {
Timur Iskhakove94e2e12017-08-10 18:52:34 -0700977 std::cerr << "ERROR: " << errorMsg << " at "
978 << @2 << "\n";
979 YYERROR;
980 }
981 // Returns fields only
982 $$ = nullptr;
Yifan Hong27e85db2016-11-09 15:45:52 -0800983 }
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700984 ;
985
986annotated_compound_declaration
987 : opt_annotations compound_declaration
988 {
Timur Iskhakove9ccfa22017-08-14 15:07:03 -0700989 CHECK($2->isScope());
990 static_cast<Scope*>($2)->setAnnotations($1);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -0700991 $$ = $2;
992 }
993 ;
994
995compound_declaration
Yifan Honga2855012016-10-11 13:36:54 -0700996 : named_struct_or_union_declaration { $$ = $1; }
Yifan Hong6a2fedf2016-10-11 13:44:07 -0700997 | named_enum_declaration { $$ = $1; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700998 ;
999
Steven Moreland1c71fd52016-11-29 14:03:33 -08001000enum_storage_type
Timur Iskhakovcec46c42017-08-09 00:22:02 -07001001 : ':' fqtype { $$ = $2; }
Steven Moreland37d26112017-09-20 16:15:19 -07001002 | /* empty */ { $$ = nullptr; }
Andreas Huberc9410c72016-07-28 12:18:40 -07001003 ;
1004
1005opt_comma
1006 : /* empty */
1007 | ','
1008 ;
1009
1010named_enum_declaration
Yifan Hongf3d3c732017-05-08 17:27:54 -07001011 : ENUM valid_type_name enum_storage_type
Andreas Huberc9410c72016-07-28 12:18:40 -07001012 {
Steven Moreland37d26112017-09-20 16:15:19 -07001013 auto storageType = $3;
1014
1015 if (storageType == nullptr) {
1016 std::cerr << "ERROR: Must explicitly specify enum storage type for "
1017 << $2 << " at " << @2 << "\n";
1018 ast->addSyntaxError();
1019 storageType = new Reference<Type>(
1020 new ScalarType(ScalarType::KIND_INT64, *scope), convertYYLoc(@2));
1021 }
1022
Timur Iskhakov565b0132017-09-06 18:07:11 -07001023 EnumType* enumType = new EnumType(
Steven Moreland37d26112017-09-20 16:15:19 -07001024 $2, ast->makeFullName($2, *scope), convertYYLoc(@2), *storageType, *scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -07001025 enterScope(ast, scope, enumType);
Yifan Hongf24fa852016-09-23 11:03:15 -07001026 }
1027 enum_declaration_body
1028 {
Steven Moreland9ecf3732017-08-04 10:31:21 -07001029 CHECK((*scope)->isEnum());
Timur Iskhakov565b0132017-09-06 18:07:11 -07001030 EnumType* enumType = static_cast<EnumType*>(*scope);
Yifan Hongbe627b32016-10-28 18:38:56 -07001031
Timur Iskhakovcb0ba522017-07-17 20:01:37 -07001032 leaveScope(ast, scope);
Timur Iskhakov565b0132017-09-06 18:07:11 -07001033 ast->addScopedType(enumType, *scope);
Andreas Huber7c5ddfb2016-09-29 13:45:22 -07001034 $$ = enumType;
Andreas Huberc9410c72016-07-28 12:18:40 -07001035 }
1036 ;
1037
Yifan Hongf24fa852016-09-23 11:03:15 -07001038enum_declaration_body
1039 : '{' enum_values opt_comma '}' { $$ = $2; }
1040 ;
1041
Steven Moreland073269e2018-05-17 15:45:26 -07001042commentable_enum_value
1043 : doc_comments enum_value
1044 {
1045 $2->setDocComment($1);
1046 $$ = $2;
1047 }
1048 | enum_value { $$ = $1; }
1049 ;
1050
Andreas Huberc9410c72016-07-28 12:18:40 -07001051enum_value
Timur Iskhakovcec46c42017-08-09 00:22:02 -07001052 : valid_identifier
1053 {
1054 $$ = new EnumValue($1 /* name */, nullptr /* value */, convertYYLoc(@$));
1055 }
1056 | valid_identifier '=' const_expr
1057 {
1058 $$ = new EnumValue($1 /* name */, $3 /* value */, convertYYLoc(@$));
1059 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001060 ;
1061
1062enum_values
1063 : /* empty */
Yifan Hongf24fa852016-09-23 11:03:15 -07001064 { /* do nothing */ }
Steven Moreland073269e2018-05-17 15:45:26 -07001065 | commentable_enum_value
Andreas Huberc9410c72016-07-28 12:18:40 -07001066 {
Steven Moreland9ecf3732017-08-04 10:31:21 -07001067 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -07001068 static_cast<EnumType *>(*scope)->addValue($1);
Andreas Huberc9410c72016-07-28 12:18:40 -07001069 }
Steven Moreland073269e2018-05-17 15:45:26 -07001070 | enum_values ',' commentable_enum_value
Andreas Huberc9410c72016-07-28 12:18:40 -07001071 {
Steven Moreland9ecf3732017-08-04 10:31:21 -07001072 CHECK((*scope)->isEnum());
Timur Iskhakovcb0ba522017-07-17 20:01:37 -07001073 static_cast<EnumType *>(*scope)->addValue($3);
Andreas Huberc9410c72016-07-28 12:18:40 -07001074 }
Steven Moreland073269e2018-05-17 15:45:26 -07001075 | error ',' commentable_enum_value
Steven Moreland9ecf3732017-08-04 10:31:21 -07001076 {
1077 ast->addSyntaxError();
1078
1079 CHECK((*scope)->isEnum());
1080 static_cast<EnumType *>(*scope)->addValue($3);
1081 }
Steven Moreland073269e2018-05-17 15:45:26 -07001082 | enum_values ',' error ',' commentable_enum_value
Steven Moreland9ecf3732017-08-04 10:31:21 -07001083 {
1084 ast->addSyntaxError();
1085
1086 CHECK((*scope)->isEnum());
1087 static_cast<EnumType *>(*scope)->addValue($5);
1088 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001089 ;
1090
Yifan Hongbd33e382016-11-02 13:30:17 -07001091array_type_base
Yifan Hongae16eed2016-09-23 13:25:25 -07001092 : fqtype { $$ = $1; }
Yifan Hongbf459bc2016-08-23 16:50:37 -07001093 | TEMPLATED '<' type '>'
Andreas Huberb95ea8a2016-08-15 15:35:42 -07001094 {
Timur Iskhakov505316c2017-08-05 03:38:59 +00001095 $1->setElementType(*$3);
1096 $$ = new Reference<Type>($1, convertYYLoc(@1));
Yifan Hongbf459bc2016-08-23 16:50:37 -07001097 }
1098 | TEMPLATED '<' TEMPLATED '<' type RSHIFT
1099 {
Timur Iskhakov505316c2017-08-05 03:38:59 +00001100 $3->setElementType(*$5);
Timur Iskhakov505316c2017-08-05 03:38:59 +00001101 $1->setElementType(Reference<Type>($3, convertYYLoc(@3)));
1102 $$ = new Reference<Type>($1, convertYYLoc(@1));
Andreas Huberb95ea8a2016-08-15 15:35:42 -07001103 }
Yifan Hongbd33e382016-11-02 13:30:17 -07001104 ;
1105
1106array_type
1107 : array_type_base '[' const_expr ']'
1108 {
Timur Iskhakov0737c2a2017-08-31 10:57:28 -07001109 $$ = new ArrayType(*$1, $3, *scope);
Yifan Hongbd33e382016-11-02 13:30:17 -07001110 }
1111 | array_type '[' const_expr ']'
1112 {
1113 $$ = $1;
1114 $$->appendDimension($3);
1115 }
1116 ;
1117
1118type
1119 : array_type_base { $$ = $1; }
Timur Iskhakov505316c2017-08-05 03:38:59 +00001120 | array_type { $$ = new Reference<Type>($1, convertYYLoc(@1)); }
Yifan Hongc8934042016-11-17 17:10:52 -08001121 | INTERFACE
1122 {
1123 // "interface" is a synonym of android.hidl.base@1.0::IBase
Timur Iskhakov505316c2017-08-05 03:38:59 +00001124 $$ = new Reference<Type>(gIBaseFqName, convertYYLoc(@1));
Yifan Hongc8934042016-11-17 17:10:52 -08001125 }
Andreas Huberc9410c72016-07-28 12:18:40 -07001126 ;
1127
Timur Iskhakov653caa42017-09-13 21:32:56 -07001128type_or_inplace_compound_declaration
1129 : type { $$ = $1; }
1130 | annotated_compound_declaration
1131 {
1132 $$ = new Reference<Type>($1, convertYYLoc(@1));
1133 }
1134 ;
1135
Andreas Huberc9410c72016-07-28 12:18:40 -07001136%%
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001137
Andreas Huber0d0f9a22016-08-17 10:26:11 -07001138void yy::parser::error(
1139 const yy::parser::location_type &where,
1140 const std::string &errstr) {
1141 std::cerr << "ERROR: " << errstr << " at " << where << "\n";
1142}
1143