program_lexer.l revision 3464ebd5
1%{
2/*
3 * Copyright © 2009 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#include "main/glheader.h"
25#include "main/imports.h"
26#include "program/prog_instruction.h"
27#include "program/prog_statevars.h"
28#include "program/symbol_table.h"
29#include "program/program_parser.h"
30#include "program/program_parse.tab.h"
31
32#define require_ARB_vp (yyextra->mode == ARB_vertex)
33#define require_ARB_fp (yyextra->mode == ARB_fragment)
34#define require_NV_fp  (yyextra->option.NV_fragment)
35#define require_shadow (yyextra->option.Shadow)
36#define require_rect   (yyextra->option.TexRect)
37#define require_texarray        (yyextra->option.TexArray)
38
39#ifndef HAVE_UNISTD_H
40#define YY_NO_UNISTD_H
41#endif
42
43#define return_token_or_IDENTIFIER(condition, token)	\
44   do {							\
45      if (condition) {					\
46	 return token;					\
47      } else {						\
48	 return handle_ident(yyextra, yytext, yylval);	\
49      }							\
50   } while (0)
51
52#define return_token_or_DOT(condition, token)		\
53   do {							\
54      if (condition) {					\
55	 return token;					\
56      } else {						\
57	 yyless(1);					\
58	 return DOT;					\
59      }							\
60   } while (0)
61
62
63#define return_opcode(condition, token, opcode, len)	\
64   do {							\
65      if (condition &&					\
66	  _mesa_parse_instruction_suffix(yyextra,	\
67					 yytext + len,	\
68					 & yylval->temp_inst)) {	\
69	 yylval->temp_inst.Opcode = OPCODE_ ## opcode;	\
70	 return token;					\
71      } else {						\
72	 return handle_ident(yyextra, yytext, yylval);	\
73      }							\
74   } while (0)
75
76#define SWIZZLE_INVAL  MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
77				     SWIZZLE_NIL, SWIZZLE_NIL)
78
79static unsigned
80mask_from_char(char c)
81{
82   switch (c) {
83   case 'x':
84   case 'r':
85      return WRITEMASK_X;
86   case 'y':
87   case 'g':
88      return WRITEMASK_Y;
89   case 'z':
90   case 'b':
91      return WRITEMASK_Z;
92   case 'w':
93   case 'a':
94      return WRITEMASK_W;
95   }
96
97   return 0;
98}
99
100static unsigned
101swiz_from_char(char c)
102{
103   switch (c) {
104   case 'x':
105   case 'r':
106      return SWIZZLE_X;
107   case 'y':
108   case 'g':
109      return SWIZZLE_Y;
110   case 'z':
111   case 'b':
112      return SWIZZLE_Z;
113   case 'w':
114   case 'a':
115      return SWIZZLE_W;
116   }
117
118   return 0;
119}
120
121static int
122handle_ident(struct asm_parser_state *state, const char *text, YYSTYPE *lval)
123{
124   lval->string = strdup(text);
125
126   return (_mesa_symbol_table_find_symbol(state->st, 0, text) == NULL)
127      ? IDENTIFIER : USED_IDENTIFIER;
128}
129
130#define YY_USER_ACTION							\
131   do {									\
132      yylloc->first_column = yylloc->last_column;			\
133      yylloc->last_column += yyleng;					\
134      if ((yylloc->first_line == 1)					\
135	  && (yylloc->first_column == 1)) {				\
136	 yylloc->position = 1;						\
137      } else {								\
138	 yylloc->position += yylloc->last_column - yylloc->first_column; \
139      }									\
140   } while(0);
141
142#define YY_NO_INPUT
143
144/* Yes, this is intentionally doing nothing. We have this line of code
145here only to avoid the compiler complaining about an unput function
146that is defined, but never called. */
147#define YY_USER_INIT while (0) { unput(0); }
148
149#define YY_EXTRA_TYPE struct asm_parser_state *
150
151/* Flex defines a couple of functions with no declarations nor the
152static keyword. Declare them here to avoid a compiler warning. */
153int yyget_column  (yyscan_t yyscanner);
154void yyset_column (int  column_no , yyscan_t yyscanner);
155
156%}
157
158num    [0-9]+
159exp    [Ee][-+]?[0-9]+
160frac   "."[0-9]+
161dot    "."[ \t]*
162
163sz     [HRX]?
164szf    [HR]?
165cc     C?
166sat    (_SAT)?
167
168%option bison-bridge bison-locations reentrant noyywrap
169%%
170
171"!!ARBvp1.0"              { return ARBvp_10; }
172"!!ARBfp1.0"              { return ARBfp_10; }
173ADDRESS                   {
174   yylval->integer = at_address;
175   return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
176}
177ALIAS                     { return ALIAS; }
178ATTRIB                    { return ATTRIB; }
179END                       { return END; }
180OPTION                    { return OPTION; }
181OUTPUT                    { return OUTPUT; }
182PARAM                     { return PARAM; }
183TEMP                      { yylval->integer = at_temp; return TEMP; }
184
185ABS{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, ABS, 3); }
186ADD{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, ADD, 3); }
187ARL                { return_opcode(require_ARB_vp, ARL, ARL, 3); }
188
189CMP{sat}           { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); }
190COS{szf}{cc}{sat}  { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); }
191
192DDX{szf}{cc}{sat}  { return_opcode(require_NV_fp,  VECTOR_OP, DDX, 3); }
193DDY{szf}{cc}{sat}  { return_opcode(require_NV_fp,  VECTOR_OP, DDY, 3); }
194DP3{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, DP3, 3); }
195DP4{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, DP4, 3); }
196DPH{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, DPH, 3); }
197DST{szf}{cc}{sat}  { return_opcode(             1, BIN_OP, DST, 3); }
198
199EX2{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, EX2, 3); }
200EXP                { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); }
201
202FLR{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, FLR, 3); }
203FRC{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, FRC, 3); }
204
205KIL                { return_opcode(require_ARB_fp, KIL, KIL, 3); }
206
207LIT{szf}{cc}{sat}  { return_opcode(             1, VECTOR_OP, LIT, 3); }
208LG2{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, LG2, 3); }
209LOG                { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); }
210LRP{sz}{cc}{sat}   { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); }
211
212MAD{sz}{cc}{sat}   { return_opcode(             1, TRI_OP, MAD, 3); }
213MAX{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, MAX, 3); }
214MIN{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, MIN, 3); }
215MOV{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, MOV, 3); }
216MUL{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, MUL, 3); }
217
218PK2H               { return_opcode(require_NV_fp,  VECTOR_OP, PK2H, 4); }
219PK2US              { return_opcode(require_NV_fp,  VECTOR_OP, PK2US, 5); }
220PK4B               { return_opcode(require_NV_fp,  VECTOR_OP, PK4B, 4); }
221PK4UB              { return_opcode(require_NV_fp,  VECTOR_OP, PK4UB, 5); }
222POW{szf}{cc}{sat}  { return_opcode(             1, BINSC_OP, POW, 3); }
223
224RCP{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, RCP, 3); }
225RFL{szf}{cc}{sat}  { return_opcode(require_NV_fp,  BIN_OP,    RFL, 3); }
226RSQ{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, RSQ, 3); }
227
228SCS{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); }
229SEQ{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SEQ, 3); }
230SFL{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SFL, 3); }
231SGE{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, SGE, 3); }
232SGT{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SGT, 3); }
233SIN{szf}{cc}{sat}  { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); }
234SLE{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SLE, 3); }
235SLT{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, SLT, 3); }
236SNE{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SNE, 3); }
237STR{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, STR, 3); }
238SUB{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, SUB, 3); }
239SWZ{sat}           { return_opcode(             1, SWZ, SWZ, 3); }
240
241TEX{cc}{sat}       { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); }
242TXB{cc}{sat}       { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); }
243TXD{cc}{sat}       { return_opcode(require_NV_fp,  TXD_OP, TXD, 3); }
244TXP{cc}{sat}       { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); }
245
246UP2H{cc}{sat}      { return_opcode(require_NV_fp,  SCALAR_OP, UP2H, 4); }
247UP2US{cc}{sat}     { return_opcode(require_NV_fp,  SCALAR_OP, UP2US, 5); }
248UP4B{cc}{sat}      { return_opcode(require_NV_fp,  SCALAR_OP, UP4B, 4); }
249UP4UB{cc}{sat}     { return_opcode(require_NV_fp,  SCALAR_OP, UP4UB, 5); }
250
251X2D{szf}{cc}{sat}  { return_opcode(require_NV_fp,  TRI_OP, X2D, 3); }
252XPD{sat}           { return_opcode(             1, BIN_OP, XPD, 3); }
253
254vertex                    { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
255fragment                  { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
256program                   { return PROGRAM; }
257state                     { return STATE; }
258result                    { return RESULT; }
259
260{dot}ambient              { return AMBIENT; }
261{dot}attenuation          { return ATTENUATION; }
262{dot}back                 { return BACK; }
263{dot}clip                 { return_token_or_DOT(require_ARB_vp, CLIP); }
264{dot}color                { return COLOR; }
265{dot}depth                { return_token_or_DOT(require_ARB_fp, DEPTH); }
266{dot}diffuse              { return DIFFUSE; }
267{dot}direction            { return DIRECTION; }
268{dot}emission             { return EMISSION; }
269{dot}env                  { return ENV; }
270{dot}eye                  { return EYE; }
271{dot}fogcoord             { return FOGCOORD; }
272{dot}fog                  { return FOG; }
273{dot}front                { return FRONT; }
274{dot}half                 { return HALF; }
275{dot}inverse              { return INVERSE; }
276{dot}invtrans             { return INVTRANS; }
277{dot}light                { return LIGHT; }
278{dot}lightmodel           { return LIGHTMODEL; }
279{dot}lightprod            { return LIGHTPROD; }
280{dot}local                { return LOCAL; }
281{dot}material             { return MATERIAL; }
282{dot}program              { return MAT_PROGRAM; }
283{dot}matrix               { return MATRIX; }
284{dot}matrixindex          { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
285{dot}modelview            { return MODELVIEW; }
286{dot}mvp                  { return MVP; }
287{dot}normal               { return_token_or_DOT(require_ARB_vp, NORMAL); }
288{dot}object               { return OBJECT; }
289{dot}palette              { return PALETTE; }
290{dot}params               { return PARAMS; }
291{dot}plane                { return PLANE; }
292{dot}point                { return_token_or_DOT(require_ARB_vp, POINT_TOK); }
293{dot}pointsize            { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
294{dot}position             { return POSITION; }
295{dot}primary              { return PRIMARY; }
296{dot}projection           { return PROJECTION; }
297{dot}range                { return_token_or_DOT(require_ARB_fp, RANGE); }
298{dot}row                  { return ROW; }
299{dot}scenecolor           { return SCENECOLOR; }
300{dot}secondary            { return SECONDARY; }
301{dot}shininess            { return SHININESS; }
302{dot}size                 { return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
303{dot}specular             { return SPECULAR; }
304{dot}spot                 { return SPOT; }
305{dot}texcoord             { return TEXCOORD; }
306{dot}texenv               { return_token_or_DOT(require_ARB_fp, TEXENV); }
307{dot}texgen               { return_token_or_DOT(require_ARB_vp, TEXGEN); }
308{dot}q                    { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
309{dot}s                    { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
310{dot}t                    { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
311{dot}texture              { return TEXTURE; }
312{dot}transpose            { return TRANSPOSE; }
313{dot}attrib               { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
314{dot}weight               { return_token_or_DOT(require_ARB_vp, WEIGHT); }
315
316texture                   { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
3171D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
3182D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
3193D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
320CUBE                      { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
321RECT                      { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
322SHADOW1D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
323SHADOW2D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
324SHADOWRECT                { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
325ARRAY1D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
326ARRAY2D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
327ARRAYSHADOW1D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
328ARRAYSHADOW2D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
329
330[_a-zA-Z$][_a-zA-Z0-9$]*  { return handle_ident(yyextra, yytext, yylval); }
331
332".."                      { return DOT_DOT; }
333
334{num}                     {
335   yylval->integer = strtol(yytext, NULL, 10);
336   return INTEGER;
337}
338{num}?{frac}{exp}?        {
339   yylval->real = _mesa_strtof(yytext, NULL);
340   return REAL;
341}
342{num}"."/[^.]             {
343   yylval->real = _mesa_strtof(yytext, NULL);
344   return REAL;
345}
346{num}{exp}                {
347   yylval->real = _mesa_strtof(yytext, NULL);
348   return REAL;
349}
350{num}"."{exp}             {
351   yylval->real = _mesa_strtof(yytext, NULL);
352   return REAL;
353}
354
355".xyzw"                   {
356   yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
357   yylval->swiz_mask.mask = WRITEMASK_XYZW;
358   return MASK4;
359}
360
361".xy"[zw]                 {
362   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
363   yylval->swiz_mask.mask = WRITEMASK_XY
364      | mask_from_char(yytext[3]);
365   return MASK3;
366}
367".xzw"                    {
368   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
369   yylval->swiz_mask.mask = WRITEMASK_XZW;
370   return MASK3;
371}
372".yzw"                    {
373   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
374   yylval->swiz_mask.mask = WRITEMASK_YZW;
375   return MASK3;
376}
377
378".x"[yzw]                 {
379   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
380   yylval->swiz_mask.mask = WRITEMASK_X
381      | mask_from_char(yytext[2]);
382   return MASK2;
383}
384".y"[zw]                  {
385   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
386   yylval->swiz_mask.mask = WRITEMASK_Y
387      | mask_from_char(yytext[2]);
388   return MASK2;
389}
390".zw"                     {
391   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
392   yylval->swiz_mask.mask = WRITEMASK_ZW;
393   return MASK2;
394}
395
396"."[xyzw]                 {
397   const unsigned s = swiz_from_char(yytext[1]);
398   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
399   yylval->swiz_mask.mask = mask_from_char(yytext[1]);
400   return MASK1;
401}
402
403"."[xyzw]{4}              {
404   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
405					    swiz_from_char(yytext[2]),
406					    swiz_from_char(yytext[3]),
407					    swiz_from_char(yytext[4]));
408   yylval->swiz_mask.mask = 0;
409   return SWIZZLE;
410}
411
412".rgba"                   {
413   yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
414   yylval->swiz_mask.mask = WRITEMASK_XYZW;
415   return_token_or_DOT(require_ARB_fp, MASK4);
416}
417
418".rg"[ba]                 {
419   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
420   yylval->swiz_mask.mask = WRITEMASK_XY
421      | mask_from_char(yytext[3]);
422   return_token_or_DOT(require_ARB_fp, MASK3);
423}
424".rba"                    {
425   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
426   yylval->swiz_mask.mask = WRITEMASK_XZW;
427   return_token_or_DOT(require_ARB_fp, MASK3);
428}
429".gba"                    {
430   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
431   yylval->swiz_mask.mask = WRITEMASK_YZW;
432   return_token_or_DOT(require_ARB_fp, MASK3);
433}
434
435".r"[gba]                 {
436   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
437   yylval->swiz_mask.mask = WRITEMASK_X
438      | mask_from_char(yytext[2]);
439   return_token_or_DOT(require_ARB_fp, MASK2);
440}
441".g"[ba]                  {
442   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
443   yylval->swiz_mask.mask = WRITEMASK_Y
444      | mask_from_char(yytext[2]);
445   return_token_or_DOT(require_ARB_fp, MASK2);
446}
447".ba"                     {
448   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
449   yylval->swiz_mask.mask = WRITEMASK_ZW;
450   return_token_or_DOT(require_ARB_fp, MASK2);
451}
452
453"."[gba]                  {
454   const unsigned s = swiz_from_char(yytext[1]);
455   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
456   yylval->swiz_mask.mask = mask_from_char(yytext[1]);
457   return_token_or_DOT(require_ARB_fp, MASK1);
458}
459
460
461".r"                      {
462   if (require_ARB_vp) {
463      return TEXGEN_R;
464   } else {
465      yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
466						SWIZZLE_X, SWIZZLE_X);
467      yylval->swiz_mask.mask = WRITEMASK_X;
468      return MASK1;
469   }
470}
471
472"."[rgba]{4}              {
473   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
474					    swiz_from_char(yytext[2]),
475					    swiz_from_char(yytext[3]),
476					    swiz_from_char(yytext[4]));
477   yylval->swiz_mask.mask = 0;
478   return_token_or_DOT(require_ARB_fp, SWIZZLE);
479}
480
481"."                       { return DOT; }
482
483\n                        {
484   yylloc->first_line++;
485   yylloc->first_column = 1;
486   yylloc->last_line++;
487   yylloc->last_column = 1;
488   yylloc->position++;
489}
490[ \t\r]+                  /* eat whitespace */ ;
491#.*$                      /* eat comments */ ;
492.                         { return yytext[0]; }
493%%
494
495void
496_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
497			 const char *string, size_t len)
498{
499   yylex_init_extra(state, scanner);
500   yy_scan_bytes(string, len, *scanner);
501}
502
503void
504_mesa_program_lexer_dtor(void *scanner)
505{
506   yylex_destroy(scanner);
507}
508