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.
545 lines
13 KiB
545 lines
13 KiB
4 months ago
|
/*
|
||
|
* 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
|
||
|
%define api.pure
|
||
|
%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; }
|
||
|
;
|
||
|
|
||
|
%%
|