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 17D [0-9] 18L [a-zA-Z_] 19AN [a-zA-Z_0-9] 20H [a-fA-F_0-9] 21E [Ee][+-]?{D}+ 22FS (f|F|l|L) 23IS (u|U|l|L)* 24S [ \t] 25DOT [.] 26PATH ({DOT}|{AN}|\/|-)+ 27ID {L}{AN}* 28 29%{ 30 31#include "AST.h" 32#include "Declaration.h" 33#include "Type.h" 34#include "VarDeclaration.h" 35#include "FunctionDeclaration.h" 36#include "CompositeDeclaration.h" 37#include "Define.h" 38#include "Include.h" 39#include "EnumVarDeclaration.h" 40#include "Note.h" 41#include "TypeDef.h" 42#include "Expression.h" 43 44#include <assert.h> 45#include <utils/Errors.h> 46 47#include "c2hal_y.h" 48 49using namespace android; 50 51int check_type(yyscan_t yyscanner, struct yyguts_t *yyg); 52 53// TODO convert to parse params/lex params 54 55extern int start_token; 56 57extern std::string last_comment; 58 59// :( 60extern int numB; 61extern std::string functionText; 62 63extern std::string defineText; 64extern std::string otherText; 65 66extern bool isOpenGl; 67 68#define YY_USER_ACTION yylloc->first_line = yylineno; 69 70#define ID_UNLESS_OPEN_GL(OPEN_GL_CODE) \ 71 do { \ 72 if (isOpenGl) { \ 73 OPEN_GL_CODE \ 74 } else { \ 75 yylval->str = strdup(yytext); \ 76 return ID; \ 77 } \ 78 } while(0) 79 80#pragma clang diagnostic push 81#pragma clang diagnostic ignored "-Wunused-parameter" 82#pragma clang diagnostic ignored "-Wdeprecated-register" 83 84%} 85 86%option yylineno 87%option nounput 88%option noinput 89%option reentrant 90%option bison-bridge 91%option bison-locations 92%option extra-type="android::AST *" 93 94%x COMMENT_STATE 95%x INCLUDE_STATE 96%x COPY_DECL_STATE 97%x FUNCTION_STATE 98%x DEFINE_STATE 99%x DEFINE_SLURP_STATE 100 101%% 102%{ 103 if (start_token) { 104 int token = start_token; 105 start_token = 0; 106 return token; 107 } 108%} 109 110"\n" { /* needed for yylineno to update */ } 111 112\/\*([^*]|\*+[^*\/])*\*+\/ { last_comment = strdup(yytext); } 113 114"//"[^\r\n]* { /* skip C++ style comment */ } 115 116"__BEGIN_DECLS" { /* macro'd 'extern "C" {' if CPP or nothing */ } 117"__END_DECLS" { /* '}' */ } 118 119"__attribute__((__packed__))" { /* ignore */ } 120"__attribute__((packed))" { /* ignore */ } 121"__attribute__((__deprecated__))" { /* ignore */ } 122 123"EGLAPIENTRYP" { ID_UNLESS_OPEN_GL(return '*';); } 124"EGLAPIENTRY" { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); } 125"GL_APIENTRYP" { ID_UNLESS_OPEN_GL(return '*';); } 126"GL_APIENTRY" { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); } 127"GL_APICALL" { ID_UNLESS_OPEN_GL(/* __attribute__((visibility("default"))) */); } 128 129"#include" { BEGIN(INCLUDE_STATE); return INCLUDE; } 130<INCLUDE_STATE>"<" { return '<'; } 131<INCLUDE_STATE>">" { return '>'; } 132<INCLUDE_STATE>"\"" { return '"'; } 133<INCLUDE_STATE>"\n" { BEGIN(INITIAL); } 134<INCLUDE_STATE>{PATH} { yylval->str = strdup(yytext); return INCLUDE_FILE; } 135<INCLUDE_STATE>. { /* ignore other characters */ } 136 137"static"|"inline" { 138 BEGIN(FUNCTION_STATE); 139 functionText = strdup(yytext); 140 numB = 0; 141 } 142<FUNCTION_STATE>[^{}]+ { functionText += yytext; } 143<FUNCTION_STATE>"{" { functionText += yytext; numB += 1;} 144<FUNCTION_STATE>"}" { 145 functionText += yytext; 146 numB -= 1; 147 148 // Will fail if unbalanced brackets in 149 // strings or comments in the function. 150 if (numB <= 0) { 151 BEGIN(INITIAL); 152 yylval->str = strdup(functionText.c_str()); 153 return FUNCTION; 154 } 155 } 156 157"#"{S}*"define" { BEGIN(DEFINE_STATE); return DEFINE; } 158<DEFINE_STATE>{ID} { 159 BEGIN(DEFINE_SLURP_STATE); 160 defineText = ""; 161 yylval->str = strdup(yytext); 162 return ID; 163 } 164<DEFINE_STATE>. { /* ignore other characters */ } 165 166<DEFINE_SLURP_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ { 167 defineText += yytext; 168 } 169<DEFINE_SLURP_STATE>[^\\\n] { defineText += yytext; } 170<DEFINE_SLURP_STATE>"\\\n" { defineText += yytext; } 171<DEFINE_SLURP_STATE>"\n" { 172 BEGIN(INITIAL); 173 yylval->str = strdup(defineText.c_str()); 174 return DEFINE_SLURP; 175 } 176 177"using" { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); } 178"#"{S}*{L}+ { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); } 179<COPY_DECL_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ { 180 otherText += yytext; 181 } 182<COPY_DECL_STATE>[^\\\n] { otherText += yytext; } 183<COPY_DECL_STATE>"\\\n" { otherText += yytext; } 184<COPY_DECL_STATE>"\n" { 185 BEGIN(INITIAL); 186 yylval->str = strdup(otherText.c_str()); 187 // decls/macros we want to preserve 188 // in the output, but there is nothing 189 // special to do about them yet 190 return OTHER_STATEMENT; 191 } 192 193"struct" { return STRUCT; } 194"union" { return UNION; } 195"enum" { return ENUM; } 196"class" { return CLASS; } 197"const" { return CONST; } 198"typedef" { return TYPEDEF; } 199"void" { return VOID; } 200"unsigned" { return UNSIGNED; } 201"signed" { return SIGNED; } 202"namespace" { return NAMESPACE; } 203"extern" { return EXTERN; } 204"\"C\"" { return C_STRING; } 205 206{ID} { yylval->str = strdup(yytext); return ID; } 2070[xX]{H}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; } 2080{D}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; } 209{D}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; } 210 211{D}+{E}{FS}? { yylval->str = strdup(yytext); return VALUE; } 212{D}+\.{E}?{FS}? { yylval->str = strdup(yytext); return VALUE; } 213{D}*\.{D}+{E}?{FS}? { yylval->str = strdup(yytext); return VALUE; } 214L?\"(\\.|[^\\"])*\" { yylval->str = strdup(yytext); return VALUE; } 215 216"(" { return '('; } 217")" { return ')'; } 218"<" { return '<'; } 219">" { return '>'; } 220"{" { return '{'; } 221"}" { return '}'; } 222"[" { return '['; } 223"]" { return ']'; } 224"?" { return '?'; } 225":" { return ':'; } 226"*" { return '*'; } 227";" { return ';'; } 228"," { return ','; } 229"=" { return '='; } 230"+" { return '+'; } 231"-" { return '-'; } 232"/" { return '/'; } 233"%" { return '%'; } 234"&" { return '&'; } 235"|" { return '|'; } 236"^" { return '^'; } 237"~" { return '~'; } 238"<<" { return LSHIFT; } 239">>" { return RSHIFT; } 240 241"..." { return VARARGS; } 242 243. { /* ignore other characters */ } 244 245%% 246 247#pragma clang diagnostic pop 248 249// allows us to specify what start symbol will be used in the grammar 250int start_token; 251bool should_report_errors; 252 253std::string last_comment; 254 255// this is so frowned upon on so many levels, but here vars are so that we can 256// slurp up function text as a string and don't have to implement 257// the *entire* grammar of C (and C++ in some files) just to parse headers 258int numB; 259std::string functionText; 260 261std::string defineText; 262std::string otherText; 263 264bool isOpenGl; 265 266int yywrap(yyscan_t) { 267 return 1; 268} 269 270status_t parseFile(AST *ast) { 271 FILE *file = fopen(ast->getFilename().c_str(), "rb"); 272 273 if (file == NULL) { 274 return -errno; 275 } 276 277 start_token = START_HEADER; 278 isOpenGl = ast->isOpenGl(); 279 should_report_errors = true; 280 281 yyscan_t scanner; 282 yylex_init_extra(ast, &scanner); 283 ast->setScanner(scanner); 284 285 yyset_in(file, scanner); 286 int res = yyparse(ast); 287 288 yylex_destroy(scanner); 289 ast->setScanner(NULL); 290 291 fclose(file); 292 file = NULL; 293 294 return res; 295} 296 297status_t parseExpression(AST *ast, std::string str) { 298 start_token = START_EXPR; 299 isOpenGl = ast->isOpenGl(); 300 should_report_errors = false; 301 302 yyscan_t scanner; 303 yylex_init_extra(ast, &scanner); 304 ast->setScanner(scanner); 305 306 YY_BUFFER_STATE buf = yy_scan_string(str.c_str(), scanner); 307 308 int res = yyparse(ast); 309 310 yy_delete_buffer(buf, scanner); 311 312 yylex_destroy(scanner); 313 ast->setScanner(NULL); 314 315 return res; 316} 317