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