diff options
author | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2014-02-26 18:24:40 +0400 |
---|---|---|
committer | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2014-03-01 13:02:58 +0400 |
commit | 65d0d66fdc30d351998192fdb4014a848eff9a78 (patch) | |
tree | 5548eb8c116d85016e085dd75668a9e891412808 /GLESv2/yagl_glsl_lexer.l | |
parent | a4cc60b70f8e04ad3c24f4899a391b8febe0f46b (diff) | |
download | emulator-yagl-65d0d66fdc30d351998192fdb4014a848eff9a78.tar.gz emulator-yagl-65d0d66fdc30d351998192fdb4014a848eff9a78.tar.bz2 emulator-yagl-65d0d66fdc30d351998192fdb4014a848eff9a78.zip |
YaGL: Using flex/bison-based GLSL ES patcher
Our old method of GLSL ES patching via simple tokenization
isn't feasible for GLESv3 support, there're many GLSL ES
and desktop GLSL variations and we must handle all of them.
Also, we would like to have full shader validation in
the future, thus, we can just extend this parser instead of
introducing a new one
Change-Id: Ib505a0b22c6dfa810b99a7353b15e8800ff5b55f
Diffstat (limited to 'GLESv2/yagl_glsl_lexer.l')
-rw-r--r-- | GLESv2/yagl_glsl_lexer.l | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/GLESv2/yagl_glsl_lexer.l b/GLESv2/yagl_glsl_lexer.l new file mode 100644 index 0000000..a434be9 --- /dev/null +++ b/GLESv2/yagl_glsl_lexer.l @@ -0,0 +1,308 @@ +%{ +#include <GL/gl.h> +#include "yagl_glsl_state.h" +#include "yagl_malloc.h" + +#define YY_NO_INPUT + +#define YY_INPUT(buf, result, max_size) \ + result = string_input(buf, max_size, yyscanner); + +static yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner); +%} + +%option bison-bridge reentrant noyywrap +%option nounput +%option never-interactive +%option prefix="yagl_glsl_lexer_" +%option extra-type="struct yagl_glsl_state *" + +%x COMMENT PP + +WS [ \r\t\v\f] +PRECISION "lowp"|"mediump"|"highp"|"precision"[^;\n]+;? +GLEXT "GL_"[0-9a-zA-Z]+"_"[0-9a-zA-Z_]+ +CONTROL [()\[\]{},;?:/%*&|^!+\-=<>\.] +STRING [^ \r\t\v\f\n()\[\]{},;?:/%*&|^!+\-=<>\.]+ + +%% + +"//"[^\n]* { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_comment(state, strlen(yytext)); +} + +"/*" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(COMMENT); + yagl_glsl_state_new_comment(state, strlen(yytext)); +} + +^{WS}*#{WS}*version { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(PP); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_VERSION; +} + +^{WS}*#{WS}*define { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(PP); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_DEFINE; +} + +[\n]+ { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_pending(state, yytext); +} + +{WS}+ { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_pending(state, yytext); +} + +"gl_MaxVertexUniformVectors" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_MAXVERTEXUNIFORMVECTORS; +} + +"gl_MaxFragmentUniformVectors" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_MAXFRAGMENTUNIFORMVECTORS; +} + +"gl_MaxVaryingVectors" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_MAXVARYINGVECTORS; +} + +"attribute" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_ATTRIBUTE; +} + +"varying" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_VARYING; +} + +"texture1D" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_TEXTURE; +} + +"texture2D" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_TEXTURE; +} + +"texture3D" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_TEXTURE; +} + +"textureCube" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_TEXTURE; +} + +"gl_FragColor" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_GLFRAGCOLOR; +} + +{GLEXT} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_GLEXT; +} + +{PRECISION} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_PRECISION; +} + +{CONTROL} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_pending(state, yytext); +} + +{STRING} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_pending(state, yytext); +} + +<PP>\n { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(INITIAL); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_EOL; +} + +<PP>{WS}+ { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_pending(state, yytext); +} + +<PP>[1-9][0-9]* { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_integer_token(state, yylval, strtol(yytext, NULL, 10)); + return TOK_INTEGER; +} + +<PP>"es" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_ES; +} + +<PP>{GLEXT} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_GLEXT; +} + +<PP>{PRECISION} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_PRECISION; +} + +<PP>{CONTROL} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_STRING; +} + +<PP>{STRING} { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_str_token(state, yylval, yytext); + return TOK_STRING; +} + +<COMMENT>[^*\n]* { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_comment(state, strlen(yytext)); +} + +<COMMENT>[^*\n]*\n { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_comment(state, strlen(yytext) - 1); + yagl_glsl_state_new_pending(state, "\n"); +} + +<COMMENT>"*"+[^*/\n]* { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_comment(state, strlen(yytext)); +} + +<COMMENT>"*"+[^*/\n]*\n { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + yagl_glsl_state_new_comment(state, strlen(yytext) - 1); + yagl_glsl_state_new_pending(state, "\n"); +} + +<COMMENT>"*"+"/" { + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + BEGIN(INITIAL); + yagl_glsl_state_new_comment(state, strlen(yytext)); +} + +%% + +static yy_size_t string_input(char *buf, yy_size_t max_size, yyscan_t yyscanner) +{ + struct yagl_glsl_state *state = yagl_glsl_lexer_get_extra(yyscanner); + int rem = state->source_len - state->source_pos; + int num_read = (rem < max_size) ? rem : max_size; + + memcpy(buf, state->source + state->source_pos, num_read); + + state->source_pos += num_read; + + return num_read; +} + +//extern int yagl_glsl_debug; + +int yagl_glsl_state_init(struct yagl_glsl_state *state, + GLenum shader_type, + const char *source, + int source_len, + const char **extensions, + int num_extensions, + int es3_supported) +{ + yyscan_t scanner = NULL; + + memset(state, 0, sizeof(*state)); + + //yagl_glsl_debug = 1; + + if (yagl_glsl_lexer_lex_init_extra(state, &scanner)) { + return 0; + } + + state->shader_type = shader_type; + state->source = source; + state->source_len = source_len; + state->extensions = extensions; + state->num_extensions = num_extensions; + state->es3_supported = es3_supported; + state->scanner = scanner; + state->token_index = 1; + + yagl_glsl_state_set_version(state, 120, 0); + + yagl_vector_init(&state->header, sizeof(char), 0); + yagl_vector_init(&state->output, sizeof(char), 0); + yagl_list_init(&state->pending_list); + yagl_vector_init(&state->pending, sizeof(char), 0); + yagl_vector_init(&state->strings, sizeof(char*), 0); + + return 1; +} + +void yagl_glsl_state_cleanup(struct yagl_glsl_state *state) +{ + yyscan_t scanner = state->scanner; + int i; + char **tmp; + struct yagl_glsl_pending *it, *tmp_it; + + tmp = yagl_vector_data(&state->strings); + + for (i = 0; i < yagl_vector_size(&state->strings); ++i) { + free(*(tmp + i)); + } + + yagl_vector_cleanup(&state->strings); + + yagl_vector_cleanup(&state->pending); + + yagl_list_for_each_safe(struct yagl_glsl_pending, + it, + tmp_it, + &state->pending_list, list) { + yagl_list_remove(&it->list); + yagl_free(it); + } + + yagl_vector_cleanup(&state->output); + + yagl_vector_cleanup(&state->header); + + yagl_glsl_lexer_lex_destroy(scanner); +} |