summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/program_lexer.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/program_lexer.l')
-rw-r--r--src/mesa/shader/program_lexer.l482
1 files changed, 482 insertions, 0 deletions
diff --git a/src/mesa/shader/program_lexer.l b/src/mesa/shader/program_lexer.l
new file mode 100644
index 00000000000..2d207726315
--- /dev/null
+++ b/src/mesa/shader/program_lexer.l
@@ -0,0 +1,482 @@
+%{
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "main/glheader.h"
+#include "prog_instruction.h"
+
+#include "program_parser.h"
+#include "program_parse.tab.h"
+
+#define require_ARB_vp (yyextra->mode == ARB_vertex)
+#define require_ARB_fp (yyextra->mode == ARB_fragment)
+
+#define return_token_or_IDENTIFIER(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define return_token_or_DOT(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yyless(1); \
+ return DOT; \
+ } \
+ } while (0)
+
+
+#define return_opcode(condition, token, opcode, sat) \
+ do { \
+ if (condition) { \
+ yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
+ yylval->temp_inst.SaturateMode = SATURATE_ ## sat; \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
+ SWIZZLE_NIL, SWIZZLE_NIL)
+
+static unsigned
+mask_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return WRITEMASK_X;
+ case 'y':
+ case 'g':
+ return WRITEMASK_Y;
+ case 'z':
+ case 'b':
+ return WRITEMASK_Z;
+ case 'w':
+ case 'a':
+ return WRITEMASK_W;
+ }
+
+ return 0;
+}
+
+static unsigned
+swiz_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return SWIZZLE_X;
+ case 'y':
+ case 'g':
+ return SWIZZLE_Y;
+ case 'z':
+ case 'b':
+ return SWIZZLE_Z;
+ case 'w':
+ case 'a':
+ return SWIZZLE_W;
+ }
+
+ return 0;
+}
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->first_column = yylloc->last_column; \
+ yylloc->last_column += yyleng; \
+ if ((yylloc->first_line == 1) \
+ && (yylloc->first_column == 1)) { \
+ yylloc->position = 1; \
+ } else { \
+ yylloc->position += yylloc->last_column - yylloc->first_column; \
+ } \
+ } while(0);
+
+#define YY_EXTRA_TYPE struct asm_parser_state *
+%}
+
+num [0-9]+
+exp [Ee][-+]?[0-9]+
+frac "."[0-9]+
+dot "."[ \t]*
+
+%option bison-bridge bison-locations reentrant noyywrap
+%%
+
+"!!ARBvp1.0" { return ARBvp_10; }
+"!!ARBfp1.0" { return ARBfp_10; }
+ADDRESS {
+ yylval->integer = at_address;
+ return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
+}
+ALIAS { return ALIAS; }
+ATTRIB { return ATTRIB; }
+END { return END; }
+OPTION { return OPTION; }
+OUTPUT { return OUTPUT; }
+PARAM { return PARAM; }
+TEMP { yylval->integer = at_temp; return TEMP; }
+
+ABS { return_opcode( 1, VECTOR_OP, ABS, OFF); }
+ABS_SAT { return_opcode(require_ARB_fp, VECTOR_OP, ABS, ZERO_ONE); }
+ADD { return_opcode( 1, BIN_OP, ADD, OFF); }
+ADD_SAT { return_opcode(require_ARB_fp, BIN_OP, ADD, ZERO_ONE); }
+ARL { return_opcode(require_ARB_vp, ARL, ARL, OFF); }
+
+CMP { return_opcode(require_ARB_fp, TRI_OP, CMP, OFF); }
+CMP_SAT { return_opcode(require_ARB_fp, TRI_OP, CMP, ZERO_ONE); }
+COS { return_opcode(require_ARB_fp, SCALAR_OP, COS, OFF); }
+COS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, COS, ZERO_ONE); }
+
+DP3 { return_opcode( 1, BIN_OP, DP3, OFF); }
+DP3_SAT { return_opcode(require_ARB_fp, BIN_OP, DP3, ZERO_ONE); }
+DP4 { return_opcode( 1, BIN_OP, DP4, OFF); }
+DP4_SAT { return_opcode(require_ARB_fp, BIN_OP, DP4, ZERO_ONE); }
+DPH { return_opcode( 1, BIN_OP, DPH, OFF); }
+DPH_SAT { return_opcode(require_ARB_fp, BIN_OP, DPH, ZERO_ONE); }
+DST { return_opcode( 1, BIN_OP, DST, OFF); }
+DST_SAT { return_opcode(require_ARB_fp, BIN_OP, DST, ZERO_ONE); }
+
+EX2 { return_opcode( 1, SCALAR_OP, EX2, OFF); }
+EX2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, EX2, ZERO_ONE); }
+EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, OFF); }
+
+FLR { return_opcode( 1, VECTOR_OP, FLR, OFF); }
+FLR_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FLR, ZERO_ONE); }
+FRC { return_opcode( 1, VECTOR_OP, FRC, OFF); }
+FRC_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FRC, ZERO_ONE); }
+
+KIL { return_opcode(require_ARB_fp, KIL, KIL, OFF); }
+
+LIT { return_opcode( 1, VECTOR_OP, LIT, OFF); }
+LIT_SAT { return_opcode(require_ARB_fp, VECTOR_OP, LIT, ZERO_ONE); }
+LG2 { return_opcode( 1, SCALAR_OP, LG2, OFF); }
+LG2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, LG2, ZERO_ONE); }
+LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, OFF); }
+LRP { return_opcode(require_ARB_fp, TRI_OP, LRP, OFF); }
+LRP_SAT { return_opcode(require_ARB_fp, TRI_OP, LRP, ZERO_ONE); }
+
+MAD { return_opcode( 1, TRI_OP, MAD, OFF); }
+MAD_SAT { return_opcode(require_ARB_fp, TRI_OP, MAD, ZERO_ONE); }
+MAX { return_opcode( 1, BIN_OP, MAX, OFF); }
+MAX_SAT { return_opcode(require_ARB_fp, BIN_OP, MAX, ZERO_ONE); }
+MIN { return_opcode( 1, BIN_OP, MIN, OFF); }
+MIN_SAT { return_opcode(require_ARB_fp, BIN_OP, MIN, ZERO_ONE); }
+MOV { return_opcode( 1, VECTOR_OP, MOV, OFF); }
+MOV_SAT { return_opcode(require_ARB_fp, VECTOR_OP, MOV, ZERO_ONE); }
+MUL { return_opcode( 1, BIN_OP, MUL, OFF); }
+MUL_SAT { return_opcode(require_ARB_fp, BIN_OP, MUL, ZERO_ONE); }
+
+POW { return_opcode( 1, BINSC_OP, POW, OFF); }
+POW_SAT { return_opcode(require_ARB_fp, BINSC_OP, POW, ZERO_ONE); }
+
+RCP { return_opcode( 1, SCALAR_OP, RCP, OFF); }
+RCP_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RCP, ZERO_ONE); }
+RSQ { return_opcode( 1, SCALAR_OP, RSQ, OFF); }
+RSQ_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RSQ, ZERO_ONE); }
+
+SCS { return_opcode(require_ARB_fp, SCALAR_OP, SCS, OFF); }
+SCS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SCS, ZERO_ONE); }
+SGE { return_opcode( 1, BIN_OP, SGE, OFF); }
+SGE_SAT { return_opcode(require_ARB_fp, BIN_OP, SGE, ZERO_ONE); }
+SIN { return_opcode(require_ARB_fp, SCALAR_OP, SIN, OFF); }
+SIN_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SIN, ZERO_ONE); }
+SLT { return_opcode( 1, BIN_OP, SLT, OFF); }
+SLT_SAT { return_opcode(require_ARB_fp, BIN_OP, SLT, ZERO_ONE); }
+SUB { return_opcode( 1, BIN_OP, SUB, OFF); }
+SUB_SAT { return_opcode(require_ARB_fp, BIN_OP, SUB, ZERO_ONE); }
+SWZ { return_opcode( 1, SWZ, SWZ, OFF); }
+SWZ_SAT { return_opcode(require_ARB_fp, SWZ, SWZ, ZERO_ONE); }
+
+TEX { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, OFF); }
+TEX_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, ZERO_ONE); }
+TXB { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, OFF); }
+TXB_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, ZERO_ONE); }
+TXP { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, OFF); }
+TXP_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, ZERO_ONE); }
+
+XPD { return_opcode( 1, BIN_OP, XPD, OFF); }
+XPD_SAT { return_opcode(require_ARB_fp, BIN_OP, XPD, ZERO_ONE); }
+
+vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
+fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
+program { return PROGRAM; }
+state { return STATE; }
+result { return RESULT; }
+
+{dot}ambient { return AMBIENT; }
+{dot}attenuation { return_token_or_DOT(require_ARB_vp, ATTENUATION); }
+{dot}back { return BACK; }
+{dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); }
+{dot}color { return COLOR; }
+{dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); }
+{dot}diffuse { return DIFFUSE; }
+{dot}direction { return DIRECTION; }
+{dot}emission { return EMISSION; }
+{dot}env { return ENV; }
+{dot}eye { return EYE; }
+{dot}fogcoord { return FOGCOORD; }
+{dot}fog { return FOG; }
+{dot}front { return FRONT; }
+{dot}half { return HALF; }
+{dot}inverse { return INVERSE; }
+{dot}invtrans { return INVTRANS; }
+{dot}light { return LIGHT; }
+{dot}lightmodel { return LIGHTMODEL; }
+{dot}lightprod { return LIGHTPROD; }
+{dot}local { return LOCAL; }
+{dot}material { return MATERIAL; }
+{dot}program { return MAT_PROGRAM; }
+{dot}matrix { return MATRIX; }
+{dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
+{dot}modelview { return MODELVIEW; }
+{dot}mvp { return MVP; }
+{dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); }
+{dot}object { return OBJECT; }
+{dot}palette { return PALETTE; }
+{dot}params { return PARAMS; }
+{dot}plane { return PLANE; }
+{dot}point { return_token_or_DOT(require_ARB_vp, POINT); }
+{dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
+{dot}position { return POSITION; }
+{dot}primary { return PRIMARY; }
+{dot}projection { return PROJECTION; }
+{dot}range { return_token_or_DOT(require_ARB_fp, RANGE); }
+{dot}row { return ROW; }
+{dot}scenecolor { return SCENECOLOR; }
+{dot}secondary { return SECONDARY; }
+{dot}shininess { return SHININESS; }
+{dot}size { return_token_or_DOT(require_ARB_vp, SIZE); }
+{dot}specular { return SPECULAR; }
+{dot}spot { return SPOT; }
+{dot}texcoord { return TEXCOORD; }
+{dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); }
+{dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); }
+{dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
+{dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
+{dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
+{dot}texture { return TEXTURE; }
+{dot}transpose { return TRANSPOSE; }
+{dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
+{dot}weight { return_token_or_DOT(require_ARB_vp, WEIGHT); }
+
+texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
+1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
+2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
+3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
+CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
+RECT { return_token_or_IDENTIFIER(require_ARB_fp, TEX_RECT); }
+
+[_a-zA-Z$][_a-zA-Z0-9$]* {
+ yylval->string = strdup(yytext);
+ return IDENTIFIER;
+}
+
+".." { return DOT_DOT; }
+
+{num} {
+ yylval->integer = strtol(yytext, NULL, 10);
+ return INTEGER;
+}
+{num}?{frac}{exp}? {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}"."/[^.] {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}{exp} {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}"."{exp} {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+
+".xyzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return MASK4;
+}
+
+".xy"[zw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return MASK3;
+}
+".xzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return MASK3;
+}
+".yzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return MASK3;
+}
+
+".x"[yzw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+".y"[zw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+".zw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return MASK2;
+}
+
+"."[xyzw] {
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return MASK1;
+}
+
+"."[xyzw]{4} {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return SWIZZLE;
+}
+
+".rgba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return_token_or_DOT(require_ARB_fp, MASK4);
+}
+
+".rg"[ba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+".rba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+".gba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+
+".r"[gba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+".g"[ba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+".ba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+
+"."[gba] {
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return_token_or_DOT(require_ARB_fp, MASK1);
+}
+
+
+".r" {
+ if (require_ARB_vp) {
+ return TEXGEN_R;
+ } else {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
+ yylval->swiz_mask.mask = WRITEMASK_X;
+ return MASK1;
+ }
+}
+
+"."[rgba]{4} {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return_token_or_DOT(require_ARB_fp, SWIZZLE);
+}
+
+"." { return DOT; }
+
+\n {
+ yylloc->first_line++;
+ yylloc->first_column = 1;
+ yylloc->last_line++;
+ yylloc->last_column = 1;
+ yylloc->position++;
+}
+[ \t]+ /* eat whitespace */ ;
+#.*$ /* eat comments */ ;
+. { return yytext[0]; }
+%%
+
+void
+_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
+ const char *string, size_t len)
+{
+ yylex_init_extra(state, scanner);
+ yy_scan_bytes(string, len, *scanner);
+}
+
+void
+_mesa_program_lexer_dtor(void *scanner)
+{
+ /* FINISHME: It's not clear to me whether or not the buffer state returned
+ * FINISHME: by yy_scan_bytes in _mesa_program_lexer_ctor needs to be
+ * FINISHME: explicitly destroyed here or not.
+ */
+ yylex_destroy(scanner);
+}