You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
13 KiB
544 lines
13 KiB
/* |
|
* Copyright (C) 2016 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
%{ |
|
|
|
#include "AST.h" |
|
#include "Declaration.h" |
|
#include "Type.h" |
|
#include "VarDeclaration.h" |
|
#include "FunctionDeclaration.h" |
|
#include "CompositeDeclaration.h" |
|
#include "Define.h" |
|
#include "Include.h" |
|
#include "EnumVarDeclaration.h" |
|
#include "Note.h" |
|
#include "TypeDef.h" |
|
#include "Expression.h" |
|
|
|
#include "c2hal_y.h" |
|
|
|
#include <stdio.h> |
|
#include <algorithm> |
|
|
|
using namespace android; |
|
|
|
extern int yylex(YYSTYPE *yylval_param, YYLTYPE *llocp, void *); |
|
|
|
int yyerror(YYLTYPE *llocp, AST *, const char *s) { |
|
extern bool should_report_errors; |
|
|
|
if (!should_report_errors) { |
|
return 0; |
|
} |
|
|
|
fflush(stdout); |
|
LOG(ERROR) << " " |
|
<< s |
|
<< " near line " |
|
<< llocp->first_line; |
|
|
|
return 0; |
|
} |
|
|
|
#define scanner ast->scanner() |
|
|
|
std::string get_last_comment() { |
|
extern std::string last_comment; |
|
|
|
std::string ret{last_comment}; |
|
|
|
// clear the last comment now that it's been taken |
|
last_comment = ""; |
|
|
|
return ret; |
|
} |
|
|
|
%} |
|
|
|
%parse-param { android::AST *ast } |
|
%lex-param { void *scanner } |
|
%locations |
|
%pure-parser |
|
%glr-parser |
|
|
|
/* These have to do with the fact that |
|
* struct_or_union_declaration and enum_declaration |
|
* both start with STRUCT/UNION/ENUM opt_id |
|
* and type_qualifiers contain these. |
|
*/ |
|
%expect 3 |
|
|
|
%token START_HEADER |
|
%token START_EXPR |
|
|
|
%token STRUCT |
|
%token UNION |
|
%token ENUM |
|
%token CLASS |
|
%token CONST |
|
%token VOID |
|
%token INCLUDE |
|
%token DEFINE |
|
%token TYPEDEF |
|
%token UNSIGNED |
|
%token SIGNED |
|
%token LSHIFT |
|
%token RSHIFT |
|
%token VARARGS |
|
%token NAMESPACE |
|
%token EXTERN |
|
%token C_STRING |
|
|
|
%left ',' |
|
%right '?' ':' |
|
%left '|' |
|
%left '^' |
|
%left '&' |
|
%left RSHIFT LSHIFT |
|
%left '+' '-' |
|
%left '*' '/' '%' |
|
%right '~' '!' UMINUS UPLUS |
|
%left ARRAY_SUBSCRIPT FUNCTION_CALL |
|
|
|
%right STRUCT ENUM |
|
|
|
%token<str> ID |
|
%token<str> COMMENT |
|
%token<str> VALUE |
|
%token<str> INTEGRAL_VALUE |
|
%token<str> INCLUDE_FILE |
|
%token<str> FUNCTION |
|
%token<str> DEFINE_SLURP |
|
%token<str> OTHER_STATEMENT |
|
|
|
%type<expression> array |
|
%type<expressions> arrays |
|
%type<expression> expr |
|
%type<expressions> args |
|
%type<type> type |
|
%type<type> opt_enum_base_type |
|
%type<qualifier> type_qualifier |
|
%type<qualifiers> type_qualifiers |
|
%type<declaration> declaration |
|
%type<declarations> declarations |
|
%type<composite> struct_or_union_declaration |
|
%type<composite> enum_declaration |
|
%type<param> param |
|
%type<params> params |
|
%type<qualification> struct_or_union |
|
%type<str> opt_id |
|
%type<include> include |
|
%type<enum_var> enum_var |
|
%type<declarations> enum_vars enum_vars_all_but_last |
|
%type<declaration> enum_var_line enum_var_last_line |
|
|
|
%start parse_selector |
|
|
|
%union { |
|
const char *str; |
|
int count; |
|
android::Declaration *declaration; |
|
android::CompositeDeclaration *composite; |
|
std::vector<android::Declaration *> *declarations; |
|
android::EnumVarDeclaration *enum_var; |
|
android::Declaration *param; |
|
std::vector<android::Declaration *> *params; |
|
android::Type *type; |
|
android::Type::Qualifier *qualifier; |
|
android::Type::Qualifier::Qualification qualification; |
|
std::vector<android::Type::Qualifier*> *qualifiers; |
|
android::Include *include; |
|
std::vector<android::Include *> *includes; |
|
android::Expression *expression; |
|
std::vector<android::Expression *> *expressions; |
|
} |
|
|
|
%% |
|
|
|
parse_selector |
|
: START_HEADER header |
|
| START_EXPR expr_parser |
|
; |
|
|
|
expr_parser |
|
: expr |
|
{ |
|
ast->setExpression($1); |
|
} |
|
; |
|
|
|
header |
|
: declarations /* well, we are a header file */ |
|
{ |
|
ast->setDeclarations($1); |
|
} |
|
; |
|
|
|
declarations |
|
: /* EMPTY */ |
|
{ |
|
$$ = new std::vector<Declaration *>; |
|
} |
|
| declarations declaration |
|
{ |
|
$$ = $1; |
|
$$->push_back($2); |
|
} |
|
| declarations EXTERN C_STRING '{' declarations '}' |
|
{ |
|
$1->push_back(new Note("extern \"C\" { ")); |
|
$1->insert($1->end(), $5->begin(), $5->end()); |
|
$1->push_back(new Note("} // end of extern C")); |
|
delete $5; |
|
|
|
$$ = $1; |
|
} |
|
; |
|
|
|
declaration |
|
: param ';' |
|
{ |
|
$$ = $1; |
|
$$->setComment(get_last_comment()); |
|
} |
|
| struct_or_union_declaration ';' |
|
{ |
|
$$ = $1; |
|
} |
|
| enum_declaration ';' |
|
{ |
|
$$ = $1; |
|
} |
|
| TYPEDEF struct_or_union_declaration ';' |
|
{ |
|
// ignore that it is a typedef, for our purposes it doesn't matter |
|
$$ = $2; |
|
} |
|
| TYPEDEF enum_declaration ';' |
|
{ |
|
// ignore that it is a typedef, for our purposes it doesn't matter |
|
$$ = $2; |
|
} |
|
| TYPEDEF param ';' /* looks like 'typedef const int8_t store;' */ |
|
{ |
|
$$ = new TypeDef($2->getName(), $2); |
|
$$->setComment(get_last_comment()); |
|
} |
|
| DEFINE ID DEFINE_SLURP |
|
{ |
|
$$ = new Define($2, $3); |
|
$$->setComment(get_last_comment()); |
|
} |
|
| OTHER_STATEMENT |
|
{ |
|
$$ = new Note($1); |
|
$$->setComment(get_last_comment()); |
|
} |
|
| FUNCTION |
|
{ |
|
$$ = new Note($1); |
|
$$->setComment(get_last_comment()); |
|
} |
|
| type ID '=' expr ';' |
|
{ |
|
$$ = new Note($1->decorateName($2) + " = " + $4->toString()); |
|
} |
|
| include |
|
{ |
|
$$ = $1; |
|
$$->setComment(get_last_comment()); |
|
} |
|
| NAMESPACE ID '{' declarations '}' |
|
{ |
|
$$ = new CompositeDeclaration(Type::Qualifier::STRUCT, |
|
$2, |
|
$4); |
|
|
|
get_last_comment(); // clear it |
|
$$->setComment("/* from namespace declaration */"); |
|
} |
|
; |
|
|
|
include |
|
: INCLUDE '<' INCLUDE_FILE '>' |
|
{ |
|
$$ = new Include($3, true /* isLibrary */); |
|
} |
|
| INCLUDE '"' INCLUDE_FILE '"' |
|
{ |
|
$$ = new Include($3, false /* isLibrary */); |
|
} |
|
; |
|
|
|
struct_or_union_declaration |
|
: struct_or_union opt_id |
|
{ |
|
$<str>$ = strdup(get_last_comment().c_str()); |
|
} |
|
'{' declarations '}' opt_id |
|
{ |
|
$$ = new CompositeDeclaration($1, $2, $5); |
|
$$->setComment($<str>3); |
|
|
|
if(!std::string($7).empty()) { |
|
$$->setName($7); |
|
} |
|
} |
|
; |
|
|
|
opt_comma |
|
: /* EMPTY */ |
|
| ',' |
|
; |
|
|
|
enum_key |
|
: ENUM |
|
| ENUM CLASS /* c++11 */ |
|
| ENUM STRUCT /* c++11 */ |
|
; |
|
|
|
opt_enum_base_type |
|
: /* EMPTY */ { $$ = NULL; } |
|
| ':' type { $$ = $2; } |
|
; |
|
|
|
enum_declaration |
|
: enum_key opt_id |
|
{ |
|
$<str>$ = strdup(get_last_comment().c_str()); |
|
} |
|
opt_enum_base_type '{' enum_vars '}' opt_id |
|
{ |
|
$$ = new CompositeDeclaration(Type::Qualifier::ENUM, $2, $6); |
|
$$->setComment($<str>3); |
|
|
|
if($4) { |
|
$$->setEnumTypeName($4->decorateName("")); |
|
delete $4; |
|
} |
|
|
|
if(!std::string($8).empty()) { |
|
$$->setName($8); |
|
} |
|
} |
|
; |
|
|
|
enum_vars |
|
: /* EMPTY */ |
|
{ |
|
$$ = new std::vector<Declaration *>; |
|
} |
|
| enum_vars_all_but_last enum_var_last_line |
|
{ |
|
$$ = $1; |
|
$$->push_back($2); |
|
} |
|
|
|
enum_vars_all_but_last |
|
: /* EMPTY */ |
|
{ |
|
$$ = new std::vector<Declaration *>; |
|
} |
|
| enum_vars_all_but_last enum_var_line |
|
{ |
|
$$ = $1; |
|
$$->push_back($2); |
|
} |
|
; |
|
|
|
enum_var_last_line |
|
: enum_var opt_comma { $$ = $1; } |
|
| OTHER_STATEMENT |
|
{ |
|
$$ = new Note($1); |
|
$$->setComment(get_last_comment()); |
|
} |
|
; |
|
|
|
enum_var_line |
|
: enum_var ',' { $$ = $1; } |
|
| OTHER_STATEMENT |
|
{ |
|
$$ = new Note($1); |
|
$$->setComment(get_last_comment()); |
|
} |
|
; |
|
|
|
enum_var |
|
: ID |
|
{ |
|
$$ = new EnumVarDeclaration($1, NULL); |
|
$$->setComment(get_last_comment()); |
|
} |
|
| ID '=' expr |
|
{ |
|
$$ = new EnumVarDeclaration($1, $3); |
|
$$->setComment(get_last_comment()); |
|
} |
|
; |
|
|
|
params |
|
: /* EMPTY */ |
|
{ |
|
$$ = new std::vector<Declaration *>; |
|
} |
|
| param |
|
{ |
|
$$ = new std::vector<Declaration *>; |
|
$$->push_back($1); |
|
} |
|
| params ',' param |
|
{ |
|
$$ = $1; |
|
$$->push_back($3); |
|
} |
|
; |
|
|
|
param |
|
: type arrays |
|
{ |
|
$1->setArrays($2); |
|
|
|
// allow for either "const int myvar" or "const int" |
|
// as a parameter declaration |
|
std::string lastId = $1->removeLastId(); |
|
|
|
$$ = new VarDeclaration($1, lastId); |
|
} |
|
| type '(' '*' ID arrays ')' '(' params ')' |
|
{ |
|
$1->setArrays($5); |
|
$$ = new FunctionDeclaration($1, $4, $8); |
|
} |
|
| type ID '(' params ')' |
|
{ |
|
$$ = new FunctionDeclaration($1, $2, $4); |
|
} |
|
| type '(' ID ')' '(' params ')' |
|
{ |
|
$$ = new FunctionDeclaration($1, $3, $6); |
|
} |
|
| VARARGS |
|
{ |
|
$$ = new VarDeclaration(new Type(NULL), "..."); |
|
} |
|
; |
|
|
|
type |
|
: type_qualifiers |
|
{ |
|
$$ = new Type($1); |
|
} |
|
; |
|
|
|
type_qualifiers |
|
: type_qualifier |
|
{ |
|
$$ = new std::vector<Type::Qualifier *>; |
|
$$->push_back($1); |
|
} |
|
| type_qualifiers type_qualifier |
|
{ |
|
$$ = $1; |
|
$$->push_back($2); |
|
} |
|
; |
|
|
|
opt_id |
|
: /* EMPTY */ { $$ = ""; } |
|
| |
|
ID { $$ = $1; } |
|
; |
|
|
|
expr |
|
: ID |
|
{ |
|
$$ = Expression::atom(Expression::Type::UNKNOWN, $1, true /* isId*/ ); |
|
} |
|
| VALUE { $$ = Expression::atom(Expression::Type::UNKNOWN, $1); } |
|
| INTEGRAL_VALUE { $$ = Expression::atom(Expression::integralType($1), $1); } |
|
| '(' expr ')' { $$ = Expression::parenthesize($2); } |
|
| ID '[' expr ']' %prec ARRAY_SUBSCRIPT { |
|
$$ = Expression::arraySubscript($1, $3); |
|
} |
|
| ID '(' args ')' %prec FUNCTION_CALL { |
|
$$ = Expression::functionCall($1, $3); |
|
} |
|
| expr '?' expr ':' expr { $$ = Expression::ternary($1, $3, $5); } |
|
| expr '+' expr { $$ = Expression::binary($1, "+", $3); } |
|
| expr '-' expr { $$ = Expression::binary($1, "-", $3); } |
|
| expr '/' expr { $$ = Expression::binary($1, "/", $3); } |
|
| expr '*' expr { $$ = Expression::binary($1, "*", $3); } |
|
| expr '%' expr { $$ = Expression::binary($1, "%%", $3); } |
|
| expr '&' expr { $$ = Expression::binary($1, "&", $3); } |
|
| expr '|' expr { $$ = Expression::binary($1, "|", $3); } |
|
| expr '^' expr { $$ = Expression::binary($1, "^", $3); } |
|
| expr LSHIFT expr { $$ = Expression::binary($1, "<<", $3); } |
|
| expr RSHIFT expr { $$ = Expression::binary($1, ">>", $3); } |
|
| '~' expr { $$ = Expression::unary("~", $2); } |
|
| '-' expr %prec UMINUS { $$ = Expression::unary("-", $2); } |
|
| '+' expr %prec UPLUS { $$ = Expression::unary("+", $2); } |
|
; |
|
|
|
args |
|
: /* empty */ |
|
{ |
|
$$ = new std::vector<Expression *>; |
|
} |
|
| expr |
|
{ |
|
$$ = new std::vector<Expression *>; |
|
$$->push_back($1); |
|
} |
|
| args ',' expr |
|
{ |
|
$$ = $1; |
|
$$->push_back($3); |
|
} |
|
; |
|
|
|
type_qualifier |
|
: UNSIGNED { $$ = new Type::Qualifier(Type::Qualifier::UNSIGNED); } |
|
| SIGNED { $$ = new Type::Qualifier(Type::Qualifier::SIGNED); } |
|
| VOID { $$ = new Type::Qualifier(Type::Qualifier::VOID); } |
|
| '*' { $$ = new Type::Qualifier(Type::Qualifier::POINTER); } |
|
| CONST { $$ = new Type::Qualifier(Type::Qualifier::CONST); } |
|
| ID { $$ = new Type::Qualifier(Type::Qualifier::ID, $1); } |
|
| '<' type '>' { $$ = new Type::Qualifier(Type::Qualifier::GENERICS, $2); } |
|
| enum_key { $$ = new Type::Qualifier(Type::Qualifier::ENUM); } |
|
| struct_or_union { $$ = new Type::Qualifier($1); } |
|
; |
|
|
|
struct_or_union |
|
: STRUCT { $$ = android::Type::Qualifier::STRUCT; } |
|
| UNION { $$ = android::Type::Qualifier::UNION; } |
|
; |
|
|
|
arrays |
|
: /* empty */ { $$ = new std::vector<Expression *>; } |
|
| arrays array { |
|
$$ = $1; |
|
$$->push_back($2); |
|
} |
|
; |
|
|
|
array |
|
: '[' ']' { $$ = Expression::atom(Expression::Type::UNKNOWN, " "); } |
|
| '[' expr ']' { $$ = $2; } |
|
; |
|
|
|
%%
|
|
|