1/*
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
17%{
18#include "aidl_language.h"
19#include "parser.h"
20#include "aidl_language_y.h"
21#include "logging.h"
22#include <android-base/parseint.h>
23#include <set>
24#include <map>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
30
31AidlLocation loc(const yy::parser::location_type& begin, const yy::parser::location_type& end) {
32  AIDL_FATAL_IF(begin.begin.filename != begin.end.filename, AIDL_LOCATION_HERE);
33  AIDL_FATAL_IF(begin.end.filename != end.begin.filename, AIDL_LOCATION_HERE);
34  AIDL_FATAL_IF(end.begin.filename != end.end.filename, AIDL_LOCATION_HERE);
35  AidlLocation::Point begin_point {
36    .line = begin.begin.line,
37    .column = begin.begin.column,
38  };
39  AidlLocation::Point end_point {
40    .line = end.end.line,
41    .column = end.end.column,
42  };
43  return AidlLocation(*begin.begin.filename, begin_point, end_point, AidlLocation::Source::EXTERNAL);
44}
45
46AidlLocation loc(const yy::parser::location_type& l) {
47  return loc(l, l);
48}
49
50#define lex_scanner ps->Scanner()
51
52%}
53
54%initial-action {
55    @$.begin.filename = @$.end.filename =
56        const_cast<std::string *>(&ps->FileName());
57}
58
59%parse-param { Parser* ps }
60%lex-param { void *lex_scanner }
61
62%glr-parser
63%skeleton "glr.cc"
64
65%expect-rr 0
66
67%define parse.error verbose
68%locations
69
70%union {
71    AidlToken* token;
72    char character;
73    std::string *str;
74    std::vector<std::unique_ptr<AidlToken>> *token_list;
75    AidlAnnotation* annotation;
76    AidlAnnotationParameter* param;
77    std::map<std::string, std::shared_ptr<AidlConstantValue>>* param_list;
78    std::vector<std::unique_ptr<AidlAnnotation>>* annotation_list;
79    AidlTypeSpecifier* type;
80    AidlArgument* arg;
81    AidlArgument::Direction direction;
82    AidlConstantValue* const_expr;
83    AidlEnumerator* enumerator;
84    std::vector<std::unique_ptr<AidlEnumerator>>* enumerators;
85    std::vector<std::unique_ptr<AidlConstantValue>>* constant_value_list;
86    std::vector<std::unique_ptr<AidlArgument>>* arg_list;
87    AidlVariableDeclaration* variable;
88    AidlMethod* method;
89    AidlMember* constant;
90    std::vector<std::unique_ptr<AidlMember>>* members;
91    AidlDefinedType* declaration;
92    std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args;
93    std::vector<std::string>* type_params;
94    std::vector<std::unique_ptr<AidlDefinedType>>* declarations;
95    AidlUnstructuredHeaders* unstructured_headers;
96}
97
98%destructor { } <direction>
99%destructor { delete ($$); } <*>
100
101%token<token> PACKAGE "package"
102%token<token> IMPORT "import"
103%token<token> ANNOTATION "annotation"
104%token<token> C_STR "string literal"
105%token<token> IDENTIFIER "identifier"
106%token<token> INTERFACE "interface"
107%token<token> PARCELABLE "parcelable"
108%token<token> ONEWAY "oneway"
109%token<token> ENUM "enum"
110%token<token> UNION "union"
111%token<token> CONST "const"
112
113%token<token> CHARVALUE "char literal"
114%token<token> FLOATVALUE "float literal"
115%token<token> HEXVALUE "hex literal"
116%token<token> INTVALUE "int literal"
117
118%token '(' ')' ',' '=' '[' ']' '.' '{' '}' ';'
119%token UNKNOWN "unrecognized character"
120%token<token> CPP_HEADER "cpp_header (which can also be used as an identifier)"
121%token<token> NDK_HEADER "ndk_header (which can also be used as an identifier)"
122%token<token> RUST_TYPE "rust_type (which can also be used as an identifier)"
123%token IN "in"
124%token INOUT "inout"
125%token OUT "out"
126%token TRUE_LITERAL "true"
127%token FALSE_LITERAL "false"
128
129/* Operator precedence and associativity, as per
130 * http://en.cppreference.com/w/cpp/language/operator_precedence */
131/* Precedence level 13 - 14, LTR, logical operators*/
132%left LOGICAL_OR
133%left LOGICAL_AND
134/* Precedence level 10 - 12, LTR, bitwise operators*/
135%left '|'
136%left '^'
137%left '&'
138/* Precedence level 9, LTR */
139%left EQUALITY NEQ
140/* Precedence level 8, LTR */
141%left '<' '>' LEQ GEQ
142/* Precedence level 7, LTR */
143%left LSHIFT RSHIFT
144/* Precedence level 6, LTR */
145%left '+' '-'
146/* Precedence level 5, LTR */
147%left '*' '/' '%'
148/* Precedence level 3, RTL; but we have to use %left here */
149%right UNARY_PLUS UNARY_MINUS  '!' '~'
150
151%type<declaration> decl
152%type<declaration> unannotated_decl
153%type<declaration> interface_decl
154%type<declaration> parcelable_decl
155%type<declaration> enum_decl
156%type<declaration> union_decl
157%type<members> parcelable_members interface_members
158%type<variable> variable_decl
159%type<type_params> optional_type_params
160%type<method> method_decl
161%type<constant> constant_decl
162%type<enumerator> enumerator
163%type<enumerators> enumerators enum_decl_body
164%type<param> parameter
165%type<param_list> parameter_list
166%type<param_list> parameter_non_empty_list
167%type<annotation> annotation
168%type<annotation_list>annotation_list
169%type<type> type
170%type<type> non_array_type
171%type<arg_list> arg_list arg_non_empty_list
172%type<arg> arg
173%type<direction> direction
174%type<type_args> type_args
175%type<type_params> type_params
176%type<const_expr> const_expr
177%type<constant_value_list> constant_value_list
178%type<constant_value_list> constant_value_non_empty_list
179%type<token_list> imports
180%type<declarations> decls
181%type<token> import identifier error qualified_name optional_package
182%type<unstructured_headers> optional_unstructured_headers
183
184%%
185
186document
187 : optional_package imports decls {
188    std::vector<std::string> imports;
189    for (const auto& import : *$2) {
190      imports.push_back(import->GetText());
191    }
192
193    ps->MakeDocument(loc(@1), Comments(), std::move(imports), std::move(*$3));
194
195    for (auto i = $2->rbegin(); i != $2->rend(); ++i) {
196      ps->GetDocument()->PrependComments((*i)->GetComments());
197    }
198    if ($1) {
199      ps->GetDocument()->PrependComments($1->GetComments());
200    }
201
202    delete $1;
203    delete $2;
204    delete $3;
205  }
206 ;
207
208/* A couple of tokens that are keywords elsewhere are identifiers when
209 * occurring in the identifier position. Therefore identifier is a
210 * non-terminal, which is either an IDENTIFIER token, or one of the
211 * aforementioned keyword tokens.
212 */
213identifier
214 : IDENTIFIER
215 | CPP_HEADER
216 | NDK_HEADER
217 | RUST_TYPE
218 ;
219
220optional_package
221 : {
222    $$ = nullptr;
223 }
224 | PACKAGE qualified_name ';' {
225    ps->SetPackage($2->GetText());
226    $$ = $1; // for comments
227    delete $2;
228  }
229 ;
230
231imports
232 : { $$ = new std::vector<std::unique_ptr<AidlToken>>(); }
233 | imports import
234  {
235    $$ = $1;
236    $$->emplace_back($2);
237  }
238
239import
240 : IMPORT qualified_name ';' {
241    // carry the comments before "import" token
242    $$ = new AidlToken($2->GetText(), $1->GetComments());
243    delete $1;
244    delete $2;
245  };
246
247qualified_name
248 : identifier {
249    $$ = $1;
250  }
251 | qualified_name '.' identifier
252  { $$ = $1;
253    $$->Append('.');
254    $$->Append($3->GetText());
255    delete $3;
256  };
257
258decls
259 : decl
260  { $$ = new std::vector<std::unique_ptr<AidlDefinedType>>();
261    if ($1 != nullptr) {
262      $$->emplace_back($1);
263    }
264  }
265 | decls decl
266  { $$ = $1;
267    if ($2 != nullptr) {
268      $$->emplace_back($2);
269    }
270  }
271
272decl
273 : annotation_list unannotated_decl
274   {
275    $$ = $2;
276
277    if ($$ != nullptr) {
278      $$->Annotate(std::move(*$1));
279    }
280
281    delete $1;
282   }
283 ;
284
285unannotated_decl
286 : parcelable_decl
287 | interface_decl
288 | enum_decl
289 | union_decl
290 ;
291
292type_params
293 : identifier {
294    $$ = new std::vector<std::string>();
295    $$->emplace_back($1->GetText());
296    delete $1;
297  }
298 | type_params ',' identifier {
299    $1->emplace_back($3->GetText());
300    $$ = $1;
301    delete $3;
302  };
303
304optional_type_params
305 : /* none */ { $$ = nullptr; }
306 | '<' type_params '>' {
307   $$ = $2;
308 };
309
310optional_unstructured_headers
311 : /* none */ { $$ = new AidlUnstructuredHeaders; }
312 | optional_unstructured_headers CPP_HEADER C_STR {
313     $$ = $1;
314     $$->cpp = $3->GetText();
315     delete $2;
316     delete $3;
317 }
318 | optional_unstructured_headers NDK_HEADER C_STR {
319     $$ = $1;
320     $$->ndk = $3->GetText();
321     delete $2;
322     delete $3;
323 }
324 | optional_unstructured_headers RUST_TYPE C_STR {
325     $$ = $1;
326     $$->rust_type = $3->GetText();
327     delete $2;
328     delete $3;
329 }
330 ;
331
332parcelable_decl
333 : PARCELABLE qualified_name optional_type_params optional_unstructured_headers ';' {
334    // No check for type name here. We allow nested types for unstructured parcelables.
335    $$ = new AidlParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), *$4, $3);
336    delete $1;
337    delete $2;
338    delete $4;
339 }
340 | PARCELABLE qualified_name optional_type_params '{' parcelable_members '}' {
341    ps->CheckValidTypeName(*$2, loc(@2));
342    $$ = new AidlStructuredParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5);
343    delete $1;
344    delete $2;
345 }
346 | PARCELABLE error ';' {
347    ps->AddError();
348    $$ = nullptr;
349    delete $1;
350  };
351
352parcelable_members
353 : /* empty */ {
354    $$ = new std::vector<std::unique_ptr<AidlMember>>();
355  }
356 | parcelable_members variable_decl {
357    $1->emplace_back($2);
358    $$ = $1;
359  }
360 | parcelable_members constant_decl {
361    $1->emplace_back($2);
362    $$ = $1;
363  }
364 | parcelable_members decl {
365    if ($2) $1->emplace_back($2);  // decl may be nullptr on error
366    $$ = $1;
367  }
368 | parcelable_members error ';' {
369    ps->AddError();
370    $$ = $1;
371  };
372
373variable_decl
374 : type identifier ';' {
375   $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText());
376   delete $2;
377 }
378 | type identifier '=' const_expr ';' {
379   // TODO(b/123321528): Support enum type default assignments (TestEnum foo = TestEnum.FOO).
380   $$ = new AidlVariableDeclaration(loc(@2), $1, $2->GetText(),  $4);
381   delete $2;
382 }
383 ;
384
385interface_decl
386 : INTERFACE qualified_name ';' {
387    ps->CheckValidTypeName(*$2, loc(@2));
388    $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), nullptr);
389    delete $1;
390    delete $2;
391  }
392 | INTERFACE qualified_name '{' interface_members '}' {
393    ps->CheckValidTypeName(*$2, loc(@2));
394    $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), $4);
395    delete $1;
396    delete $2;
397  }
398 | ONEWAY INTERFACE qualified_name '{' interface_members '}' {
399    ps->CheckValidTypeName(*$3, loc(@3));
400    $$ = new AidlInterface(loc(@2), $3->GetText(), $1->GetComments(), true, ps->Package(), $5);
401    delete $1;
402    delete $2;
403    delete $3;
404  }
405 | INTERFACE error '{' interface_members '}' {
406    ps->AddError();
407    $$ = nullptr;
408    delete $1;
409    delete $4;
410  };
411
412interface_members
413 :
414  { $$ = new std::vector<std::unique_ptr<AidlMember>>(); }
415 | interface_members method_decl
416  { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; }
417 | interface_members constant_decl
418  { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; }
419 | interface_members decl
420  {
421    if ($2) $1->emplace_back($2);  // decl may be nullptr on error
422    $$ = $1;
423  }
424 | interface_members error ';' {
425    ps->AddError();
426    $$ = $1;
427  };
428
429const_expr
430 : TRUE_LITERAL { $$ = AidlConstantValue::Boolean(loc(@1), true); }
431 | FALSE_LITERAL { $$ = AidlConstantValue::Boolean(loc(@1), false); }
432 | CHARVALUE {
433    $$ = AidlConstantValue::Character(loc(@1), $1->GetText());
434    delete $1;
435  }
436 | INTVALUE {
437    $$ = AidlConstantValue::Integral(loc(@1), $1->GetText());
438    if ($$ == nullptr) {
439      AIDL_ERROR(loc(@1)) << "Could not parse integer: "
440                << $1->GetText();
441      ps->AddError();
442      $$ = AidlConstantValue::Integral(loc(@1), "0");
443    }
444    delete $1;
445  }
446 | FLOATVALUE {
447    $$ = AidlConstantValue::Floating(loc(@1), $1->GetText());
448    delete $1;
449  }
450 | HEXVALUE {
451    $$ = AidlConstantValue::Integral(loc(@1), $1->GetText());
452    if ($$ == nullptr) {
453      AIDL_ERROR(loc(@1)) << "Could not parse hexvalue: "
454                << $1->GetText();
455      ps->AddError();
456      $$ = AidlConstantValue::Integral(loc(@1), "0");
457    }
458    delete $1;
459  }
460 | C_STR {
461    $$ = AidlConstantValue::String(loc(@1), $1->GetText());
462    delete $1;
463  }
464 | qualified_name {
465    $$ = new AidlConstantReference(loc(@1), $1->GetText());
466    delete $1;
467 }
468 | '{' constant_value_list '}' {
469    $$ = AidlConstantValue::Array(loc(@1), std::unique_ptr<vector<unique_ptr<AidlConstantValue>>>($2));
470  }
471 | const_expr LOGICAL_OR const_expr {
472    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "||", std::unique_ptr<AidlConstantValue>($3));
473  }
474 | const_expr LOGICAL_AND const_expr {
475    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "&&", std::unique_ptr<AidlConstantValue>($3));
476  }
477 | const_expr '|' const_expr {
478    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "|" , std::unique_ptr<AidlConstantValue>($3));
479  }
480 | const_expr '^' const_expr {
481    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "^" , std::unique_ptr<AidlConstantValue>($3));
482  }
483 | const_expr '&' const_expr {
484    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "&" , std::unique_ptr<AidlConstantValue>($3));
485  }
486 | const_expr EQUALITY const_expr {
487    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "==", std::unique_ptr<AidlConstantValue>($3));
488  }
489 | const_expr NEQ const_expr {
490    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "!=", std::unique_ptr<AidlConstantValue>($3));
491  }
492 | const_expr '<' const_expr {
493    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<" , std::unique_ptr<AidlConstantValue>($3));
494  }
495 | const_expr '>' const_expr {
496    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">" , std::unique_ptr<AidlConstantValue>($3));
497  }
498 | const_expr LEQ const_expr {
499    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<=", std::unique_ptr<AidlConstantValue>($3));
500  }
501 | const_expr GEQ const_expr {
502    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">=", std::unique_ptr<AidlConstantValue>($3));
503  }
504 | const_expr LSHIFT const_expr {
505    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "<<", std::unique_ptr<AidlConstantValue>($3));
506  }
507 | const_expr RSHIFT const_expr {
508    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), ">>", std::unique_ptr<AidlConstantValue>($3));
509  }
510 | const_expr '+' const_expr {
511    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "+" , std::unique_ptr<AidlConstantValue>($3));
512  }
513 | const_expr '-' const_expr {
514    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "-" , std::unique_ptr<AidlConstantValue>($3));
515  }
516 | const_expr '*' const_expr {
517    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "*" , std::unique_ptr<AidlConstantValue>($3));
518  }
519 | const_expr '/' const_expr {
520    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "/" , std::unique_ptr<AidlConstantValue>($3));
521  }
522 | const_expr '%' const_expr {
523    $$ = new AidlBinaryConstExpression(loc(@1), std::unique_ptr<AidlConstantValue>($1), "%" , std::unique_ptr<AidlConstantValue>($3));
524  }
525 | '+' const_expr %prec UNARY_PLUS  {
526    $$ = new AidlUnaryConstExpression(loc(@1), "+", std::unique_ptr<AidlConstantValue>($2));
527  }
528 | '-' const_expr %prec UNARY_MINUS {
529    $$ = new AidlUnaryConstExpression(loc(@1), "-", std::unique_ptr<AidlConstantValue>($2));
530  }
531 | '!' const_expr {
532    $$ = new AidlUnaryConstExpression(loc(@1), "!", std::unique_ptr<AidlConstantValue>($2));
533  }
534 | '~' const_expr {
535    $$ = new AidlUnaryConstExpression(loc(@1), "~", std::unique_ptr<AidlConstantValue>($2));
536  }
537 | '(' const_expr ')'
538  {
539    $$ = $2;
540  }
541 | '(' error ')'
542   {
543     AIDL_ERROR(loc(@1)) << "invalid const expression within parenthesis";
544     ps->AddError();
545     // to avoid segfaults
546     $$ = AidlConstantValue::Integral(loc(@1), "0");
547   }
548 ;
549
550constant_value_list
551 : /* empty */ {
552    $$ = new std::vector<std::unique_ptr<AidlConstantValue>>;
553 }
554 | constant_value_non_empty_list {
555    $$ = $1;
556 }
557 | constant_value_non_empty_list  ',' {
558    $$ = $1;
559 }
560 ;
561
562constant_value_non_empty_list
563 : const_expr {
564    $$ = new std::vector<std::unique_ptr<AidlConstantValue>>;
565    $$->push_back(std::unique_ptr<AidlConstantValue>($1));
566 }
567 | constant_value_non_empty_list ',' const_expr {
568    $$ = $1;
569    $$->push_back(std::unique_ptr<AidlConstantValue>($3));
570 }
571 ;
572
573constant_decl
574 : annotation_list CONST type identifier '=' const_expr ';' {
575    $3->PrependComments($2->GetComments());
576    // TODO(b/151102494) do not merge annotations.
577    $3->Annotate(std::move(*$1));
578    $$ = new AidlConstantDeclaration(loc(@4), $3, $4->GetText(), $6);
579    delete $1;
580    delete $2;
581    delete $4;
582   }
583 ;
584
585enumerator
586 : identifier '=' const_expr {
587    $$ = new AidlEnumerator(loc(@1), $1->GetText(), $3, $1->GetComments());
588    delete $1;
589   }
590 | identifier {
591    $$ = new AidlEnumerator(loc(@1), $1->GetText(), nullptr, $1->GetComments());
592    delete $1;
593   }
594 ;
595
596enumerators
597 : enumerator {
598    $$ = new std::vector<std::unique_ptr<AidlEnumerator>>();
599    $$->push_back(std::unique_ptr<AidlEnumerator>($1));
600   }
601 | enumerators ',' enumerator {
602    $1->push_back(std::unique_ptr<AidlEnumerator>($3));
603    $$ = $1;
604   }
605 ;
606
607enum_decl_body
608 : '{' enumerators '}' { $$ = $2; }
609 | '{' enumerators ',' '}' { $$ = $2; }
610 ;
611
612enum_decl
613 : ENUM qualified_name enum_decl_body {
614    ps->CheckValidTypeName(*$2, loc(@2));
615    $$ = new AidlEnumDeclaration(loc(@2), $2->GetText(), $3, ps->Package(), $1->GetComments());
616    delete $1;
617    delete $2;
618    delete $3;
619   }
620 ;
621
622union_decl
623 : UNION qualified_name optional_type_params '{' parcelable_members '}' {
624    ps->CheckValidTypeName(*$2, loc(@2));
625    $$ = new AidlUnionDecl(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5);
626    delete $1;
627    delete $2;
628  }
629 ;
630
631method_decl
632 : type identifier '(' arg_list ')' ';' {
633    $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $2->GetComments());
634    $$->PrependComments($1->GetComments());
635    delete $2;
636  }
637 | annotation_list ONEWAY type identifier '(' arg_list ')' ';' {
638    $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, $4->GetComments());
639    $3->PrependComments($2->GetComments());
640    $3->Annotate(std::move(*$1));
641    $$->PrependComments($3->GetComments());
642    delete $1;
643    delete $2;
644    delete $4;
645  }
646 | type identifier '(' arg_list ')' '=' INTVALUE ';' {
647    int32_t serial = 0;
648    if (!android::base::ParseInt($7->GetText(), &serial)) {
649        AIDL_ERROR(loc(@7)) << "Could not parse int value: " << $7->GetText();
650        ps->AddError();
651    }
652    $$ = new AidlMethod(loc(@2), false, $1, $2->GetText(), $4, $2->GetComments(), serial);
653    $$->PrependComments($1->GetComments());
654    delete $2;
655    delete $7;
656  }
657 | annotation_list ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' {
658    int32_t serial = 0;
659    if (!android::base::ParseInt($9->GetText(), &serial)) {
660        AIDL_ERROR(loc(@9)) << "Could not parse int value: " << $9->GetText();
661        ps->AddError();
662    }
663    $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, $4->GetComments(), serial);
664    $3->PrependComments($2->GetComments());
665    $3->Annotate(std::move(*$1));
666    $$->PrependComments($3->GetComments());
667    delete $1;
668    delete $2;
669    delete $4;
670    delete $9;
671  };
672
673arg_non_empty_list
674 : arg {
675    $$ = new std::vector<std::unique_ptr<AidlArgument>>();
676    $$->push_back(std::unique_ptr<AidlArgument>($1));
677  }
678 | arg_non_empty_list ',' arg {
679    $$ = $1;
680    $$->push_back(std::unique_ptr<AidlArgument>($3));
681  };
682
683arg_list
684 : /*empty*/
685   { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
686 | arg_non_empty_list { $$ = $1; }
687 ;
688
689arg
690 : direction type identifier {
691    $$ = new AidlArgument(loc(@3), $1, $2, $3->GetText());
692    delete $3;
693  }
694 | type identifier {
695    $$ = new AidlArgument(loc(@2), $1, $2->GetText());
696    delete $2;
697  };
698
699non_array_type
700 : annotation_list qualified_name {
701    $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), /*array=*/std::nullopt, nullptr, $2->GetComments());
702    $$->Annotate(std::move(*$1));
703    delete $1;
704    delete $2;
705  }
706 | non_array_type '<' type_args '>' {
707    ps->SetTypeParameters($1, $3);
708    $$ = $1;
709  }
710 | non_array_type '<' non_array_type '<' type_args RSHIFT {
711    ps->SetTypeParameters($3, $5);
712    auto params = new std::vector<std::unique_ptr<AidlTypeSpecifier>>();
713    params->emplace_back($3);
714    ps->SetTypeParameters($1, params);
715    $$ = $1;
716  }
717 | non_array_type '<' type_args ',' non_array_type '<' type_args RSHIFT {
718    ps->SetTypeParameters($5, $7);
719    $3->emplace_back($5);
720    ps->SetTypeParameters($1, $3);
721    $$ = $1;
722  };
723
724type
725 : non_array_type
726 | type annotation_list '[' ']' {
727    if (!$2->empty()) {
728      AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported.";
729      ps->AddError();
730    }
731    if (!$1->MakeArray(DynamicArray{})) {
732      AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size.";
733      ps->AddError();
734    }
735    $$ = $1;
736    delete $2;
737  }
738 | type annotation_list '[' const_expr ']' {
739    if (!$2->empty()) {
740      AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported.";
741      ps->AddError();
742    }
743    if (!$1->MakeArray(FixedSizeArray{std::unique_ptr<AidlConstantValue>($4)})) {
744      AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size.";
745      ps->AddError();
746    }
747    $$ = $1;
748    delete $2;
749  }
750 ;
751
752type_args
753 : type {
754    if (!$1->GetAnnotations().empty()) {
755      AIDL_ERROR(loc(@1)) << "Annotations for type arguments are not supported.";
756      ps->AddError();
757    }
758    $$ = new std::vector<std::unique_ptr<AidlTypeSpecifier>>();
759    $$->emplace_back($1);
760  }
761 | type_args ',' type {
762    $1->emplace_back($3);
763    $$ = $1;
764  };
765
766annotation_list
767 :
768  { $$ = new std::vector<std::unique_ptr<AidlAnnotation>>(); }
769 | annotation_list annotation
770  {
771    if ($2 != nullptr) {
772      $1->emplace_back(std::unique_ptr<AidlAnnotation>($2));
773    }
774    $$ = $1;
775  };
776
777parameter
778  : identifier '=' const_expr {
779    $$ = new AidlAnnotationParameter{$1->GetText(), std::unique_ptr<AidlConstantValue>($3)};
780    delete $1;
781  };
782
783parameter_list
784  : /*empty*/{
785    $$ = new std::map<std::string, std::shared_ptr<AidlConstantValue>>();
786  }
787  | parameter_non_empty_list  {
788    $$ = $1;
789  };
790
791parameter_non_empty_list
792  : parameter {
793    $$ = new std::map<std::string, std::shared_ptr<AidlConstantValue>>();
794    $$->emplace(std::move($1->name), $1->value.release());
795    delete $1;
796  }
797  | parameter_non_empty_list ',' parameter {
798    $$ = $1;
799    if ($$->find($3->name) != $$->end()) {
800      AIDL_ERROR(loc(@3)) << "Trying to redefine parameter " << $3->name << ".";
801      ps->AddError();
802    }
803    $$->emplace(std::move($3->name), std::move($3->value));
804    delete $3;
805  };
806
807annotation
808 : ANNOTATION {
809    // release() returns nullptr if unique_ptr is empty.
810    $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), {}, $1->GetComments()).release();
811    if (!$$) {
812      ps->AddError();
813    }
814    delete $1;
815  }
816 | ANNOTATION '(' const_expr ')' {
817    auto value = std::shared_ptr<AidlConstantValue>($3);
818    std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list {{"value" , value}};
819    $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), std::move(parameter_list), $1->GetComments()).release();
820    if (!$$) {
821      ps->AddError();
822    }
823    delete $1;
824  }
825 | ANNOTATION '(' parameter_list ')' {
826    // release() returns nullptr if unique_ptr is empty.
827    $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), std::move(*$3), $1->GetComments()).release();
828    if (!$$) {
829      ps->AddError();
830    }
831    delete $1;
832    delete $3;
833  }
834 ;
835
836direction
837 : IN
838  { $$ = AidlArgument::IN_DIR; }
839 | OUT
840  { $$ = AidlArgument::OUT_DIR; }
841 | INOUT
842  { $$ = AidlArgument::INOUT_DIR; };
843
844%%
845
846#include <ctype.h>
847#include <stdio.h>
848
849void yy::parser::error(const yy::parser::location_type& l, const std::string& errstr) {
850  AIDL_ERROR(loc(l)) << errstr;
851  // parser will return error value
852}
853