1%{
2#include "aidl_language.h"
3#include "aidl_language_y.h"
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
9
10#define lex_scanner ps->Scanner()
11
12%}
13
14%parse-param { Parser* ps }
15%lex-param { void *lex_scanner }
16
17%pure-parser
18%skeleton "glr.cc"
19
20%union {
21    AidlToken* token;
22    int integer;
23    std::string *str;
24    AidlType::Annotation annotation;
25    AidlType::Annotation annotation_list;
26    AidlType* type;
27    AidlType* unannotated_type;
28    AidlArgument* arg;
29    AidlArgument::Direction direction;
30    std::vector<std::unique_ptr<AidlArgument>>* arg_list;
31    AidlMethod* method;
32    AidlConstant* constant;
33    std::vector<std::unique_ptr<AidlMember>>* members;
34    AidlQualifiedName* qname;
35    AidlInterface* interface_obj;
36    AidlParcelable* parcelable;
37    AidlDocument* parcelable_list;
38}
39
40%token<token> IDENTIFIER INTERFACE ONEWAY C_STR
41%token<integer> INTVALUE
42
43%token '(' ')' ',' '=' '[' ']' '<' '>' '.' '{' '}' ';'
44%token IN OUT INOUT PACKAGE IMPORT PARCELABLE CPP_HEADER CONST INT
45%token ANNOTATION_NULLABLE ANNOTATION_UTF8 ANNOTATION_UTF8_CPP
46
47%type<parcelable_list> parcelable_decls
48%type<parcelable> parcelable_decl
49%type<members> members
50%type<interface_obj> interface_decl
51%type<method> method_decl
52%type<constant> constant_decl
53%type<annotation> annotation
54%type<annotation_list>annotation_list
55%type<type> type
56%type<unannotated_type> unannotated_type
57%type<arg_list> arg_list
58%type<arg> arg
59%type<direction> direction
60%type<str> generic_list
61%type<qname> qualified_name
62
63%type<token> identifier error
64%%
65document
66 : package imports parcelable_decls
67  { ps->SetDocument($3); }
68 | package imports interface_decl
69  { ps->SetDocument(new AidlDocument($3)); };
70
71/* A couple of tokens that are keywords elsewhere are identifiers when
72 * occurring in the identifier position. Therefore identifier is a
73 * non-terminal, which is either an IDENTIFIER token, or one of the
74 * aforementioned keyword tokens.
75 */
76identifier
77 : IDENTIFIER
78  { $$ = $1; }
79 | CPP_HEADER
80  { $$ = new AidlToken("cpp_header", ""); }
81 | INT
82  { $$ = new AidlToken("int", ""); };
83
84package
85 : {}
86 | PACKAGE qualified_name ';'
87  { ps->SetPackage($2); };
88
89imports
90 : {}
91 | import imports {};
92
93import
94 : IMPORT qualified_name ';'
95  { ps->AddImport($2, @1.begin.line); };
96
97qualified_name
98 : identifier {
99    $$ = new AidlQualifiedName($1->GetText(), $1->GetComments());
100    delete $1;
101  }
102 | qualified_name '.' identifier
103  { $$ = $1;
104    $$->AddTerm($3->GetText());
105  };
106
107parcelable_decls
108 :
109  { $$ = new AidlDocument(); }
110 | parcelable_decls parcelable_decl {
111   $$ = $1;
112   $$->AddParcelable($2);
113  }
114 | parcelable_decls error {
115    fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n",
116            ps->FileName().c_str(),
117            @2.begin.line, $2->GetText().c_str());
118    $$ = $1;
119  };
120
121parcelable_decl
122 : PARCELABLE qualified_name ';' {
123    $$ = new AidlParcelable($2, @2.begin.line, ps->Package());
124  }
125 | PARCELABLE qualified_name CPP_HEADER C_STR ';' {
126    $$ = new AidlParcelable($2, @2.begin.line, ps->Package(), $4->GetText());
127  }
128 | PARCELABLE ';' {
129    fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n",
130            ps->FileName().c_str(), @1.begin.line);
131    $$ = NULL;
132  }
133 | PARCELABLE error ';' {
134    fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n",
135            ps->FileName().c_str(), @2.begin.line, $2->GetText().c_str());
136    $$ = NULL;
137  };
138
139interface_decl
140 : INTERFACE identifier '{' members '}' {
141    $$ = new AidlInterface($2->GetText(), @2.begin.line, $1->GetComments(),
142                           false, $4, ps->Package());
143    delete $1;
144    delete $2;
145  }
146 | ONEWAY INTERFACE identifier '{' members '}' {
147    $$ = new AidlInterface($3->GetText(), @3.begin.line, $1->GetComments(),
148                           true, $5, ps->Package());
149    delete $1;
150    delete $2;
151    delete $3;
152  }
153 | INTERFACE error '{' members '}' {
154    fprintf(stderr, "%s:%d: syntax error in interface declaration.  Expected type name, saw \"%s\"\n",
155            ps->FileName().c_str(), @2.begin.line, $2->GetText().c_str());
156    $$ = NULL;
157    delete $1;
158    delete $2;
159  }
160 | INTERFACE error '}' {
161    fprintf(stderr, "%s:%d: syntax error in interface declaration.  Expected type name, saw \"%s\"\n",
162            ps->FileName().c_str(), @2.begin.line, $2->GetText().c_str());
163    $$ = NULL;
164    delete $1;
165    delete $2;
166  };
167
168members
169 :
170  { $$ = new std::vector<std::unique_ptr<AidlMember>>(); }
171 | members method_decl
172  { $1->push_back(std::unique_ptr<AidlMember>($2)); }
173 | members constant_decl
174  { $1->push_back(std::unique_ptr<AidlMember>($2)); }
175 | members error ';' {
176    fprintf(stderr, "%s:%d: syntax error before ';' "
177                    "(expected method or constant declaration)\n",
178            ps->FileName().c_str(), @3.begin.line);
179    $$ = $1;
180  };
181
182constant_decl
183 : CONST INT identifier '=' INTVALUE ';' {
184    $$ = new AidlConstant($3->GetText(), $5);
185 };
186
187method_decl
188 : type identifier '(' arg_list ')' ';' {
189    $$ = new AidlMethod(false, $1, $2->GetText(), $4, @2.begin.line,
190                        $1->GetComments());
191    delete $2;
192  }
193 | ONEWAY type identifier '(' arg_list ')' ';' {
194    $$ = new AidlMethod(true, $2, $3->GetText(), $5, @3.begin.line,
195                        $1->GetComments());
196    delete $1;
197    delete $3;
198  }
199 | type identifier '(' arg_list ')' '=' INTVALUE ';' {
200    $$ = new AidlMethod(false, $1, $2->GetText(), $4, @2.begin.line,
201                        $1->GetComments(), $7);
202    delete $2;
203  }
204 | ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' {
205    $$ = new AidlMethod(true, $2, $3->GetText(), $5, @3.begin.line,
206                        $1->GetComments(), $8);
207    delete $1;
208    delete $3;
209  };
210
211arg_list
212 :
213  { $$ = new std::vector<std::unique_ptr<AidlArgument>>(); }
214 | arg {
215    $$ = new std::vector<std::unique_ptr<AidlArgument>>();
216    $$->push_back(std::unique_ptr<AidlArgument>($1));
217  }
218 | arg_list ',' arg {
219    $$ = $1;
220    $$->push_back(std::unique_ptr<AidlArgument>($3));
221  }
222 | error {
223    fprintf(stderr, "%s:%d: syntax error in parameter list\n",
224            ps->FileName().c_str(), @1.begin.line);
225    $$ = new std::vector<std::unique_ptr<AidlArgument>>();
226  };
227
228arg
229 : direction type identifier {
230    $$ = new AidlArgument($1, $2, $3->GetText(), @3.begin.line);
231    delete $3;
232  };
233 | type identifier {
234    $$ = new AidlArgument($1, $2->GetText(), @2.begin.line);
235    delete $2;
236  };
237
238unannotated_type
239 : qualified_name {
240    $$ = new AidlType($1->GetDotName(), @1.begin.line, $1->GetComments(), false);
241    delete $1;
242  }
243 | qualified_name '[' ']' {
244    $$ = new AidlType($1->GetDotName(), @1.begin.line, $1->GetComments(),
245                      true);
246    delete $1;
247  }
248 | qualified_name '<' generic_list '>' {
249    $$ = new AidlType($1->GetDotName() + "<" + *$3 + ">", @1.begin.line,
250                      $1->GetComments(), false);
251    delete $1;
252    delete $3;
253  };
254
255type
256 : annotation_list unannotated_type {
257    $$ = $2;
258    $2->Annotate($1);
259  }
260 | unannotated_type {
261    $$ = $1;
262  };
263
264generic_list
265 : qualified_name {
266    $$ = new std::string($1->GetDotName());
267    delete $1;
268  }
269 | generic_list ',' qualified_name {
270    $$ = new std::string(*$1 + "," + $3->GetDotName());
271    delete $1;
272    delete $3;
273  };
274
275annotation_list
276 : annotation_list annotation
277  { $$ = static_cast<AidlType::Annotation>($1 | $2); }
278 | annotation
279  { $$ = $1; };
280
281annotation
282 : ANNOTATION_NULLABLE
283  { $$ = AidlType::AnnotationNullable; }
284 | ANNOTATION_UTF8
285  { $$ = AidlType::AnnotationUtf8; }
286 | ANNOTATION_UTF8_CPP
287  { $$ = AidlType::AnnotationUtf8InCpp; };
288
289direction
290 : IN
291  { $$ = AidlArgument::IN_DIR; }
292 | OUT
293  { $$ = AidlArgument::OUT_DIR; }
294 | INOUT
295  { $$ = AidlArgument::INOUT_DIR; };
296
297%%
298
299#include <ctype.h>
300#include <stdio.h>
301
302void yy::parser::error(const yy::parser::location_type& l,
303                       const std::string& errstr) {
304  ps->ReportError(errstr, l.begin.line);
305}
306