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
19#include "AST.h"
20#include "Declaration.h"
21#include "Type.h"
22#include "VarDeclaration.h"
23#include "FunctionDeclaration.h"
24#include "CompositeDeclaration.h"
25#include "Define.h"
26#include "Include.h"
27#include "EnumVarDeclaration.h"
28#include "Note.h"
29#include "TypeDef.h"
30#include "Expression.h"
31
32#include "c2hal_y.h"
33
34#include <stdio.h>
35#include <algorithm>
36
37using namespace android;
38
39extern int yylex(YYSTYPE *yylval_param, YYLTYPE *llocp, void *);
40
41int yyerror(YYLTYPE *llocp, AST *, const char *s) {
42    extern bool should_report_errors;
43
44    if (!should_report_errors) {
45      return 0;
46    }
47
48    fflush(stdout);
49    LOG(ERROR) << " "
50               << s
51               << " near line "
52               << llocp->first_line;
53
54    return 0;
55}
56
57#define scanner ast->scanner()
58
59std::string get_last_comment() {
60    extern std::string last_comment;
61
62    std::string ret{last_comment};
63
64    // clear the last comment now that it's been taken
65    last_comment = "";
66
67    return ret;
68}
69
70%}
71
72%parse-param { android::AST *ast }
73%lex-param   { void *scanner }
74%locations
75%define api.pure
76%glr-parser
77
78/* These have to do with the fact that
79 * struct_or_union_declaration and enum_declaration
80 * both start with STRUCT/UNION/ENUM opt_id
81 * and type_qualifiers contain these.
82 */
83%expect 3
84
85%token START_HEADER
86%token START_EXPR
87
88%token STRUCT
89%token UNION
90%token ENUM
91%token CLASS
92%token CONST
93%token VOID
94%token INCLUDE
95%token DEFINE
96%token TYPEDEF
97%token UNSIGNED
98%token SIGNED
99%token LSHIFT
100%token RSHIFT
101%token VARARGS
102%token NAMESPACE
103%token EXTERN
104%token C_STRING
105
106%left ','
107%right '?' ':'
108%left '|'
109%left '^'
110%left '&'
111%left RSHIFT LSHIFT
112%left '+' '-'
113%left '*' '/' '%'
114%right '~' '!' UMINUS UPLUS
115%left ARRAY_SUBSCRIPT FUNCTION_CALL
116
117%right STRUCT ENUM
118
119%token<str> ID
120%token<str> COMMENT
121%token<str> VALUE
122%token<str> INTEGRAL_VALUE
123%token<str> INCLUDE_FILE
124%token<str> FUNCTION
125%token<str> DEFINE_SLURP
126%token<str> OTHER_STATEMENT
127
128%type<expression> array
129%type<expressions> arrays
130%type<expression> expr
131%type<expressions> args
132%type<type> type
133%type<type> opt_enum_base_type
134%type<qualifier> type_qualifier
135%type<qualifiers> type_qualifiers
136%type<declaration> declaration
137%type<declarations> declarations
138%type<composite> struct_or_union_declaration
139%type<composite> enum_declaration
140%type<param> param
141%type<params> params
142%type<qualification> struct_or_union
143%type<str> opt_id
144%type<include> include
145%type<enum_var> enum_var
146%type<declarations> enum_vars enum_vars_all_but_last
147%type<declaration> enum_var_line enum_var_last_line
148
149%start parse_selector
150
151%union {
152    const char *str;
153    int count;
154    android::Declaration *declaration;
155    android::CompositeDeclaration *composite;
156    std::vector<android::Declaration *> *declarations;
157    android::EnumVarDeclaration *enum_var;
158    android::Declaration *param;
159    std::vector<android::Declaration *> *params;
160    android::Type *type;
161    android::Type::Qualifier *qualifier;
162    android::Type::Qualifier::Qualification qualification;
163    std::vector<android::Type::Qualifier*> *qualifiers;
164    android::Include *include;
165    std::vector<android::Include *> *includes;
166    android::Expression *expression;
167    std::vector<android::Expression *> *expressions;
168}
169
170%%
171
172parse_selector
173    : START_HEADER header
174    | START_EXPR expr_parser
175    ;
176
177expr_parser
178    : expr
179      {
180        ast->setExpression($1);
181      }
182    ;
183
184header
185    : declarations /* well, we are a header file */
186      {
187        ast->setDeclarations($1);
188      }
189    ;
190
191declarations
192    : /* EMPTY */
193      {
194        $$ = new std::vector<Declaration *>;
195      }
196    | declarations declaration
197      {
198        $$ = $1;
199        $$->push_back($2);
200      }
201    | declarations EXTERN C_STRING '{' declarations '}'
202      {
203        $1->push_back(new Note("extern \"C\" { "));
204        $1->insert($1->end(), $5->begin(), $5->end());
205        $1->push_back(new Note("} // end of extern C"));
206        delete $5;
207
208        $$ = $1;
209      }
210    ;
211
212declaration
213    : param ';'
214      {
215        $$ = $1;
216        $$->setComment(get_last_comment());
217      }
218    | struct_or_union_declaration ';'
219      {
220        $$ = $1;
221      }
222    | enum_declaration ';'
223      {
224        $$ = $1;
225      }
226    | TYPEDEF struct_or_union_declaration ';'
227      {
228        // ignore that it is a typedef, for our purposes it doesn't matter
229        $$ = $2;
230      }
231    | TYPEDEF enum_declaration ';'
232      {
233        // ignore that it is a typedef, for our purposes it doesn't matter
234        $$ = $2;
235      }
236    | TYPEDEF param ';' /* looks like 'typedef const int8_t store;' */
237      {
238        $$ = new TypeDef($2->getName(), $2);
239        $$->setComment(get_last_comment());
240      }
241    | DEFINE ID DEFINE_SLURP
242      {
243        $$ = new Define($2, $3);
244        $$->setComment(get_last_comment());
245      }
246    | OTHER_STATEMENT
247      {
248        $$ = new Note($1);
249        $$->setComment(get_last_comment());
250      }
251    | FUNCTION
252      {
253        $$ = new Note($1);
254        $$->setComment(get_last_comment());
255      }
256    | type ID '=' expr ';'
257      {
258        $$ = new Note($1->decorateName($2) + " = " + $4->toString());
259      }
260    | include
261      {
262        $$ = $1;
263        $$->setComment(get_last_comment());
264      }
265    | NAMESPACE ID '{' declarations '}'
266      {
267        $$ = new CompositeDeclaration(Type::Qualifier::STRUCT,
268                                               $2,
269                                               $4);
270
271        get_last_comment(); // clear it
272        $$->setComment("/* from namespace declaration */");
273      }
274    ;
275
276include
277    : INCLUDE '<' INCLUDE_FILE '>'
278      {
279        $$ = new Include($3, true /* isLibrary */);
280      }
281    | INCLUDE '"' INCLUDE_FILE '"'
282      {
283        $$ = new Include($3, false /* isLibrary */);
284      }
285    ;
286
287struct_or_union_declaration
288    : struct_or_union opt_id
289      {
290        $<str>$ = strdup(get_last_comment().c_str());
291      }
292                             '{' declarations '}' opt_id
293      {
294        $$ = new CompositeDeclaration($1, $2, $5);
295        $$->setComment($<str>3);
296
297        if(!std::string($7).empty()) {
298          $$->setName($7);
299        }
300      }
301    ;
302
303opt_comma
304    : /* EMPTY */
305    | ','
306    ;
307
308enum_key
309    : ENUM
310    | ENUM CLASS  /* c++11 */
311    | ENUM STRUCT /* c++11 */
312    ;
313
314opt_enum_base_type
315    : /* EMPTY */ { $$ = NULL; }
316    | ':' type    { $$ = $2; }
317    ;
318
319enum_declaration
320    : enum_key opt_id
321      {
322        $<str>$ = strdup(get_last_comment().c_str());
323      }
324                        opt_enum_base_type '{' enum_vars '}' opt_id
325      {
326        $$ = new CompositeDeclaration(Type::Qualifier::ENUM, $2, $6);
327        $$->setComment($<str>3);
328
329        if($4) {
330          $$->setEnumTypeName($4->decorateName(""));
331          delete $4;
332        }
333
334        if(!std::string($8).empty()) {
335          $$->setName($8);
336        }
337      }
338    ;
339
340enum_vars
341    : /* EMPTY */
342      {
343        $$ = new std::vector<Declaration *>;
344      }
345    | enum_vars_all_but_last enum_var_last_line
346      {
347        $$ = $1;
348        $$->push_back($2);
349      }
350
351enum_vars_all_but_last
352    : /* EMPTY */
353      {
354        $$ = new std::vector<Declaration *>;
355      }
356    | enum_vars_all_but_last enum_var_line
357      {
358        $$ = $1;
359        $$->push_back($2);
360      }
361    ;
362
363enum_var_last_line
364    : enum_var opt_comma { $$ = $1; }
365    | OTHER_STATEMENT
366      {
367        $$ = new Note($1);
368        $$->setComment(get_last_comment());
369      }
370    ;
371
372enum_var_line
373    : enum_var ',' { $$ = $1; }
374    | OTHER_STATEMENT
375      {
376        $$ = new Note($1);
377        $$->setComment(get_last_comment());
378      }
379    ;
380
381enum_var
382    : ID
383      {
384        $$ = new EnumVarDeclaration($1, NULL);
385        $$->setComment(get_last_comment());
386      }
387    | ID '=' expr
388      {
389        $$ = new EnumVarDeclaration($1, $3);
390        $$->setComment(get_last_comment());
391      }
392    ;
393
394params
395    : /* EMPTY */
396      {
397        $$ = new std::vector<Declaration *>;
398      }
399    | param
400      {
401        $$ = new std::vector<Declaration *>;
402        $$->push_back($1);
403      }
404    | params ',' param
405      {
406        $$ = $1;
407        $$->push_back($3);
408      }
409    ;
410
411param
412    : type arrays
413      {
414        $1->setArrays($2);
415
416        // allow for either "const int myvar" or "const int"
417        // as a parameter declaration
418        std::string lastId = $1->removeLastId();
419
420        $$ = new VarDeclaration($1, lastId);
421      }
422    | type '(' '*' ID arrays ')' '(' params ')'
423      {
424        $1->setArrays($5);
425        $$ = new FunctionDeclaration($1, $4, $8);
426      }
427    | type ID '(' params ')'
428      {
429        $$ = new FunctionDeclaration($1, $2, $4);
430      }
431    | type '(' ID ')' '(' params ')'
432      {
433        $$ = new FunctionDeclaration($1, $3, $6);
434      }
435    | VARARGS
436      {
437        $$ = new VarDeclaration(new Type(NULL), "...");
438      }
439    ;
440
441type
442    : type_qualifiers
443      {
444        $$ = new Type($1);
445      }
446    ;
447
448type_qualifiers
449    : type_qualifier
450     {
451        $$ = new std::vector<Type::Qualifier *>;
452        $$->push_back($1);
453     }
454    | type_qualifiers type_qualifier
455     {
456        $$ = $1;
457        $$->push_back($2);
458     }
459    ;
460
461opt_id
462    : /* EMPTY */             { $$ = ""; }
463    |
464     ID                       { $$ = $1; }
465    ;
466
467expr
468    : ID
469      {
470        $$ = Expression::atom(Expression::Type::UNKNOWN, $1, true /* isId*/ );
471      }
472    | VALUE                   { $$ = Expression::atom(Expression::Type::UNKNOWN, $1); }
473    | INTEGRAL_VALUE          { $$ = Expression::atom(Expression::integralType($1), $1); }
474    | '(' expr ')'            { $$ = Expression::parenthesize($2); }
475    | ID '[' expr ']' %prec ARRAY_SUBSCRIPT {
476                                $$ = Expression::arraySubscript($1, $3);
477                              }
478    | ID '(' args ')' %prec FUNCTION_CALL {
479                                $$ = Expression::functionCall($1, $3);
480                              }
481    | expr '?' expr ':' expr  { $$ = Expression::ternary($1, $3, $5); }
482    | expr '+' expr           { $$ = Expression::binary($1, "+", $3); }
483    | expr '-' expr           { $$ = Expression::binary($1, "-", $3); }
484    | expr '/' expr           { $$ = Expression::binary($1, "/", $3); }
485    | expr '*' expr           { $$ = Expression::binary($1, "*", $3); }
486    | expr '%' expr           { $$ = Expression::binary($1, "%%", $3); }
487    | expr '&' expr           { $$ = Expression::binary($1, "&", $3); }
488    | expr '|' expr           { $$ = Expression::binary($1, "|", $3); }
489    | expr '^' expr           { $$ = Expression::binary($1, "^", $3); }
490    | expr LSHIFT expr        { $$ = Expression::binary($1, "<<", $3); }
491    | expr RSHIFT expr        { $$ = Expression::binary($1, ">>", $3); }
492    | '~' expr                { $$ = Expression::unary("~", $2); }
493    | '-' expr %prec UMINUS   { $$ = Expression::unary("-", $2); }
494    | '+' expr %prec UPLUS    { $$ = Expression::unary("+", $2); }
495    ;
496
497args
498    : /* empty */
499      {
500        $$ = new std::vector<Expression *>;
501      }
502    | expr
503      {
504        $$ = new std::vector<Expression *>;
505        $$->push_back($1);
506      }
507    | args ',' expr
508      {
509        $$ = $1;
510        $$->push_back($3);
511      }
512    ;
513
514type_qualifier
515    : UNSIGNED                { $$ = new Type::Qualifier(Type::Qualifier::UNSIGNED); }
516    | SIGNED                  { $$ = new Type::Qualifier(Type::Qualifier::SIGNED); }
517    | VOID                    { $$ = new Type::Qualifier(Type::Qualifier::VOID); }
518    | '*'                     { $$ = new Type::Qualifier(Type::Qualifier::POINTER); }
519    | CONST                   { $$ = new Type::Qualifier(Type::Qualifier::CONST); }
520    | ID                      { $$ = new Type::Qualifier(Type::Qualifier::ID, $1); }
521    | '<' type '>'            { $$ = new Type::Qualifier(Type::Qualifier::GENERICS, $2); }
522    | enum_key                { $$ = new Type::Qualifier(Type::Qualifier::ENUM); }
523    | struct_or_union         { $$ = new Type::Qualifier($1); }
524    ;
525
526struct_or_union
527    : STRUCT                  { $$ = android::Type::Qualifier::STRUCT; }
528    | UNION                   { $$ = android::Type::Qualifier::UNION; }
529    ;
530
531arrays
532    : /* empty */             { $$ = new std::vector<Expression *>; }
533    | arrays array            {
534                                $$ = $1;
535                                $$->push_back($2);
536                              }
537    ;
538
539array
540    : '[' ']'                 { $$ = Expression::atom(Expression::Type::UNKNOWN, " "); }
541    | '[' expr ']'            { $$ = $2; }
542    ;
543
544%%
545