blob: 813bd2ec049a7fd3fcc19d524a5dc73f162c9bcd [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001%{
2
Andreas Huber3599d922016-08-09 10:42:57 -07003#include "Annotation.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07004#include "AST.h"
5#include "ArrayType.h"
6#include "CompoundType.h"
7#include "Constant.h"
Yifan Hong52165692016-08-12 18:06:40 -07008#include "ConstantExpression.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07009#include "EnumType.h"
10#include "Interface.h"
11#include "Method.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070012#include "TypeDef.h"
13#include "VectorType.h"
14
15#include "hidl-gen_y.h"
16
17#include <stdio.h>
Andreas Huber84f89de2016-07-28 15:39:51 -070018#include <utils/String8.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070019
20using namespace android;
21
22extern int yylex(YYSTYPE *yylval_param, void *yyscanner);
23extern int column;
24
Andreas Hubereb1081f2016-07-28 13:13:24 -070025int yyerror(AST *, const char *s) {
Andreas Huberc9410c72016-07-28 12:18:40 -070026 fflush(stdout);
27 printf("\n%*s\n%*s\n", column, "^", column, s);
28
29 return 0;
30}
31
32#define scanner ast->scanner()
33
34%}
35
36%parse-param { android::AST *ast }
37%lex-param { void *scanner }
38%pure-parser
39
40%token<str> CONST
41%token<str> ENUM
42%token<str> EXTENDS
Andreas Huber84f89de2016-07-28 15:39:51 -070043%token<str> FQNAME
Andreas Huberc9410c72016-07-28 12:18:40 -070044%token<str> GENERATES
45%token<str> IDENTIFIER
46%token<str> IMPORT
47%token<str> INTEGER
Yifan Hong52165692016-08-12 18:06:40 -070048%token<str> FLOAT
Andreas Huberc9410c72016-07-28 12:18:40 -070049%token<str> INTERFACE
50%token<str> PACKAGE
Andreas Huber84f89de2016-07-28 15:39:51 -070051%token<type> SCALAR
Andreas Huberc9410c72016-07-28 12:18:40 -070052%token<str> STRUCT
53%token<str> STRING_LITERAL
54%token<str> TYPEDEF
55%token<str> UNION
56%token<str> VEC
Iliyan Malchev639bff82016-08-13 14:24:11 -070057%token<void> ONEWAY
Andreas Huberc9410c72016-07-28 12:18:40 -070058
Yifan Hong52165692016-08-12 18:06:40 -070059/* Operator precedence and associativity, as per
60 * http://en.cppreference.com/w/cpp/language/operator_precedence */
61/* Precedence level 15 ternary operator */
62%right '?' ':'
63/* Precedence level 13 - 14, LTR, logical operators*/
64%left LOGICAL_OR
65%left LOGICAL_AND
66/* Precedence level 10 - 12, LTR, bitwise operators*/
67%left '|'
68%left '^'
69%left '&'
70/* Precedence level 9, LTR */
71%left EQUALITY NEQ
72/* Precedence level 8, LTR */
73%left '<' '>' LEQ GEQ
74/* Precedence level 7, LTR */
75%left LSHIFT RSHIFT
76/* Precedence level 6, LTR */
77%left '+' '-'
78/* Precedence level 5, LTR */
79%left '*' '/' '%'
80/* Precedence level 3, RTL; but we have to use %left here */
81%left UNARY_MINUS UNARY_PLUS '!' '~'
82
Andreas Huberc9410c72016-07-28 12:18:40 -070083%type<str> optIdentifier package
84%type<str> const_value
Andreas Huber84f89de2016-07-28 15:39:51 -070085%type<type> fqname
Andreas Huberc9410c72016-07-28 12:18:40 -070086
87%type<type> type opt_storage_type
88%type<type> enum_declaration
89%type<type> struct_or_union_declaration
90%type<type> opt_extends
91
92%type<field> field_declaration
93%type<fields> field_declarations struct_or_union_body
Yifan Hong52165692016-08-12 18:06:40 -070094%type<constantExpression> const_expr
Andreas Huberc9410c72016-07-28 12:18:40 -070095%type<enumValue> enum_value
96%type<enumValues> enum_values
97%type<typedVars> typed_vars
98%type<typedVar> typed_var
99%type<method> method_declaration
100%type<compoundStyle> struct_or_union_keyword
Andreas Huber3599d922016-08-09 10:42:57 -0700101%type<stringVec> annotation_string_values annotation_value
102%type<annotationParam> annotation_param
103%type<annotationParams> opt_annotation_params annotation_params
104%type<annotation> annotation
105%type<annotations> opt_annotations
Andreas Huberc9410c72016-07-28 12:18:40 -0700106
107%start program
108
109%union {
110 const char *str;
111 android::Type *type;
112 android::CompoundType *compoundType;
113 android::CompoundField *field;
Andreas Huber881227d2016-08-02 14:20:21 -0700114 std::vector<android::CompoundField *> *fields;
Andreas Huberc9410c72016-07-28 12:18:40 -0700115 android::EnumValue *enumValue;
Yifan Hong52165692016-08-12 18:06:40 -0700116 android::ConstantExpression *constantExpression;
Andreas Huber881227d2016-08-02 14:20:21 -0700117 std::vector<android::EnumValue *> *enumValues;
Andreas Huberc9410c72016-07-28 12:18:40 -0700118 android::TypedVar *typedVar;
Andreas Huber881227d2016-08-02 14:20:21 -0700119 std::vector<android::TypedVar *> *typedVars;
Andreas Huberc9410c72016-07-28 12:18:40 -0700120 android::Method *method;
121 android::CompoundType::Style compoundStyle;
Andreas Huber3599d922016-08-09 10:42:57 -0700122 std::vector<std::string> *stringVec;
123 std::pair<std::string, std::vector<std::string> *> *annotationParam;
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700124 android::DefaultKeyedVector<std::string, std::vector<std::string> *> *annotationParams;
Andreas Huber3599d922016-08-09 10:42:57 -0700125 android::Annotation *annotation;
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700126 android::DefaultKeyedVector<std::string, android::Annotation *> *annotations;
Andreas Huberc9410c72016-07-28 12:18:40 -0700127}
128
129%%
130
Andreas Huber3599d922016-08-09 10:42:57 -0700131opt_annotations
132 : /* empty */
133 {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700134 $$ = new DefaultKeyedVector<std::string, Annotation *>;
Andreas Huber3599d922016-08-09 10:42:57 -0700135 }
136 | opt_annotations annotation
137 {
138 $$ = $1;
139 $$->add($2->name(), $2);
140 }
141 ;
142
143annotation
144 : '@' IDENTIFIER opt_annotation_params
145 {
146 $$ = new Annotation($2, $3);
147 }
148 ;
149
150opt_annotation_params
151 : /* empty */
152 {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700153 $$ = new DefaultKeyedVector<std::string, std::vector<std::string> *>;
Andreas Huber3599d922016-08-09 10:42:57 -0700154 }
155 | '(' annotation_params ')'
156 {
157 $$ = $2;
158 }
159 ;
160
161annotation_params
162 : annotation_param
163 {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700164 $$ = new DefaultKeyedVector<std::string, std::vector<std::string> *>;
Andreas Huber3599d922016-08-09 10:42:57 -0700165 $$->add($1->first, $1->second);
166 }
167 | annotation_params ',' annotation_param
168 {
169 $$ = $1;
170 $$->add($3->first, $3->second);
171 }
172 ;
173
174annotation_param
175 : IDENTIFIER '=' annotation_value
176 {
177 $$ = new std::pair<std::string, std::vector<std::string> *>($1, $3);
178 }
179 ;
180
181annotation_value
182 : STRING_LITERAL
183 {
184 $$ = new std::vector<std::string>;
185 $$->push_back($1);
186 }
187 | '{' annotation_string_values '}' { $$ = $2; }
188 ;
189
190annotation_string_values
191 : STRING_LITERAL
192 {
193 $$ = new std::vector<std::string>;
194 $$->push_back($1);
195 }
196 | annotation_string_values ',' STRING_LITERAL
197 {
198 $$ = $1;
199 $$->push_back($3);
200 }
201 ;
202
Andreas Huberc9410c72016-07-28 12:18:40 -0700203program
Andreas Huberda51b8e2016-07-28 16:00:57 -0700204 : package imports body
Andreas Huber84f89de2016-07-28 15:39:51 -0700205 ;
206
207fqname
208 : FQNAME
209 {
210 $$ = ast->lookupType($1);
211 if ($$ == NULL) {
212 yyerror(ast,
213 android::String8::format(
214 "Failed to lookup type '%s'.", $1).string());
215 YYERROR;
216 }
217 }
218 | IDENTIFIER
219 {
220 $$ = ast->lookupType($1);
221 if ($$ == NULL) {
222 yyerror(ast,
223 android::String8::format(
224 "Failed to lookup type '%s'.", $1).string());
225 YYERROR;
226 }
227 }
228 | SCALAR
229 ;
Andreas Huberc9410c72016-07-28 12:18:40 -0700230
231package
Andreas Huber84f89de2016-07-28 15:39:51 -0700232 : PACKAGE FQNAME ';'
Andreas Hubereb1081f2016-07-28 13:13:24 -0700233 {
Andreas Huber84f89de2016-07-28 15:39:51 -0700234 if (!ast->setPackage($2)) {
235 yyerror(ast, "Malformed package identifier.");
236 YYERROR;
237 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700238 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700239
Andreas Huberc9410c72016-07-28 12:18:40 -0700240imports
241 : /* empty */
Andreas Huber84f89de2016-07-28 15:39:51 -0700242 | imports IMPORT FQNAME ';'
Andreas Hubereb1081f2016-07-28 13:13:24 -0700243 {
Andreas Huber68f24592016-07-29 14:53:48 -0700244 if (!ast->addImport($3)) {
245 yyerror(ast,
246 android::String8::format(
247 "Unable to import '%s'.", $3));
248
249 YYERROR;
250 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700251 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700252 | imports IMPORT IDENTIFIER ';'
253 {
Andreas Huber68f24592016-07-29 14:53:48 -0700254 if (!ast->addImport($3)) {
255 yyerror(ast,
256 android::String8::format(
257 "Unable to import '%s'.", $3));
258
259 YYERROR;
260 }
Andreas Huber5345ec22016-07-29 13:33:27 -0700261 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700262 ;
263
264opt_extends
265 : /* empty */ { $$ = NULL; }
Andreas Huber84f89de2016-07-28 15:39:51 -0700266 | EXTENDS fqname { $$ = $2; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700267
268body
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -0700269 : opt_annotations INTERFACE IDENTIFIER opt_extends
Andreas Huberc9410c72016-07-28 12:18:40 -0700270 {
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -0700271 if ($4 != NULL && !$4->isInterface()) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700272 fprintf(stderr, "You can only extend interfaces.\n");
273 YYERROR;
274 }
275
Andreas Huber991b8642016-08-15 16:40:44 -0700276 if ($3[0] != 'I') {
277 fprintf(stderr,
278 "All interface names must start with an 'I' prefix.\n");
279
280 YYERROR;
281 }
282
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -0700283 Interface *iface = new Interface(static_cast<Interface *>($4), $1);
Andreas Hubereb1081f2016-07-28 13:13:24 -0700284
285 // Register interface immediately so it can be referenced inside
286 // definition.
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -0700287 if (!ast->addScopedType($3, iface)) {
Andreas Huber5a545442016-08-03 10:44:56 -0700288 YYERROR;
289 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700290
Andreas Huberc9410c72016-07-28 12:18:40 -0700291 ast->enterScope(iface);
292 }
293 '{' interface_declarations '}' ';'
294 {
295 Interface *iface = static_cast<Interface *>(ast->scope());
296
297 ast->leaveScope();
Andreas Huberc9410c72016-07-28 12:18:40 -0700298 }
299 | type_declarations
300 ;
301
302interface_declarations
303 : /* empty */
304 | interface_declarations type_declaration
305 | interface_declarations method_declaration
306 {
307 Interface *iface = static_cast<Interface *>(ast->scope());
308 iface->addMethod($2);
309 }
310 ;
311
312type_declarations
Andreas Hubera2723d22016-07-29 15:36:07 -0700313 : /* empty */
Andreas Huberc9410c72016-07-28 12:18:40 -0700314 | type_declarations type_declaration
315 ;
316
317type_declaration
318 : named_struct_or_union_declaration ';'
319 | named_enum_declaration ';'
320 | typedef_declaration ';'
321 | const_declaration ';'
322 ;
323
324typedef_declaration
325 : TYPEDEF type IDENTIFIER
326 {
Andreas Huber31629bc2016-08-03 09:06:40 -0700327 TypeDef *def = new TypeDef($2);
Andreas Huber5a545442016-08-03 10:44:56 -0700328 if (!ast->addScopedType($3, def)) {
329 YYERROR;
330 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700331 }
332 ;
333
Yifan Hong52165692016-08-12 18:06:40 -0700334const_expr
335 : INTEGER { $$ = new ConstantExpression($1); }
336 | IDENTIFIER { $$ = new ConstantExpression($1); }
337 | const_expr '?' const_expr ':' const_expr
338 {
339 $$ = new ConstantExpression($1, $3, $5);
340 }
341 | const_expr LOGICAL_OR const_expr { $$ = new ConstantExpression($1, "||", $3); }
342 | const_expr LOGICAL_AND const_expr { $$ = new ConstantExpression($1, "&&", $3); }
343 | const_expr '|' const_expr { $$ = new ConstantExpression($1, "|" , $3); }
344 | const_expr '^' const_expr { $$ = new ConstantExpression($1, "^" , $3); }
345 | const_expr '&' const_expr { $$ = new ConstantExpression($1, "&" , $3); }
346 | const_expr EQUALITY const_expr { $$ = new ConstantExpression($1, "==", $3); }
347 | const_expr NEQ const_expr { $$ = new ConstantExpression($1, "!=", $3); }
348 | const_expr '<' const_expr { $$ = new ConstantExpression($1, "<" , $3); }
349 | const_expr '>' const_expr { $$ = new ConstantExpression($1, ">" , $3); }
350 | const_expr LEQ const_expr { $$ = new ConstantExpression($1, "<=", $3); }
351 | const_expr GEQ const_expr { $$ = new ConstantExpression($1, ">=", $3); }
352 | const_expr LSHIFT const_expr { $$ = new ConstantExpression($1, "<<", $3); }
353 | const_expr RSHIFT const_expr { $$ = new ConstantExpression($1, ">>", $3); }
354 | const_expr '+' const_expr { $$ = new ConstantExpression($1, "+" , $3); }
355 | const_expr '-' const_expr { $$ = new ConstantExpression($1, "-" , $3); }
356 | const_expr '*' const_expr { $$ = new ConstantExpression($1, "*" , $3); }
357 | const_expr '/' const_expr { $$ = new ConstantExpression($1, "/" , $3); }
358 | const_expr '%' const_expr { $$ = new ConstantExpression($1, "%" , $3); }
359 | '+' const_expr %prec UNARY_PLUS { $$ = new ConstantExpression("+", $2); }
360 | '-' const_expr %prec UNARY_MINUS { $$ = new ConstantExpression("-", $2); }
361 | '!' const_expr { $$ = new ConstantExpression("!", $2); }
362 | '~' const_expr { $$ = new ConstantExpression("~", $2); }
363 | '(' const_expr ')' { $$ = $2; }
364 ;
365
Andreas Huberc9410c72016-07-28 12:18:40 -0700366const_value
367 : INTEGER
368 | STRING_LITERAL ;
369
370const_declaration
Andreas Huber84f89de2016-07-28 15:39:51 -0700371 : CONST fqname IDENTIFIER '=' const_value
Andreas Huberc9410c72016-07-28 12:18:40 -0700372 {
373 Constant *constant = new Constant($3, $2, $5);
374 ast->scope()->addConstant(constant);
375 }
376 ;
377
378method_declaration
Andreas Huber3599d922016-08-09 10:42:57 -0700379 : opt_annotations IDENTIFIER '(' typed_vars ')' ';'
Andreas Huberc9410c72016-07-28 12:18:40 -0700380 {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700381 $$ = new Method($2, $4, new std::vector<TypedVar *>, false, $1);
382 }
383 | opt_annotations ONEWAY IDENTIFIER '(' typed_vars ')' ';'
384 {
385 $$ = new Method($3, $5, new std::vector<TypedVar *>, true, $1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700386 }
Andreas Huber3599d922016-08-09 10:42:57 -0700387 | opt_annotations IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' ';'
Andreas Huberc9410c72016-07-28 12:18:40 -0700388 {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700389 $$ = new Method($2, $4, $8, false, $1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700390 }
391 ;
392
393typed_vars
394 : /* empty */
395 {
Andreas Huber881227d2016-08-02 14:20:21 -0700396 $$ = new std::vector<TypedVar *>;
Andreas Huberc9410c72016-07-28 12:18:40 -0700397 }
398 | typed_var
399 {
Andreas Huber881227d2016-08-02 14:20:21 -0700400 $$ = new std::vector<TypedVar *>;
Andreas Huberc9410c72016-07-28 12:18:40 -0700401 $$->push_back($1);
402 }
403 | typed_vars ',' typed_var
404 {
405 $$ = $1;
406 $$->push_back($3);
407 }
408 ;
409
410typed_var : type IDENTIFIER { $$ = new TypedVar($2, $1); }
411 ;
412
413
414struct_or_union_keyword
415 : STRUCT { $$ = CompoundType::STYLE_STRUCT; }
416 | UNION { $$ = CompoundType::STYLE_UNION; }
417 ;
418
419named_struct_or_union_declaration
420 : struct_or_union_keyword IDENTIFIER
421 {
Andreas Huber31629bc2016-08-03 09:06:40 -0700422 CompoundType *container = new CompoundType($1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700423 ast->enterScope(container);
424 }
425 struct_or_union_body
426 {
427 CompoundType *container = static_cast<CompoundType *>(ast->scope());
428
Andreas Huber5a545442016-08-03 10:44:56 -0700429 if (!container->setFields($4)) {
430 YYERROR;
431 }
432
Andreas Huberc9410c72016-07-28 12:18:40 -0700433 ast->leaveScope();
Andreas Huber5a545442016-08-03 10:44:56 -0700434 if (!ast->addScopedType($2, container)) {
435 YYERROR;
436 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700437 }
438 ;
439
440struct_or_union_declaration
441 : struct_or_union_keyword optIdentifier
442 {
Andreas Huber31629bc2016-08-03 09:06:40 -0700443 CompoundType *container = new CompoundType($1);
Andreas Huberc9410c72016-07-28 12:18:40 -0700444 ast->enterScope(container);
445 }
446 struct_or_union_body
447 {
448 CompoundType *container = static_cast<CompoundType *>(ast->scope());
449
Andreas Huber5a545442016-08-03 10:44:56 -0700450 if (!container->setFields($4)) {
451 YYERROR;
452 }
453
Andreas Huberc9410c72016-07-28 12:18:40 -0700454 ast->leaveScope();
Andreas Huber5a545442016-08-03 10:44:56 -0700455 if (!ast->addScopedType($2, container)) {
456 YYERROR;
457 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700458
Andreas Huberfd4afab2016-08-03 13:02:57 -0700459 $$ = container->ref();
Andreas Huberc9410c72016-07-28 12:18:40 -0700460 }
461 ;
462
463struct_or_union_body
464 : '{' field_declarations '}' { $$ = $2; }
465 ;
466
467field_declarations
Andreas Huber881227d2016-08-02 14:20:21 -0700468 : /* empty */ { $$ = new std::vector<CompoundField *>; }
Andreas Huberc9410c72016-07-28 12:18:40 -0700469 | field_declarations field_declaration
470 {
471 $$ = $1;
472
473 if ($2 != NULL) {
474 $$->push_back($2);
475 }
476 }
477 ;
478
479field_declaration
480 : type IDENTIFIER ';' { $$ = new CompoundField($2, $1); }
481 | struct_or_union_declaration ';' { $$ = NULL; }
482 | enum_declaration ';' { $$ = NULL; }
483 ;
484
485opt_storage_type
486 : /* empty */ { $$ = NULL; }
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700487 | ':' fqname
488 {
489 $$ = $2;
490
491 if ($$ != NULL && !$$->isValidEnumStorageType()) {
492 fprintf(stderr, "Invalid enum storage type specified.\n");
493 YYABORT;
494 }
495 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700496 ;
497
498opt_comma
499 : /* empty */
500 | ','
501 ;
502
503named_enum_declaration
504 : ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
505 {
Andreas Huber31629bc2016-08-03 09:06:40 -0700506 EnumType *enumType = new EnumType($5, $3);
Andreas Huber5a545442016-08-03 10:44:56 -0700507 if (!ast->addScopedType($2, enumType)) {
508 YYERROR;
509 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700510 }
511 ;
512
513enum_declaration
514 : ENUM '{' enum_values opt_comma '}'
515 {
Andreas Huber31629bc2016-08-03 09:06:40 -0700516 EnumType *enumType = new EnumType($3);
Andreas Huber5a545442016-08-03 10:44:56 -0700517 if (!ast->addScopedType(NULL /* localName */, enumType)) {
518 YYERROR;
519 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700520
Andreas Huberfd4afab2016-08-03 13:02:57 -0700521 $$ = enumType->ref();
Andreas Huberc9410c72016-07-28 12:18:40 -0700522 }
523 | ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
524 {
Andreas Huber31629bc2016-08-03 09:06:40 -0700525 EnumType *enumType = new EnumType($5, $3);
Andreas Huber5a545442016-08-03 10:44:56 -0700526 if (!ast->addScopedType($2, enumType)) {
527 YYERROR;
528 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700529
Andreas Huberfd4afab2016-08-03 13:02:57 -0700530 $$ = enumType->ref();
Andreas Huberc9410c72016-07-28 12:18:40 -0700531 }
532 ;
533
534enum_value
535 : IDENTIFIER { $$ = new EnumValue($1); }
Yifan Hong52165692016-08-12 18:06:40 -0700536 | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3->value()); }
Andreas Huberc9410c72016-07-28 12:18:40 -0700537 ;
538
539enum_values
540 : /* empty */
541 {
Andreas Huber881227d2016-08-02 14:20:21 -0700542 $$ = new std::vector<EnumValue *>;
Andreas Huberc9410c72016-07-28 12:18:40 -0700543 }
544 | enum_value
545 {
Andreas Huber881227d2016-08-02 14:20:21 -0700546 $$ = new std::vector<EnumValue *>;
Andreas Huberc9410c72016-07-28 12:18:40 -0700547 $$->push_back($1);
548 }
549 | enum_values ',' enum_value
550 {
551 $$ = $1;
552 $$->push_back($3);
553 }
554 ;
555
556type
Andreas Huber84f89de2016-07-28 15:39:51 -0700557 : fqname { $$ = $1; }
Andreas Huberb95ea8a2016-08-15 15:35:42 -0700558 | fqname '[' INTEGER ']'
559 {
560 if ($1->isInterface()) {
561 fprintf(stderr, "Arrays of interface types are not supported.");
562 YYERROR;
563 }
564
565 $$ = new ArrayType($1, $3);
566 }
567 | VEC '<' fqname '>'
568 {
569 if ($3->isInterface()) {
570 fprintf(stderr, "Vectors of interface types are not supported.");
571 YYERROR;
572 }
573
574 $$ = new VectorType($3);
575 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700576 | struct_or_union_declaration { $$ = $1; }
577 | enum_declaration { $$ = $1; }
578 ;
579
580optIdentifier
581 : /* empty */ { $$ = NULL; }
582 | IDENTIFIER { $$ = $1; }
583 ;
584
585%%