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