blob: 9873de25060669097fcd73d00d2f1e6956e5c989 [file] [log] [blame]
Steven Morelandf1a35f72016-08-17 08:41:49 -07001/*
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 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 Hongcea77732016-10-03 14:59:42 -0700194"class" { return CLASS; }
Steven Morelandf1a35f72016-08-17 08:41:49 -0700195"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; }
2050[xX]{H}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
2060{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; }
212L?\"(\\.|[^\\"])*\" { 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
248int start_token;
249bool should_report_errors;
250
251std::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
256int numB;
257std::string functionText;
258
259std::string defineText;
260std::string otherText;
261
262bool isOpenGl;
263
264int yywrap(yyscan_t) {
265 return 1;
266}
267
268status_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
295status_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}