From 9a0d97a21c94f8e1ae673b8b96737956a27ae201 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 18 Jul 2003 16:43:45 +0000 Subject: [PATCH] Karl Rasche's ARB_vertex_program parser --- src/mesa/main/arbvertparse.c | 6629 ++++++++++++++++++++++++++++++++++ src/mesa/main/arbvertparse.h | 36 + 2 files changed, 6665 insertions(+) create mode 100644 src/mesa/main/arbvertparse.c create mode 100644 src/mesa/main/arbvertparse.h diff --git a/src/mesa/main/arbvertparse.c b/src/mesa/main/arbvertparse.c new file mode 100644 index 00000000000..d21358bd6d6 --- /dev/null +++ b/src/mesa/main/arbvertparse.c @@ -0,0 +1,6629 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * 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 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 + * BRIAN PAUL 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 "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "nvprogram.h" +#include "nvvertparse.h" +#include "nvvertprog.h" + +#include "arbvertparse.h" + +/** + * Overview: + * + * This is a simple top-down predictive parser. In a nutshell, there are two key + * elements to a predictive parser. First, is the 'look ahead' symbol. This is simply + * the next token in the input stream. The other component is a stack of symbols. + * + * Given the grammar, we can derive a look ahead table. This is just a 2D array, + * where one axis is the non-terminal on top of the stack and the other axis is + * the look ahead. Each entry in the array is the production to apply when the pair + * of stack symbol & look ahead is encountered. If no production is listed at + * a given entry in the table, a parse error occurs if this combination + * is seen. + * + * Since we want to drive the parsing from a couple of huge tables, we have to + * save some information later on for processing (e.g. for code generation). + * For this, we explicitly recreate the parse tree representing the derivation. + * We can then make several passes over the parse tree to perform all additional + * processing, and we can be sure the the parse is valid. + * + * The stack is initialized by pushing the start symbol onto it. The look ahead + * symbol is initially the first token in the program string. + * + * If there is a non-terminal symbol on top of the stack, the look ahead table + * is consulted to find if a production exists for the top of the stack + * and the look ahead. + * + * When we find a matching production, we pop the non-terminal off the top of + * the stack (the LHS of the production), and push the tokens on the RHS of + * the production onto the stack. Note that we store a pointer to the parse_tree_node + * containing the LHS token on the stack. This way, we can setup the children in + * the parse tree as we apply the production. + * + * If there is a terminal symbol on top of the stack, we compare it with the + * look ahead symbol. If they match, or we don't care about the value of the + * terminal (e.g. we know its an integer, but don't necessairly care what + * integer), the terminal symbol is popped off the stack and the look ahead + * is advanced. + * + * There are a few special nasty cases of productions for which we make special + * cases. These aren't found in the production/look-ahead tables, but listed + * out explicitly. + * + * After the parse tree has been constructed, we make several recusive passes + * over it to perform various tasks. + * + * The first pass is made to clean up the state bindings. This is done in + * parse_tree_fold_bindings(). The goal is to reduce the big mess of a parse tree + * created by strings such as: + * + * result.color.secondary + * + * and roll them up into one token and fill out some information in a symbol table. + * In this case, the token at the root of the derivation becomes BINDING_TOKEN, + * and the token attribute is an index into the binding table where this state + * is held. + * + * The next two passes go about associating variables with BINDING_TOKENs. This + * takes care of the cases like: + * + * OUTPUT foo = result.color.secondary; + * + * by inserting the index in the binding table for result.color.secondary into + * the attr field in the identifier table where the 'foo' variable sits. + * The second such pass deals with setting up arrays of program parameters, + * while the first only deals with scalars. + * + * We then examine all the information on variables and state that we have + * gathered, and layout which 'register' each variable or bit-of-state should use. + * + * + * Finally, we make a recursive pass of the parse tree and generate opcodes + * for Mesa to interpret while executing the program. + * + * It should be noted that each input/stack token has two parts, an 'identifier' + * and an 'attribute'. The identifier tells what class the token is, e.g. INTEGER_TOKEN, + * or NT_PROGRAM_SINGLE_ITEM_TOKEN. For some tokens, e.g. INTEGER_TOKEN, ID_TOKEN, + * FLOAT_TOKEN, or BINDING_TOKEN, the attribute for the token is an index into a table + * giving various properties about the token. + * + */ + +/** + * Here are all of the structs used to hold parse state and symbol + * tables used. + * + * All strings which are not reserved words, floats, ints, or misc + * puncuation (ie .) are considered to be [potential] identifiers. + * When we encounter such a string while lex'ing, insert it into + * the id symbol table, shown below. + * + * Sometime later, we'll initialize the variable types for identifiers + * which really are variables. This gets shoved into the 'type' field. + * + * For variables, we'll need additional info (e.g. state it is bound to, + * variable we're aliased to, etc). This is stored in the 'attr' field. + * - For alias variables, the attr is the idx in the id table of + * the variable we are bound to. + * - For other variables, we need a whole mess of info. This can be + * found in the binding symbol table, below. In this case, the + * attr field is the idx into the binding table that describes us. + * - For uninitialized ids, attr is -1. + * + * The data field holds the string of the id. + * + * len is the number of identifiers in the table. + */ +typedef struct st_id_table +{ + GLint len; + GLint *type; + GLint *attr; + GLubyte **data; +} +id_table; + +/** + * For PARAM arrays, we need to record the contents for use when + * laying out registers and loading state. + * + * len is the number of arrays in the table. + * + * num_elements[i] is the number of items in array i. In other words, this + * is the number of registers it would require when allocating. + * + * data[i][n] is the state bound to element n in array i. It is an idx into + * the binding table + */ +typedef struct st_array_table +{ + GLint len; + GLint *num_elements; + GLint **data; +} +array_table; + +/** + * For holding all of the data used to describe an identifier, we have the catch + * all binding symbol table. + * + * len is the number of bound items; + * + * type[i] tells what we are binding too, e.g. ATTRIB_POSITION, FOG_COLOR, or CONSTANT + * + * offset[i] gives the matrix number for matrix bindings, e.g. MATRIXROWS_MODELVIEW. + * Alternativly, it gives the number of the first parameter for PROGRAM_ENV_* and + * PROGRAM_LOCAL_*. + * + * num_rows[i] gives the number of rows for multiple matrix rows, or the number + * of parameters in a env/local array. + * + * consts gives the 4-GLfloat constant value for bindings of type CONSTANT + * + * reg_num gives the register number which this binding is held in. + */ +typedef struct st_binding_table +{ + GLint len; + GLint *type; + GLint *offset; + GLint *row; + GLint *num_rows; + GLfloat **consts; + GLint *reg_num; +} +binding_table; + +/** + * Integers and floats are stored here. + */ +typedef struct st_int_table +{ + GLint len; + GLint *data; +} +int_table; + +typedef struct st_float_table +{ + GLint len; + GLdouble *data; +} +float_table; + +/** + * To avoid writing tons of mindless parser code, the parsing is driven by + * a few big tables of rules, plus a few special cases. However, this means + * that we have to do all of our analysis outside of the parsing step. + * + * So, the parser will contruct a parse tree describing the program string + * which we can then operate on to do things like code generation. + * + * This struct represents a node in the parse tree. + * + * If tok is a non-terminal token, tok_attr is not relevant. + * If tok is BINDING_TOKEN, tok_attr is the index into the binding table. + * if tok is INTEGER_TOKEN or FLOAT_TOKEN, tok_attr is the index in the integer/GLfloat table + * + * prod_applied is the production number applied to this token in the derivation of + * the program string. See arbvp_grammar.txt for a listing of the productions, and + * their numbers. + */ +typedef struct st_parse_tree_node +{ + GLint tok, tok_attr, is_terminal; + GLint prod_applied; + struct st_parse_tree_node *children[4]; +} +parse_tree_node; + +/** This stores tokens that we lex out + */ +typedef struct st_token_list +{ + GLint tok, tok_attr; + parse_tree_node *pt; + + struct st_token_list *next; +} +token_list; + +/** + * This holds all of the productions in the grammar. + * + * lhs is a non-terminal token, e.g. NT_PROGRAM_TOKEN. + * rhs is either NULL_TOKEN, another non-terminal token, or a terminal token. + * In some cases, we need the RHS to be a certain value, e.g. for the dst reg write masks. + * For this, key is used to specify the string. If we don't care about the key, just + * specify "". + * Int/floats are slightly different, "-1" specifies 'we don't care'. + * + * lhs is not very useful here, but is is convient for sanity sake when specifing productions. + */ +typedef struct st_prod_table +{ + GLint lhs; + GLint rhs[4]; + GLubyte *key[4]; +} +prod_table; + +/** + * This holds the look ahead table to drive the parser. We examine the token on + * the top of the stack, as well as the next token in the input stream (the look ahead). + * We then match this against the table, and apply the approprate production. If nothing + * matches, we have a parse error. + * + * Here, LHS is the (non-terminal) token to match against the top of the stack. + * + * la is the token to match against the look ahead. + * + * If la is ID_TOKEN, we have to match a given keyword (e.g. 'ambient'). This is specified in + * la_kw. + * + * prod_idx is the idx into the prod_table of the production that we are to apply if this + * rule matches. + */ +typedef struct st_look_ahead_table +{ + GLint lhs; + GLint la; + GLubyte *la_kw; + GLint prod_idx; +} +look_ahead_table; + +/** + * This is the general catch-all for the parse state + */ +typedef struct st_parse_state +{ + GLubyte *str; + GLint len; + + /* lex stuff ------ */ + GLint start_pos, curr_pos; + GLint curr_state; + /* ---------------- */ + + id_table idents; + int_table ints; + float_table floats; + binding_table binds; + array_table arrays; + + token_list *stack_head, *stack_free_list; + + parse_tree_node *pt_head; +} +parse_state; + +/* local prototypes */ +static GLint float_table_add(float_table * tab, GLubyte * str, GLint start, + GLint end); +static GLint int_table_add(int_table * tab, GLubyte * str, GLint start, + GLint end); +static GLint id_table_add(id_table * tab, GLubyte * str, GLint start, + GLint end); +static void parse_tree_free_children(parse_tree_node * ptn); + +/** + * Here we have a ton of defined terms that we use to identify productions, + * terminals, and nonterminals. + */ + +/** + * Terminal tokens + */ +#define EOF_TOKEN 0 +#define ID_TOKEN 1 +#define ABS_TOKEN 2 +#define ADD_TOKEN 3 +#define ADDRESS_TOKEN 4 +#define ALIAS_TOKEN 5 +#define ARL_TOKEN 6 +#define ATTRIB_TOKEN 7 + +#define DP3_TOKEN 8 +#define DP4_TOKEN 9 +#define DPH_TOKEN 10 +#define DST_TOKEN 11 + +#define END_TOKEN 12 +#define EX2_TOKEN 13 +#define EXP_TOKEN 14 + +#define FLR_TOKEN 15 +#define FRC_TOKEN 16 + +#define LG2_TOKEN 17 +#define LIT_TOKEN 18 +#define LOG_TOKEN 19 + +#define MAD_TOKEN 20 +#define MAX_TOKEN 21 +#define MIN_TOKEN 22 +#define MOV_TOKEN 23 +#define MUL_TOKEN 24 + +#define OPTION_TOKEN 25 +#define OUTPUT_TOKEN 26 + +#define PARAM_TOKEN 27 +#define POW_TOKEN 28 + +#define RCP_TOKEN 29 +#define RSQ_TOKEN 30 + +#define SGE_TOKEN 31 +#define SLT_TOKEN 32 +#define SUB_TOKEN 33 +#define SWZ_TOKEN 34 + +#define TEMP_TOKEN 35 + +#define XPD_TOKEN 36 + +#define SEMICOLON_TOKEN 37 +#define COMMA_TOKEN 38 +#define PLUS_TOKEN 39 +#define MINUS_TOKEN 40 +#define PERIOD_TOKEN 41 +#define DOTDOT_TOKEN 42 +#define LBRACKET_TOKEN 43 +#define RBRACKET_TOKEN 44 +#define LBRACE_TOKEN 45 +#define RBRACE_TOKEN 46 +#define EQUAL_TOKEN 47 + +#define INTEGER_TOKEN 48 +#define FLOAT_TOKEN 49 + +#define PROGRAM_TOKEN 50 +#define RESULT_TOKEN 51 +#define STATE_TOKEN 52 +#define VERTEX_TOKEN 53 + +#define NULL_TOKEN 54 + +#define BINDING_TOKEN 55 + +/** + * Non-terminal tokens + */ +#define NT_PROGRAM_TOKEN 100 +#define NT_OPTION_SEQUENCE_TOKEN 101 +#define NT_OPTION_SEQUENCE2_TOKEN 102 +#define NT_OPTION_TOKEN 103 +#define NT_STATEMENT_SEQUENCE_TOKEN 104 +#define NT_STATEMENT_SEQUENCE2_TOKEN 105 +#define NT_STATEMENT_TOKEN 106 + +#define NT_INSTRUCTION_TOKEN 107 +#define NT_ARL_INSTRUCTION_TOKEN 108 +#define NT_VECTOROP_INSTRUCTION_TOKEN 109 +#define NT_VECTOROP_TOKEN 110 +#define NT_SCALAROP_INSTRUCTION_TOKEN 111 +#define NT_SCALAROP_TOKEN 112 +#define NT_BINSCOP_INSTRUCTION_TOKEN 113 +#define NT_BINSCOP_INSTRUCTION2_TOKEN 114 +#define NT_BINSCOP_TOKEN 115 +#define NT_BINOP_INSTRUCTION_TOKEN 116 +#define NT_BINOP_INSTRUCTION2_TOKEN 117 +#define NT_BINOP_TOKEN 118 +#define NT_TRIOP_INSTRUCTION_TOKEN 119 +#define NT_TRIOP_INSTRUCTION2_TOKEN 120 +#define NT_TRIOP_INSTRUCTION3_TOKEN 121 +#define NT_TRIOP_TOKEN 122 +#define NT_SWZ_INSTRUCTION_TOKEN 123 +#define NT_SWZ_INSTRUCTION2_TOKEN 124 + +#define NT_SCALAR_SRC_REG_TOKEN 130 +#define NT_SWIZZLE_SRC_REG_TOKEN 131 +#define NT_MASKED_DST_REG_TOKEN 132 +#define NT_MASKED_ADDR_REG_TOKEN 133 +#define NT_EXTENDED_SWIZZLE_TOKEN 134 +#define NT_EXTENDED_SWIZZLE2_TOKEN 135 +#define NT_EXT_SWIZ_COMP_TOKEN 136 +#define NT_EXT_SWIZ_SEL_TOKEN 137 +#define NT_SRC_REG_TOKEN 138 +#define NT_DST_REG_TOKEN 139 +#define NT_VERTEX_ATTRIB_REG_TOKEN 140 + +#define NT_TEMPORARY_REG_TOKEN 150 +#define NT_PROG_PARAM_REG_TOKEN 151 +#define NT_PROG_PARAM_SINGLE_TOKEN 152 +#define NT_PROG_PARAM_ARRAY_TOKEN 153 +#define NT_PROG_PARAM_ARRAY_MEM_TOKEN 154 +#define NT_PROG_PARAM_ARRAY_ABS_TOKEN 155 +#define NT_PROG_PARAM_ARRAY_REL_TOKEN 156 + +#define NT_ADDR_REG_REL_OFFSET_TOKEN 157 +#define NT_ADDR_REG_POS_OFFSET_TOKEN 158 +#define NT_ADDR_REG_NEG_OFFSET_TOKEN 159 + +#define NT_VERTEX_RESULT_REG_TOKEN 160 +#define NT_ADDR_REG_TOKEN 161 +#define NT_ADDR_COMPONENT_TOKEN 162 +#define NT_ADDR_WRITE_MASK_TOKEN 163 +#define NT_SCALAR_SUFFIX_TOKEN 164 +#define NT_SWIZZLE_SUFFIX_TOKEN 165 + +#define NT_COMPONENT_TOKEN 166 +#define NT_OPTIONAL_MASK_TOKEN 167 +#define NT_OPTIONAL_MASK2_TOKEN 168 +#define NT_NAMING_STATEMENT_TOKEN 169 + +#define NT_ATTRIB_STATEMENT_TOKEN 170 +#define NT_VTX_ATTRIB_BINDING_TOKEN 171 +#define NT_VTX_ATTRIB_ITEM_TOKEN 172 +#define NT_VTX_ATTRIB_NUM_TOKEN 173 +#define NT_VTX_OPT_WEIGHT_NUM_TOKEN 174 +#define NT_VTX_WEIGHT_NUM_TOKEN 175 +#define NT_PARAM_STATEMENT_TOKEN 176 +#define NT_PARAM_STATEMENT2_TOKEN 177 +#define NT_OPT_ARRAY_SIZE_TOKEN 178 +#define NT_PARAM_SINGLE_INIT_TOKEN 179 +#define NT_PARAM_MULTIPLE_INIT_TOKEN 180 +#define NT_PARAM_MULT_INIT_LIST_TOKEN 181 +#define NT_PARAM_MULT_INIT_LIST2_TOKEN 182 +#define NT_PARAM_SINGLE_ITEM_DECL_TOKEN 183 +#define NT_PARAM_SINGLE_ITEM_USE_TOKEN 184 +#define NT_PARAM_MULTIPLE_ITEM_TOKEN 185 +#define NT_STATE_MULTIPLE_ITEM_TOKEN 186 +#define NT_STATE_MULTIPLE_ITEM2_TOKEN 187 +#define NT_FOO_TOKEN 188 +#define NT_FOO2_TOKEN 189 +#define NT_FOO3_TOKEN 190 +#define NT_FOO35_TOKEN 191 +#define NT_FOO4_TOKEN 192 +#define NT_STATE_SINGLE_ITEM_TOKEN 193 +#define NT_STATE_SINGLE_ITEM2_TOKEN 194 +#define NT_STATE_MATERIAL_ITEM_TOKEN 195 +#define NT_STATE_MATERIAL_ITEM2_TOKEN 196 +#define NT_STATE_MAT_PROPERTY_TOKEN 197 +#define NT_STATE_LIGHT_ITEM_TOKEN 198 +#define NT_STATE_LIGHT_ITEM2_TOKEN 199 +#define NT_STATE_LIGHT_PROPERTY_TOKEN 200 +#define NT_STATE_SPOT_PROPERTY_TOKEN 201 +#define NT_STATE_LIGHT_MODEL_ITEM_TOKEN 202 +#define NT_STATE_LMOD_PROPERTY_TOKEN 203 +#define NT_STATE_LMOD_PROPERTY2_TOKEN 204 + +#define NT_STATE_LIGHT_PROD_ITEM_TOKEN 207 +#define NT_STATE_LIGHT_PROD_ITEM15_TOKEN 208 +#define NT_STATE_LIGHT_PROD_ITEM2_TOKEN 209 +#define NT_STATE_LPROD_PROPERTY_TOKEN 210 +#define NT_STATE_LIGHT_NUMBER_TOKEN 211 +#define NT_STATE_TEX_GEN_ITEM_TOKEN 212 +#define NT_STATE_TEX_GEN_ITEM2_TOKEN 213 +#define NT_STATE_TEX_GEN_TYPE_TOKEN 214 +#define NT_STATE_TEX_GEN_COORD_TOKEN 215 +#define NT_STATE_FOG_ITEM_TOKEN 216 +#define NT_STATE_FOG_PROPERTY_TOKEN 217 + +#define NT_STATE_CLIP_PLANE_ITEM_TOKEN 218 +#define NT_STATE_CLIP_PLANE_ITEM2_TOKEN 219 +#define NT_STATE_CLIP_PLANE_NUM_TOKEN 220 +#define NT_STATE_POINT_ITEM_TOKEN 221 +#define NT_STATE_POINT_PROPERTY_TOKEN 222 +#define NT_STATE_MATRIX_ROW_TOKEN 223 +#define NT_STATE_MATRIX_ROW15_TOKEN 224 +#define NT_STATE_MATRIX_ROW2_TOKEN 225 +#define NT_STATE_MATRIX_ROW3_TOKEN 226 +#define NT_STATE_MAT_MODIFIER_TOKEN 227 +#define NT_STATE_MATRIX_ROW_NUM_TOKEN 228 +#define NT_STATE_MATRIX_NAME_TOKEN 229 +#define NT_STATE_OPT_MOD_MAT_NUM_TOKEN 230 +#define NT_STATE_MOD_MAT_NUM_TOKEN 231 +#define NT_STATE_PALETTE_MAT_NUM_TOKEN 232 +#define NT_STATE_PROGRAM_MAT_NUM_TOKEN 233 + +#define NT_PROGRAM_SINGLE_ITEM_TOKEN 234 +#define NT_PROGRAM_SINGLE_ITEM2_TOKEN 235 +#define NT_PROGRAM_MULTIPLE_ITEM_TOKEN 236 +#define NT_PROGRAM_MULTIPLE_ITEM2_TOKEN 237 +#define NT_PROG_ENV_PARAMS_TOKEN 238 +#define NT_PROG_ENV_PARAM_NUMS_TOKEN 239 +#define NT_PROG_ENV_PARAM_NUMS2_TOKEN 240 +#define NT_PROG_ENV_PARAM_TOKEN 250 +#define NT_PROG_LOCAL_PARAMS_TOKEN 251 +#define NT_PROG_LOCAL_PARAM_NUMS_TOKEN 252 +#define NT_PROG_LOCAL_PARAM_NUMS2_TOKEN 253 +#define NT_PROG_LOCAL_PARAM_TOKEN 254 +#define NT_PROG_ENV_PARAM_NUM_TOKEN 255 +#define NT_PROG_LOCAL_PARAM_NUM_TOKEN 256 + +#define NT_PARAM_CONST_DECL_TOKEN 257 +#define NT_PARAM_CONST_USE_TOKEN 258 +#define NT_PARAM_CONST_SCALAR_DECL_TOKEN 259 +#define NT_PARAM_CONST_SCALAR_USE_TOKEN 260 +#define NT_PARAM_CONST_VECTOR_TOKEN 261 +#define NT_PARAM_CONST_VECTOR2_TOKEN 262 +#define NT_PARAM_CONST_VECTOR3_TOKEN 263 +#define NT_PARAM_CONST_VECTOR4_TOKEN 264 + +#define NT_SIGNED_FLOAT_CONSTANT_TOKEN 265 +#define NT_FLOAT_CONSTANT_TOKEN 266 +#define NT_OPTIONAL_SIGN_TOKEN 267 + +#define NT_TEMP_STATEMENT_TOKEN 268 +#define NT_ADDRESS_STATEMENT_TOKEN 269 +#define NT_VAR_NAME_LIST_TOKEN 270 +#define NT_OUTPUT_STATEMENT_TOKEN 271 +#define NT_RESULT_BINDING_TOKEN 272 +#define NT_RESULT_BINDING2_TOKEN 273 +#define NT_RESULT_COL_BINDING_TOKEN 274 +#define NT_RESULT_COL_BINDING2_TOKEN 275 +#define NT_RESULT_COL_BINDING3_TOKEN 276 +#define NT_RESULT_COL_BINDING4_TOKEN 277 +#define NT_RESULT_COL_BINDING5_TOKEN 278 + +#define NT_OPT_FACE_TYPE2_TOKEN 279 +#define NT_OPT_COLOR_TYPE_TOKEN 280 +#define NT_OPT_COLOR_TYPE2_TOKEN 281 +#define NT_OPT_TEX_COORD_NUM_TOKEN 282 +#define NT_TEX_COORD_NUM_TOKEN 283 + +#define NT_ALIAS_STATEMENT_TOKEN 284 +#define NT_ESTABLISH_NAME_TOKEN 285 +#define NT_ESTABLISHED_NAME_TOKEN 286 + +#define NT_SWIZZLE_SUFFIX2_TOKEN 287 +#define NT_COMPONENT4_TOKEN 288 + +/** + * FSA States for lex + * + * XXX: These can be turned into enums + */ +#define STATE_BASE 0 +#define STATE_IDENT 1 + +#define STATE_A 2 +#define STATE_AB 3 +#define STATE_ABS 4 +#define STATE_AD 5 +#define STATE_ADD 6 +#define STATE_ADDR 7 +#define STATE_ADDRE 8 +#define STATE_ADDRES 9 +#define STATE_ADDRESS 10 +#define STATE_AL 11 +#define STATE_ALI 12 +#define STATE_ALIA 13 +#define STATE_ALIAS 14 +#define STATE_AR 15 +#define STATE_ARL 16 +#define STATE_AT 17 +#define STATE_ATT 18 +#define STATE_ATTR 19 +#define STATE_ATTRI 20 +#define STATE_ATTRIB 21 + +#define STATE_D 22 +#define STATE_DP 23 +#define STATE_DP3 24 +#define STATE_DP4 25 +#define STATE_DPH 26 +#define STATE_DS 27 +#define STATE_DST 28 + +#define STATE_E 29 +#define STATE_EN 30 +#define STATE_END 31 +#define STATE_EX 32 +#define STATE_EX2 33 +#define STATE_EXP 34 + +#define STATE_F 35 +#define STATE_FL 36 +#define STATE_FLR 37 +#define STATE_FR 38 +#define STATE_FRC 39 + +#define STATE_L 40 +#define STATE_LG 41 +#define STATE_LG2 42 +#define STATE_LI 43 +#define STATE_LIT 44 +#define STATE_LO 45 +#define STATE_LOG 46 + +#define STATE_M 47 +#define STATE_MA 48 +#define STATE_MAD 49 +#define STATE_MAX 50 +#define STATE_MI 51 +#define STATE_MIN 52 +#define STATE_MO 53 +#define STATE_MOV 54 +#define STATE_MU 55 +#define STATE_MUL 56 + +#define STATE_O 57 +#define STATE_OP 58 +#define STATE_OPT 59 +#define STATE_OPTI 60 +#define STATE_OPTIO 61 +#define STATE_OPTION 62 +#define STATE_OU 63 +#define STATE_OUT 64 +#define STATE_OUTP 65 +#define STATE_OUTPU 66 +#define STATE_OUTPUT 67 + +#define STATE_P 68 +#define STATE_PA 69 +#define STATE_PAR 70 +#define STATE_PARA 71 +#define STATE_PARAM 72 +#define STATE_PO 73 +#define STATE_POW 74 + +#define STATE_R 75 +#define STATE_RC 76 +#define STATE_RCP 77 +#define STATE_RS 78 +#define STATE_RSQ 79 + +#define STATE_S 80 +#define STATE_SG 81 +#define STATE_SGE 82 +#define STATE_SL 83 +#define STATE_SLT 84 +#define STATE_SU 85 +#define STATE_SUB 86 +#define STATE_SW 87 +#define STATE_SWZ 88 + +#define STATE_T 89 +#define STATE_TE 90 +#define STATE_TEM 91 +#define STATE_TEMP 92 + +#define STATE_X 93 +#define STATE_XP 94 +#define STATE_XPD 95 + +#define STATE_N1 96 +#define STATE_N2 97 +#define STATE_N3 98 +#define STATE_N4 99 +#define STATE_N5 100 +#define STATE_N6 101 +#define STATE_N7 102 + +#define STATE_COMMENT 103 + +/* LC == lower case, as in 'program' */ +#define STATE_LC_P 104 +#define STATE_LC_PR 105 +#define STATE_LC_PRO 106 +#define STATE_LC_PROG 107 +#define STATE_LC_PROGR 108 +#define STATE_LC_PROGRA 109 + +#define STATE_LC_R 110 +#define STATE_LC_RE 111 +#define STATE_LC_RES 112 +#define STATE_LC_RESU 113 +#define STATE_LC_RESUL 114 +#define STATE_LC_RESULT 115 + +#define STATE_LC_S 116 +#define STATE_LC_ST 117 +#define STATE_LC_STA 118 +#define STATE_LC_STAT 119 +#define STATE_LC_STATE 120 + +#define STATE_LC_V 121 +#define STATE_LC_VE 122 +#define STATE_LC_VER 123 +#define STATE_LC_VERT 124 +#define STATE_LC_VERTE 125 +#define STATE_LC_VERTEX 126 +#define STATE_LC_PROGRAM 127 + +/** + * Error codes + */ +#define ARB_VP_ERROR -1 +#define ARB_VP_SUCESS 0 + +/** + * Variable types + */ +#define TYPE_NONE 0 +#define TYPE_ATTRIB 1 +#define TYPE_PARAM 2 +#define TYPE_PARAM_SINGLE 3 +#define TYPE_PARAM_ARRAY 4 +#define TYPE_TEMP 5 +#define TYPE_ADDRESS 6 +#define TYPE_OUTPUT 7 +#define TYPE_ALIAS 8 + +/** + * Vertex Attrib Bindings + */ +#define ATTRIB_POSITION 1 +#define ATTRIB_WEIGHT 2 +#define ATTRIB_NORMAL 3 +#define ATTRIB_COLOR_PRIMARY 4 +#define ATTRIB_COLOR_SECONDARY 5 +#define ATTRIB_FOGCOORD 6 +#define ATTRIB_TEXCOORD 7 +#define ATTRIB_MATRIXINDEX 8 +#define ATTRIB_ATTRIB 9 + +/** + * Result Bindings + */ +#define RESULT_POSITION 10 +#define RESULT_FOGCOORD 11 +#define RESULT_POINTSIZE 12 +#define RESULT_COLOR_FRONT_PRIMARY 13 +#define RESULT_COLOR_FRONT_SECONDARY 14 +#define RESULT_COLOR_BACK_PRIMARY 15 +#define RESULT_COLOR_BACK_SECONDARY 16 +#define RESULT_TEXCOORD 17 + +/** + * Material Property Bindings + */ +#define MATERIAL_FRONT_AMBIENT 18 +#define MATERIAL_FRONT_DIFFUSE 19 +#define MATERIAL_FRONT_SPECULAR 20 +#define MATERIAL_FRONT_EMISSION 21 +#define MATERIAL_FRONT_SHININESS 22 +#define MATERIAL_BACK_AMBIENT 23 +#define MATERIAL_BACK_DIFFUSE 24 +#define MATERIAL_BACK_SPECULAR 25 +#define MATERIAL_BACK_EMISSION 26 +#define MATERIAL_BACK_SHININESS 27 + +/** + * Light Property Bindings + */ +#define LIGHT_AMBIENT 28 +#define LIGHT_DIFFUSE 29 +#define LIGHT_SPECULAR 30 +#define LIGHT_POSITION 31 +#define LIGHT_ATTENUATION 32 +#define LIGHT_SPOT_DIRECTION 33 +#define LIGHT_HALF 34 +#define LIGHTMODEL_AMBIENT 35 +#define LIGHTMODEL_FRONT_SCENECOLOR 36 +#define LIGHTMODEL_BACK_SCENECOLOR 37 +#define LIGHTPROD_FRONT_AMBIENT 38 +#define LIGHTPROD_FRONT_DIFFUSE 39 +#define LIGHTPROD_FRONT_SPECULAR 40 +#define LIGHTPROD_BACK_AMBIENT 41 +#define LIGHTPROD_BACK_DIFFUSE 42 +#define LIGHTPROD_BACK_SPECULAR 43 + +/** + * Texgen Property Bindings + */ +#define TEXGEN_EYE_S 44 +#define TEXGEN_EYE_T 45 +#define TEXGEN_EYE_R 46 +#define TEXGEN_EYE_Q 47 +#define TEXGEN_OBJECT_S 48 +#define TEXGEN_OBJECT_T 49 +#define TEXGEN_OBJECT_R 50 +#define TEXGEN_OBJECT_Q 51 + +/** + * Fog Property Bindings + */ +#define FOG_COLOR 52 +#define FOG_PARAMS 53 + +/** + * Clip Property Bindings + */ +#define CLIP_PLANE 54 + +/** + * Point Property Bindings + */ +#define POINT_SIZE 55 +#define POINT_ATTENUATION 56 + +/** + * Matrix Row Property Bindings + */ +#define MATRIXROW_MODELVIEW 57 +#define MATRIXROW_MODELVIEW_INVERSE 58 +#define MATRIXROW_MODELVIEW_INVTRANS 59 +#define MATRIXROW_MODELVIEW_TRANSPOSE 60 +#define MATRIXROW_PROJECTION 61 +#define MATRIXROW_PROJECTION_INVERSE 62 +#define MATRIXROW_PROJECTION_INVTRANS 63 +#define MATRIXROW_PROJECTION_TRANSPOSE 64 +#define MATRIXROW_MVP 65 +#define MATRIXROW_MVP_INVERSE 66 +#define MATRIXROW_MVP_INVTRANS 67 +#define MATRIXROW_MVP_TRANSPOSE 68 +#define MATRIXROW_TEXTURE 69 +#define MATRIXROW_TEXTURE_INVERSE 70 +#define MATRIXROW_TEXTURE_INVTRANS 71 +#define MATRIXROW_TEXTURE_TRANSPOSE 72 +#define MATRIXROW_PALETTE 73 +#define MATRIXROW_PALETTE_INVERSE 74 +#define MATRIXROW_PALETTE_INVTRANS 75 +#define MATRIXROW_PALETTE_TRANSPOSE 76 +#define MATRIXROW_PROGRAM 77 +#define MATRIXROW_PROGRAM_INVERSE 78 +#define MATRIXROW_PROGRAM_INVTRANS 79 +#define MATRIXROW_PROGRAM_TRANSPOSE 80 + +#define MATRIXROWS_MODELVIEW 81 +#define MATRIXROWS_MODELVIEW_INVERSE 82 +#define MATRIXROWS_MODELVIEW_INVTRANS 83 +#define MATRIXROWS_MODELVIEW_TRANSPOSE 84 +#define MATRIXROWS_PROJECTION 85 +#define MATRIXROWS_PROJECTION_INVERSE 86 +#define MATRIXROWS_PROJECTION_INVTRANS 87 +#define MATRIXROWS_PROJECTION_TRANSPOSE 88 +#define MATRIXROWS_MVP 89 +#define MATRIXROWS_MVP_INVERSE 90 +#define MATRIXROWS_MVP_INVTRANS 91 +#define MATRIXROWS_MVP_TRANSPOSE 92 +#define MATRIXROWS_TEXTURE 93 +#define MATRIXROWS_TEXTURE_INVERSE 94 +#define MATRIXROWS_TEXTURE_INVTRANS 95 +#define MATRIXROWS_TEXTURE_TRANSPOSE 96 +#define MATRIXROWS_PALETTE 97 +#define MATRIXROWS_PALETTE_INVERSE 98 +#define MATRIXROWS_PALETTE_INVTRANS 99 +#define MATRIXROWS_PALETTE_TRANSPOSE 100 +#define MATRIXROWS_PROGRAM 101 +#define MATRIXROWS_PROGRAM_INVERSE 102 +#define MATRIXROWS_PROGRAM_INVTRANS 103 +#define MATRIXROWS_PROGRAM_TRANSPOSE 104 + +#define PROGRAM_ENV_SINGLE 105 +#define PROGRAM_LOCAL_SINGLE 106 +#define PROGRAM_ENV_MULTI 107 +#define PROGRAM_LOCAL_MULTI 108 + +#define CONSTANT 109 + + + + +#define IS_WHITESPACE(c) (c == ' ') || (c == '\t') || (c == '\n') +#define IS_IDCHAR(c) ((c >= 'A') && (c <= 'Z')) || \ + ((c >= 'a') && (c <= 'z')) || \ + (c == '_') || (c == '$') +#define IS_DIGIT(c) (c >= '0') && (c <= '9') +#define IS_CD(c) (IS_DIGIT(c)) || (IS_IDCHAR(c)) + +#define ADV_TO_STATE(state) s->curr_state = state; s->curr_pos++; + +#define ADV_OR_FALLBACK(c, state) if (curr == c) { \ + ADV_TO_STATE(state); \ + } else {\ + if (IS_CD(curr)) { \ + ADV_TO_STATE(STATE_IDENT); \ + } else \ + s->curr_state = 1;\ + } + +#define FINISH(tok) *token = tok; s->start_pos = s->curr_pos; s->curr_state = STATE_BASE; return ARB_VP_SUCESS; +#define ADV_AND_FINISH(tok) *token = tok; s->start_pos = s->curr_pos+1; s->curr_pos++; \ + s->curr_state = STATE_BASE; return ARB_VP_SUCESS; + +#define FINISH_OR_FALLBACK(tok) if (IS_CD(curr)) {\ + ADV_TO_STATE(STATE_IDENT); \ + } else { \ + FINISH(tok)\ + } + +#define NO_KW {"", "", "", ""} +#define NULL2 NULL_TOKEN, NULL_TOKEN +#define NULL3 NULL_TOKEN, NULL2 +#define NULL4 NULL2, NULL2 + +/* This uglyness is the production table. See the prod_table struct definition for a description */ +prod_table ptab[] = { + {NT_PROGRAM_TOKEN, + {NT_OPTION_SEQUENCE_TOKEN, NT_STATEMENT_SEQUENCE_TOKEN, END_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_OPTION_SEQUENCE_TOKEN, {NT_OPTION_SEQUENCE2_TOKEN, NULL3}, NO_KW}, + {NT_OPTION_SEQUENCE2_TOKEN, {NT_OPTION_TOKEN, NT_OPTION_SEQUENCE2_TOKEN, NULL2}, NO_KW}, + {NT_OPTION_SEQUENCE2_TOKEN, {NULL4}, NO_KW}, + {NT_OPTION_TOKEN, {OPTION_TOKEN, ID_TOKEN, SEMICOLON_TOKEN, NULL_TOKEN}, NO_KW}, + + + /* 5: */ + {NT_STATEMENT_SEQUENCE_TOKEN, {NT_STATEMENT_SEQUENCE2_TOKEN, NULL3}, NO_KW}, + {NT_STATEMENT_SEQUENCE2_TOKEN, {NT_STATEMENT_TOKEN, NT_STATEMENT_SEQUENCE2_TOKEN, NULL2}, NO_KW}, + {NT_STATEMENT_SEQUENCE2_TOKEN, {NULL4}, NO_KW}, + {NT_STATEMENT_TOKEN, {NT_INSTRUCTION_TOKEN, SEMICOLON_TOKEN, NULL2}, NO_KW}, + {NT_STATEMENT_TOKEN, {NT_NAMING_STATEMENT_TOKEN, SEMICOLON_TOKEN, NULL2}, NO_KW}, + + /* 10: */ + {NT_INSTRUCTION_TOKEN, {NT_ARL_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + {NT_INSTRUCTION_TOKEN, {NT_VECTOROP_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + {NT_INSTRUCTION_TOKEN, {NT_SCALAROP_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + {NT_INSTRUCTION_TOKEN, {NT_BINSCOP_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + {NT_INSTRUCTION_TOKEN, {NT_BINOP_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + + /* 15: */ + {NT_INSTRUCTION_TOKEN, {NT_TRIOP_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + {NT_INSTRUCTION_TOKEN, {NT_SWZ_INSTRUCTION_TOKEN, NULL3}, NO_KW}, + {NT_ARL_INSTRUCTION_TOKEN, {ARL_TOKEN, NT_MASKED_ADDR_REG_TOKEN, + COMMA_TOKEN, NT_SCALAR_SRC_REG_TOKEN}, NO_KW}, + {NT_VECTOROP_INSTRUCTION_TOKEN, {NT_VECTOROP_TOKEN, NT_MASKED_DST_REG_TOKEN, COMMA_TOKEN, + NT_SWIZZLE_SRC_REG_TOKEN}, NO_KW}, + {NT_VECTOROP_TOKEN, {ABS_TOKEN, NULL3}, NO_KW}, + + /* 20: */ + {NT_VECTOROP_TOKEN, {FLR_TOKEN, NULL3}, NO_KW}, + {NT_VECTOROP_TOKEN, {FRC_TOKEN, NULL3}, NO_KW}, + {NT_VECTOROP_TOKEN, {LIT_TOKEN, NULL3}, NO_KW}, + {NT_VECTOROP_TOKEN, {MOV_TOKEN, NULL3}, NO_KW}, + {NT_SCALAROP_INSTRUCTION_TOKEN, {NT_SCALAROP_TOKEN, NT_MASKED_DST_REG_TOKEN, COMMA_TOKEN, + NT_SCALAR_SRC_REG_TOKEN}, NO_KW}, + + /* 25: */ + {NT_SCALAROP_TOKEN, {EX2_TOKEN, NULL3}, NO_KW}, + {NT_SCALAROP_TOKEN, {EXP_TOKEN, NULL3}, NO_KW}, + {NT_SCALAROP_TOKEN, {LG2_TOKEN, NULL3}, NO_KW}, + {NT_SCALAROP_TOKEN, {LOG_TOKEN, NULL3}, NO_KW}, + {NT_SCALAROP_TOKEN, {RCP_TOKEN, NULL3}, NO_KW}, + + /* 30: */ + {NT_SCALAROP_TOKEN, {RSQ_TOKEN, NULL3}, NO_KW}, + {NT_BINSCOP_INSTRUCTION_TOKEN, + {NT_BINSCOP_TOKEN, NT_MASKED_DST_REG_TOKEN, NT_BINSCOP_INSTRUCTION2_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_BINSCOP_INSTRUCTION2_TOKEN, + {COMMA_TOKEN, NT_SCALAR_SRC_REG_TOKEN, COMMA_TOKEN, + NT_SCALAR_SRC_REG_TOKEN}, NO_KW}, + {NT_BINSCOP_TOKEN, {POW_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_INSTRUCTION_TOKEN, + {NT_BINOP_TOKEN, NT_MASKED_DST_REG_TOKEN, NT_BINOP_INSTRUCTION2_TOKEN, + NULL_TOKEN}, NO_KW}, + + /* 35: */ + {NT_BINOP_INSTRUCTION2_TOKEN, + {COMMA_TOKEN, NT_SWIZZLE_SRC_REG_TOKEN, COMMA_TOKEN, + NT_SWIZZLE_SRC_REG_TOKEN}, NO_KW}, + {NT_BINOP_TOKEN, {ADD_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {DP3_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {DP4_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {DPH_TOKEN, NULL3}, NO_KW}, + + /* 40: */ + {NT_BINOP_TOKEN, {DST_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {MAX_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {MIN_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {MUL_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {SGE_TOKEN, NULL3}, NO_KW}, + + /* 45: */ + {NT_BINOP_TOKEN, {SLT_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {SUB_TOKEN, NULL3}, NO_KW}, + {NT_BINOP_TOKEN, {XPD_TOKEN, NULL3}, NO_KW}, + {NT_TRIOP_INSTRUCTION_TOKEN, + {NT_TRIOP_TOKEN, NT_MASKED_DST_REG_TOKEN, NT_TRIOP_INSTRUCTION2_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_TRIOP_INSTRUCTION2_TOKEN, + {COMMA_TOKEN, NT_SWIZZLE_SRC_REG_TOKEN, NT_TRIOP_INSTRUCTION3_TOKEN, + NULL_TOKEN}, NO_KW}, + + /* 50: */ + {NT_TRIOP_INSTRUCTION3_TOKEN, + {COMMA_TOKEN, NT_SWIZZLE_SRC_REG_TOKEN, COMMA_TOKEN, + NT_SWIZZLE_SRC_REG_TOKEN}, NO_KW}, + {NT_TRIOP_TOKEN, {MAD_TOKEN, NULL3}, NO_KW}, + {NT_SWZ_INSTRUCTION_TOKEN, + {SWZ_TOKEN, NT_MASKED_DST_REG_TOKEN, NT_SWZ_INSTRUCTION2_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_SWZ_INSTRUCTION2_TOKEN, + {COMMA_TOKEN, NT_SRC_REG_TOKEN, COMMA_TOKEN, NT_EXTENDED_SWIZZLE_TOKEN}, + NO_KW}, + {NT_SCALAR_SRC_REG_TOKEN, + {NT_OPTIONAL_SIGN_TOKEN, NT_SRC_REG_TOKEN, NT_SCALAR_SUFFIX_TOKEN, + NULL_TOKEN}, NO_KW}, + + /* 55 */ + {NT_SWIZZLE_SRC_REG_TOKEN, + {NT_OPTIONAL_SIGN_TOKEN, NT_SRC_REG_TOKEN, NT_SWIZZLE_SUFFIX_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_MASKED_DST_REG_TOKEN, + {NT_DST_REG_TOKEN, NT_OPTIONAL_MASK_TOKEN, NULL2}, NO_KW}, + {NT_MASKED_ADDR_REG_TOKEN, + {NT_ADDR_REG_TOKEN, NT_ADDR_WRITE_MASK_TOKEN, NULL2}, NO_KW}, + {NT_EXTENDED_SWIZZLE_TOKEN, + {NT_EXT_SWIZ_COMP_TOKEN, COMMA_TOKEN, NT_EXT_SWIZ_COMP_TOKEN, + NT_EXTENDED_SWIZZLE2_TOKEN}, NO_KW}, + {NT_EXTENDED_SWIZZLE2_TOKEN, + {COMMA_TOKEN, NT_EXT_SWIZ_COMP_TOKEN, COMMA_TOKEN, + NT_EXT_SWIZ_COMP_TOKEN}, NO_KW}, + + /* 60 */ + {NT_EXT_SWIZ_COMP_TOKEN,{NT_OPTIONAL_SIGN_TOKEN, NT_EXT_SWIZ_SEL_TOKEN, NULL2}, + NO_KW}, + {NT_EXT_SWIZ_SEL_TOKEN, {INTEGER_TOKEN, NULL3}, {"0", "", "", ""}}, + {NT_EXT_SWIZ_SEL_TOKEN, {INTEGER_TOKEN, NULL3}, {"1", "", "", ""}}, + {NT_EXT_SWIZ_SEL_TOKEN, {NT_COMPONENT_TOKEN, NULL3}, NO_KW}, + {NT_SRC_REG_TOKEN, {NT_VERTEX_ATTRIB_REG_TOKEN, NULL3}, NO_KW}, + + /* 65: */ + {NT_SRC_REG_TOKEN, {NT_TEMPORARY_REG_TOKEN, NULL3}, NO_KW}, + {NT_SRC_REG_TOKEN, {NT_PROG_PARAM_REG_TOKEN, NULL3}, NO_KW}, + {NT_DST_REG_TOKEN, {NT_TEMPORARY_REG_TOKEN, NULL3}, NO_KW}, + {NT_DST_REG_TOKEN, {NT_VERTEX_RESULT_REG_TOKEN, NULL3}, NO_KW}, + {NT_VERTEX_ATTRIB_REG_TOKEN, {NT_ESTABLISHED_NAME_TOKEN, NULL3}, NO_KW}, + + /* 70: */ + {NT_VERTEX_ATTRIB_REG_TOKEN, {NT_VTX_ATTRIB_BINDING_TOKEN, NULL3}, NO_KW}, + {NT_TEMPORARY_REG_TOKEN, {NT_ESTABLISHED_NAME_TOKEN, NULL3}, NO_KW}, + {NT_PROG_PARAM_REG_TOKEN, {NT_PROG_PARAM_SINGLE_TOKEN, NULL3}, NO_KW}, + {NT_PROG_PARAM_REG_TOKEN, + {NT_PROG_PARAM_ARRAY_TOKEN, LBRACKET_TOKEN, NT_PROG_PARAM_ARRAY_MEM_TOKEN, + RBRACKET_TOKEN}, NO_KW}, + {NT_PROG_PARAM_REG_TOKEN, {NT_PARAM_SINGLE_ITEM_USE_TOKEN, NULL3}, NO_KW}, + + /* 75: */ + {NT_PROG_PARAM_SINGLE_TOKEN, {NT_ESTABLISHED_NAME_TOKEN, NULL3}, NO_KW}, + {NT_PROG_PARAM_ARRAY_TOKEN, {NT_ESTABLISHED_NAME_TOKEN, NULL3}, NO_KW}, + {NT_PROG_PARAM_ARRAY_MEM_TOKEN, {NT_PROG_PARAM_ARRAY_ABS_TOKEN, NULL3}, NO_KW}, + {NT_PROG_PARAM_ARRAY_MEM_TOKEN, {NT_PROG_PARAM_ARRAY_REL_TOKEN, NULL3}, NO_KW}, + /* -1 matches all */ + {NT_PROG_PARAM_ARRAY_ABS_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + + + /* 80: */ + {NT_PROG_PARAM_ARRAY_REL_TOKEN, + {NT_ADDR_REG_TOKEN, NT_ADDR_COMPONENT_TOKEN, NT_ADDR_REG_REL_OFFSET_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_ADDR_REG_REL_OFFSET_TOKEN, {NULL4}, NO_KW}, + {NT_ADDR_REG_REL_OFFSET_TOKEN, + {PLUS_TOKEN, NT_ADDR_REG_POS_OFFSET_TOKEN, NULL2}, NO_KW}, + {NT_ADDR_REG_REL_OFFSET_TOKEN, + {MINUS_TOKEN, NT_ADDR_REG_NEG_OFFSET_TOKEN, NULL2}, NO_KW}, + {NT_ADDR_REG_POS_OFFSET_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + + /* 85: */ + {NT_ADDR_REG_NEG_OFFSET_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_VERTEX_RESULT_REG_TOKEN, {NT_ESTABLISHED_NAME_TOKEN, NULL3}, NO_KW}, + {NT_VERTEX_RESULT_REG_TOKEN, {NT_RESULT_BINDING_TOKEN, NULL3}, NO_KW}, + {NT_ADDR_REG_TOKEN, {NT_ESTABLISHED_NAME_TOKEN, NULL3}, NO_KW}, + {NT_ADDR_COMPONENT_TOKEN, {PERIOD_TOKEN, ID_TOKEN, NULL2}, {"", "x", "", ""}}, + + /* 90: */ + {NT_ADDR_WRITE_MASK_TOKEN, {PERIOD_TOKEN, ID_TOKEN, NULL2}, {"", "x", "", ""}}, + {NT_SCALAR_SUFFIX_TOKEN, {PERIOD_TOKEN, NT_COMPONENT_TOKEN, NULL2}, {"", "x", "", ""}}, + {NT_SWIZZLE_SUFFIX_TOKEN, {NULL4}, NO_KW}, + {NT_COMPONENT_TOKEN, {ID_TOKEN, NULL3}, {"x", "", "", ""}}, + {NT_COMPONENT_TOKEN, {ID_TOKEN, NULL3}, {"y", "", "", ""}}, + + /* 95: */ + {NT_COMPONENT_TOKEN, {ID_TOKEN, NULL3}, {"z", "", "", ""}}, + {NT_COMPONENT_TOKEN, {ID_TOKEN, NULL3}, {"w", "", "", ""}}, + {NT_OPTIONAL_MASK_TOKEN, {PERIOD_TOKEN, NT_OPTIONAL_MASK2_TOKEN, NULL2}, NO_KW}, + {NT_OPTIONAL_MASK_TOKEN, {NULL4}, NO_KW}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"x", "", "", ""}}, + + /* 100: */ + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"y", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xy", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"z", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xz", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"yz", "", "", ""}}, + + /* 105: */ + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xyz", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"w", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xw", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"yw", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xyw", "", "", ""}}, + + /* 110: */ + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"zw", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xzw", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"yzw", "", "", ""}}, + {NT_OPTIONAL_MASK2_TOKEN, {ID_TOKEN, NULL3}, {"xyzw", "", "", ""}}, + {NT_NAMING_STATEMENT_TOKEN, {NT_ATTRIB_STATEMENT_TOKEN, NULL3}, NO_KW}, + + /* 115: */ + {NT_NAMING_STATEMENT_TOKEN, {NT_PARAM_STATEMENT_TOKEN, NULL3}, NO_KW}, + {NT_NAMING_STATEMENT_TOKEN, {NT_TEMP_STATEMENT_TOKEN, NULL3}, NO_KW}, + {NT_NAMING_STATEMENT_TOKEN, {NT_ADDRESS_STATEMENT_TOKEN, NULL3}, NO_KW}, + {NT_NAMING_STATEMENT_TOKEN, {NT_OUTPUT_STATEMENT_TOKEN, NULL3}, NO_KW}, + {NT_NAMING_STATEMENT_TOKEN, {NT_ALIAS_STATEMENT_TOKEN, NULL3}, NO_KW}, + + /* 120: */ + {NT_ATTRIB_STATEMENT_TOKEN, + {ATTRIB_TOKEN, NT_ESTABLISH_NAME_TOKEN, EQUAL_TOKEN, NT_VTX_ATTRIB_BINDING_TOKEN}, NO_KW}, + {NT_VTX_ATTRIB_BINDING_TOKEN, + {VERTEX_TOKEN, PERIOD_TOKEN, NT_VTX_ATTRIB_ITEM_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_VTX_ATTRIB_ITEM_TOKEN, {ID_TOKEN, NULL3}, {"position", "", "", ""}}, + {NT_VTX_ATTRIB_ITEM_TOKEN, {ID_TOKEN, NT_VTX_OPT_WEIGHT_NUM_TOKEN, NULL2},{"weight", "", "", ""}}, + {NT_VTX_ATTRIB_ITEM_TOKEN, {ID_TOKEN, NULL3}, {"normal", "", "", ""}}, + + /* 125: */ + {NT_VTX_ATTRIB_ITEM_TOKEN, {ID_TOKEN, NT_OPT_COLOR_TYPE_TOKEN, NULL2}, + {"color", "", "", ""}}, + {NT_VTX_ATTRIB_ITEM_TOKEN, {ID_TOKEN, NULL3}, {"fogcoord", "", "", ""}}, + {NT_VTX_ATTRIB_ITEM_TOKEN, {ID_TOKEN, NT_OPT_TEX_COORD_NUM_TOKEN, NULL2}, + {"texcoord", "", "", ""}}, + {NT_VTX_ATTRIB_ITEM_TOKEN, + {ID_TOKEN, LBRACKET_TOKEN, NT_VTX_WEIGHT_NUM_TOKEN, RBRACKET_TOKEN}, + {"matrixindex", "", "", ""}}, + {NT_VTX_ATTRIB_ITEM_TOKEN, + {ID_TOKEN, LBRACKET_TOKEN, NT_VTX_ATTRIB_NUM_TOKEN, RBRACKET_TOKEN}, + {"attrib", "", "", ""}}, + + /* 130: */ + {NT_VTX_ATTRIB_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_VTX_OPT_WEIGHT_NUM_TOKEN, {NULL4}, NO_KW}, + {NT_VTX_OPT_WEIGHT_NUM_TOKEN, {LBRACKET_TOKEN, NT_VTX_WEIGHT_NUM_TOKEN, RBRACKET_TOKEN, NULL_TOKEN}, + NO_KW}, + {NT_VTX_WEIGHT_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_PARAM_STATEMENT_TOKEN, + {PARAM_TOKEN, NT_ESTABLISH_NAME_TOKEN, NT_PARAM_STATEMENT2_TOKEN, + NULL_TOKEN}, NO_KW}, + + /* 135: */ + {NT_PARAM_STATEMENT2_TOKEN, {NT_PARAM_SINGLE_INIT_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_STATEMENT2_TOKEN, {LBRACKET_TOKEN, NT_OPT_ARRAY_SIZE_TOKEN, RBRACKET_TOKEN, + NT_PARAM_MULTIPLE_INIT_TOKEN}, NO_KW}, + {NT_OPT_ARRAY_SIZE_TOKEN, {NULL4}, NO_KW}, + {NT_OPT_ARRAY_SIZE_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_PARAM_SINGLE_INIT_TOKEN, {EQUAL_TOKEN, NT_PARAM_SINGLE_ITEM_DECL_TOKEN, NULL2}, + NO_KW}, + + + /* 140: */ + {NT_PARAM_MULTIPLE_INIT_TOKEN, + {EQUAL_TOKEN, LBRACE_TOKEN, NT_PARAM_MULT_INIT_LIST_TOKEN, RBRACE_TOKEN}, + NO_KW}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, NT_PARAM_MULT_INIT_LIST2_TOKEN, NULL2}, + NO_KW}, + {NT_PARAM_MULT_INIT_LIST2_TOKEN, + {COMMA_TOKEN, NT_PARAM_MULT_INIT_LIST_TOKEN, NULL2}, + NO_KW}, + {NT_PARAM_MULT_INIT_LIST2_TOKEN, {NULL4}, NO_KW}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, {NT_STATE_SINGLE_ITEM_TOKEN, NULL3}, + NO_KW}, + + /* 145: */ + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, {NT_PROGRAM_SINGLE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, {NT_PARAM_CONST_DECL_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, {NT_STATE_SINGLE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, {NT_PROGRAM_SINGLE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, {NT_PARAM_CONST_USE_TOKEN, NULL3}, NO_KW}, + + /* 150: */ + {NT_PARAM_MULTIPLE_ITEM_TOKEN, {NT_STATE_MULTIPLE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, {NT_PROGRAM_MULTIPLE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, {NT_PARAM_CONST_DECL_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM_TOKEN, + {STATE_TOKEN, PERIOD_TOKEN, NT_STATE_MULTIPLE_ITEM2_TOKEN, NULL_TOKEN}, + NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_MATERIAL_ITEM_TOKEN, NULL3}, NO_KW}, + + /* 155: */ + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_LIGHT_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_LIGHT_MODEL_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_LIGHT_PROD_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_TEX_GEN_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_FOG_ITEM_TOKEN, NULL3}, NO_KW}, + + /* 160: */ + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_CLIP_PLANE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, {NT_STATE_POINT_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, + {ID_TOKEN, PERIOD_TOKEN, NT_STATE_MATRIX_NAME_TOKEN, NT_FOO_TOKEN}, + {"matrix", "", "", ""}}, + {NT_FOO_TOKEN, {PERIOD_TOKEN, NT_FOO2_TOKEN, NULL2}, NO_KW}, + {NT_FOO2_TOKEN, {NT_STATE_MAT_MODIFIER_TOKEN, NT_FOO3_TOKEN, NULL2}, NO_KW}, + + /* 165: */ + {NT_FOO2_TOKEN, {ID_TOKEN, LBRACKET_TOKEN, NT_STATE_MATRIX_ROW_NUM_TOKEN, NT_FOO4_TOKEN}, + {"row", "", "", ""}}, + {NT_FOO3_TOKEN, {NULL4}, NO_KW}, + {NT_FOO3_TOKEN, {PERIOD_TOKEN, ID_TOKEN, LBRACKET_TOKEN, NT_FOO35_TOKEN}, + {"", "row", "", ""}}, + {NT_FOO35_TOKEN, {NT_STATE_MATRIX_ROW_NUM_TOKEN, NT_FOO4_TOKEN, NULL2}, + NO_KW}, + {NT_FOO4_TOKEN, {RBRACKET_TOKEN, NULL3}, NO_KW}, + + /* 170: */ + {NT_FOO4_TOKEN, {DOTDOT_TOKEN, NT_STATE_MATRIX_ROW_NUM_TOKEN, RBRACKET_TOKEN, NULL_TOKEN}, + NO_KW}, + {NT_STATE_SINGLE_ITEM_TOKEN, + {STATE_TOKEN, PERIOD_TOKEN, NT_STATE_SINGLE_ITEM2_TOKEN, NULL_TOKEN}, + NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_MATERIAL_ITEM_TOKEN, NULL3}, + NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_LIGHT_ITEM_TOKEN, NULL3}, + NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_LIGHT_MODEL_ITEM_TOKEN, NULL3}, + NO_KW}, + + /* 175: */ + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_LIGHT_PROD_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_TEX_GEN_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_FOG_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_CLIP_PLANE_ITEM_TOKEN, NULL3}, NO_KW}, + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_POINT_ITEM_TOKEN, NULL3}, NO_KW}, + + /* 180: */ + {NT_STATE_SINGLE_ITEM2_TOKEN, {NT_STATE_MATRIX_ROW_TOKEN, NULL3}, NO_KW}, + {NT_STATE_MATERIAL_ITEM_TOKEN, + {ID_TOKEN, PERIOD_TOKEN, NT_STATE_MATERIAL_ITEM2_TOKEN, NULL_TOKEN}, + {"material", "", "", ""}}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, {NT_STATE_MAT_PROPERTY_TOKEN, NULL3}, + NO_KW}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, + {PERIOD_TOKEN, NT_OPT_FACE_TYPE2_TOKEN, PERIOD_TOKEN, + NT_STATE_MAT_PROPERTY_TOKEN}, NO_KW}, + {NT_STATE_MAT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"ambient", "", "", ""}}, + + /* 185 */ + {NT_STATE_MAT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"diffuse", "", "", ""}}, + {NT_STATE_MAT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"specular", "", "", ""}}, + {NT_STATE_MAT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"emission", "", "", ""}}, + {NT_STATE_MAT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"shininess", "", "", ""}}, + {NT_STATE_LIGHT_ITEM_TOKEN, + {ID_TOKEN, LBRACKET_TOKEN, NT_STATE_LIGHT_NUMBER_TOKEN, + NT_STATE_LIGHT_ITEM2_TOKEN}, {"light", "", "", ""}}, + + /* 190: */ + {NT_STATE_LIGHT_ITEM2_TOKEN, {RBRACKET_TOKEN, PERIOD_TOKEN, NT_STATE_LIGHT_PROPERTY_TOKEN, NULL_TOKEN}, + NO_KW}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"ambient", "", "", ""}}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"diffuse", "", "", ""}}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"specular", "", "", ""}}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"position", "", "", ""}}, + + /* 195: */ + {NT_STATE_LIGHT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"attenuation", "", "", ""}}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, + {ID_TOKEN, PERIOD_TOKEN, NT_STATE_SPOT_PROPERTY_TOKEN, NULL_TOKEN}, + {"spot", "", "", ""}}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"half", "", "", ""}}, + {NT_STATE_SPOT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"direction", "", "", ""}}, + {NT_STATE_LIGHT_MODEL_ITEM_TOKEN, + {ID_TOKEN, NT_STATE_LMOD_PROPERTY_TOKEN, NULL2}, {"lightmodel", "", "", ""}}, + + /* 200: */ + {NT_STATE_LMOD_PROPERTY_TOKEN, {PERIOD_TOKEN, NT_STATE_LMOD_PROPERTY2_TOKEN, NULL2}, NO_KW}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, {ID_TOKEN, NULL3}, {"ambient", "", "", ""}}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, {ID_TOKEN, NULL3}, {"scenecolor", "", "", ""}}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, + {NT_OPT_FACE_TYPE2_TOKEN, PERIOD_TOKEN, ID_TOKEN, NULL_TOKEN}, + {"scenecolor", "", "", ""}}, + {NT_STATE_LIGHT_PROD_ITEM_TOKEN, + {ID_TOKEN, LBRACKET_TOKEN, NT_STATE_LIGHT_NUMBER_TOKEN, + NT_STATE_LIGHT_PROD_ITEM15_TOKEN}, {"lightprod", "", "", ""}}, + + /* 205: */ + {NT_STATE_LIGHT_PROD_ITEM15_TOKEN, + {RBRACKET_TOKEN, PERIOD_TOKEN, NT_STATE_LIGHT_PROD_ITEM2_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, {NT_STATE_LPROD_PROPERTY_TOKEN, NULL3}, NO_KW}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, + {NT_OPT_FACE_TYPE2_TOKEN, PERIOD_TOKEN, NT_STATE_LPROD_PROPERTY_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_STATE_LPROD_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"diffuse", "", "", ""}}, + {NT_STATE_LPROD_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"ambient", "", "", ""}}, + + /* 210: */ + {NT_STATE_LPROD_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"specular", "", "", ""}}, + {NT_STATE_LIGHT_NUMBER_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_STATE_TEX_GEN_ITEM_TOKEN, {ID_TOKEN, NT_OPT_TEX_COORD_NUM_TOKEN, + NT_STATE_TEX_GEN_ITEM2_TOKEN, NULL_TOKEN}, {"texgen", "", "", ""}}, + {NT_STATE_TEX_GEN_ITEM2_TOKEN,{PERIOD_TOKEN, NT_STATE_TEX_GEN_TYPE_TOKEN, PERIOD_TOKEN, + NT_STATE_TEX_GEN_COORD_TOKEN}, NO_KW}, + {NT_STATE_TEX_GEN_TYPE_TOKEN, {ID_TOKEN, NULL3}, {"eye", "", "", ""}}, + + /* 215: */ + {NT_STATE_TEX_GEN_TYPE_TOKEN, {ID_TOKEN, NULL3}, {"object", "", "", ""}}, + {NT_STATE_TEX_GEN_COORD_TOKEN, {ID_TOKEN, NULL3}, {"s", "", "", ""}}, + {NT_STATE_TEX_GEN_COORD_TOKEN, {ID_TOKEN, NULL3}, {"t", "", "", ""}}, + {NT_STATE_TEX_GEN_COORD_TOKEN, {ID_TOKEN, NULL3}, {"r", "", "", ""}}, + {NT_STATE_TEX_GEN_COORD_TOKEN, {ID_TOKEN, NULL3}, {"q", "", "", ""}}, + + /* 220: */ + {NT_STATE_FOG_ITEM_TOKEN, {ID_TOKEN, PERIOD_TOKEN, NT_STATE_FOG_PROPERTY_TOKEN, NULL_TOKEN}, + {"fog", "","",""}}, + {NT_STATE_FOG_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"color", "", "", ""}}, + {NT_STATE_FOG_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"params", "", "", ""}}, + {NT_STATE_CLIP_PLANE_ITEM_TOKEN, + {ID_TOKEN, LBRACKET_TOKEN, NT_STATE_CLIP_PLANE_NUM_TOKEN, + NT_STATE_CLIP_PLANE_ITEM2_TOKEN}, {"clip", "", "", ""}}, + {NT_STATE_CLIP_PLANE_ITEM2_TOKEN, + {RBRACKET_TOKEN, PERIOD_TOKEN, ID_TOKEN, NULL_TOKEN}, + {"", "", "plane", ""}}, + + /* 225: */ + {NT_STATE_CLIP_PLANE_NUM_TOKEN,{INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_STATE_POINT_ITEM_TOKEN, {ID_TOKEN, PERIOD_TOKEN, NT_STATE_POINT_PROPERTY_TOKEN, NULL_TOKEN}, + {"point", "", "", ""}}, + {NT_STATE_POINT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"size", "", "", ""}}, + {NT_STATE_POINT_PROPERTY_TOKEN, {ID_TOKEN, NULL3}, {"attenuation", "", "", ""}}, + {NT_STATE_MATRIX_ROW_TOKEN, {ID_TOKEN, PERIOD_TOKEN, NT_STATE_MATRIX_NAME_TOKEN, + NT_STATE_MATRIX_ROW15_TOKEN}, {"matrix", "", "", ""}}, + + /* 230: */ + {NT_STATE_MATRIX_ROW15_TOKEN, {PERIOD_TOKEN, NT_STATE_MATRIX_ROW2_TOKEN, NULL2}, NO_KW}, + {NT_STATE_MATRIX_ROW2_TOKEN, {ID_TOKEN, LBRACKET_TOKEN, + NT_STATE_MATRIX_ROW_NUM_TOKEN, RBRACKET_TOKEN}, + {"row", "", "", ""}}, + {NT_STATE_MATRIX_ROW2_TOKEN, {NT_STATE_MAT_MODIFIER_TOKEN, PERIOD_TOKEN, ID_TOKEN, + NT_STATE_MATRIX_ROW3_TOKEN}, + {"", "", "row", ""}}, + {NT_STATE_MATRIX_ROW3_TOKEN, {LBRACKET_TOKEN, NT_STATE_MATRIX_ROW_NUM_TOKEN, RBRACKET_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_STATE_MAT_MODIFIER_TOKEN, {ID_TOKEN, NULL3}, {"inverse", "", "", ""}}, + + /* 235: */ + {NT_STATE_MAT_MODIFIER_TOKEN, {ID_TOKEN, NULL3}, {"transpose", "", "", ""}}, + {NT_STATE_MAT_MODIFIER_TOKEN, {ID_TOKEN, NULL3}, {"invtrans", "", "", ""}}, + {NT_STATE_MATRIX_ROW_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_STATE_MATRIX_NAME_TOKEN, {ID_TOKEN, NT_STATE_OPT_MOD_MAT_NUM_TOKEN, NULL2}, + {"modelview", "", "", ""}}, + {NT_STATE_MATRIX_NAME_TOKEN, {ID_TOKEN, NULL3}, {"projection", "", "", ""}}, + + /* 240: */ + {NT_STATE_MATRIX_NAME_TOKEN, {ID_TOKEN, NULL3}, {"mvp", "", "", ""}}, + {NT_STATE_MATRIX_NAME_TOKEN, {ID_TOKEN, NT_OPT_TEX_COORD_NUM_TOKEN, NULL2}, + {"texture", "", "", ""}}, + {NT_STATE_MATRIX_NAME_TOKEN, {ID_TOKEN, LBRACKET_TOKEN, NT_STATE_PALETTE_MAT_NUM_TOKEN, + RBRACKET_TOKEN}, {"palette", "", "", ""}}, + {NT_STATE_MATRIX_NAME_TOKEN, {PROGRAM_TOKEN, LBRACKET_TOKEN, NT_STATE_PROGRAM_MAT_NUM_TOKEN, + RBRACKET_TOKEN}, NO_KW}, + {NT_STATE_OPT_MOD_MAT_NUM_TOKEN, {NULL4}, NO_KW}, + + /* 245: */ + {NT_STATE_OPT_MOD_MAT_NUM_TOKEN, + {LBRACKET_TOKEN, NT_STATE_MOD_MAT_NUM_TOKEN, RBRACKET_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_STATE_MOD_MAT_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_STATE_PALETTE_MAT_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_STATE_PROGRAM_MAT_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_PROGRAM_SINGLE_ITEM_TOKEN, + {PROGRAM_TOKEN, PERIOD_TOKEN, NT_PROGRAM_SINGLE_ITEM2_TOKEN, NULL_TOKEN}, NO_KW}, + + /* 250: */ + {NT_PROGRAM_SINGLE_ITEM2_TOKEN, {NT_PROG_ENV_PARAM_TOKEN, NULL3}, NO_KW}, + {NT_PROGRAM_SINGLE_ITEM2_TOKEN, {NT_PROG_LOCAL_PARAM_TOKEN, NULL3}, NO_KW}, + {NT_PROGRAM_MULTIPLE_ITEM_TOKEN, + {PROGRAM_TOKEN, PERIOD_TOKEN, NT_PROGRAM_MULTIPLE_ITEM2_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_PROGRAM_MULTIPLE_ITEM2_TOKEN, {NT_PROG_ENV_PARAMS_TOKEN, NULL3}, NO_KW}, + {NT_PROGRAM_MULTIPLE_ITEM2_TOKEN, {NT_PROG_LOCAL_PARAMS_TOKEN, NULL3}, NO_KW}, + + /* 255: */ + {NT_PROG_ENV_PARAMS_TOKEN, {ID_TOKEN, LBRACKET_TOKEN, NT_PROG_ENV_PARAM_NUMS_TOKEN, RBRACKET_TOKEN}, + {"env", "", "", ""}}, + {NT_PROG_ENV_PARAM_NUMS_TOKEN, {NT_PROG_ENV_PARAM_NUM_TOKEN, NT_PROG_ENV_PARAM_NUMS2_TOKEN, NULL2}, + NO_KW}, + {NT_PROG_ENV_PARAM_NUMS2_TOKEN, {DOTDOT_TOKEN, NT_PROG_ENV_PARAM_NUM_TOKEN, NULL2}, NO_KW}, + {NT_PROG_ENV_PARAM_NUMS2_TOKEN, {NULL4}, NO_KW}, + {NT_PROG_ENV_PARAM_TOKEN, + {ID_TOKEN, LBRACKET_TOKEN, NT_PROG_ENV_PARAM_NUM_TOKEN, RBRACKET_TOKEN}, + {"env", "", "", ""}}, + + /* 260: */ + {NT_PROG_LOCAL_PARAMS_TOKEN, {ID_TOKEN, LBRACKET_TOKEN, NT_PROG_LOCAL_PARAM_NUMS_TOKEN, + RBRACKET_TOKEN}, {"local", "", "", ""}}, + {NT_PROG_LOCAL_PARAM_NUMS_TOKEN, + {NT_PROG_LOCAL_PARAM_NUM_TOKEN, NT_PROG_LOCAL_PARAM_NUMS2_TOKEN, NULL2}, + NO_KW}, + {NT_PROG_LOCAL_PARAM_NUMS2_TOKEN, {DOTDOT_TOKEN, NT_PROG_LOCAL_PARAM_NUM_TOKEN, NULL2}, NO_KW}, + {NT_PROG_LOCAL_PARAM_NUMS2_TOKEN, {NULL4}, NO_KW}, + {NT_PROG_LOCAL_PARAM_TOKEN, {ID_TOKEN, LBRACKET_TOKEN, NT_PROG_LOCAL_PARAM_NUM_TOKEN, RBRACKET_TOKEN}, + {"local", "", "", ""}}, + + /* 265: */ + {NT_PROG_ENV_PARAM_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_PROG_LOCAL_PARAM_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_PARAM_CONST_DECL_TOKEN, {NT_PARAM_CONST_SCALAR_DECL_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_CONST_DECL_TOKEN, {NT_PARAM_CONST_VECTOR_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_CONST_USE_TOKEN, {NT_PARAM_CONST_SCALAR_USE_TOKEN, NULL3}, NO_KW}, + + /* 270: */ + {NT_PARAM_CONST_USE_TOKEN, {NT_PARAM_CONST_VECTOR_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_CONST_SCALAR_DECL_TOKEN, {NT_SIGNED_FLOAT_CONSTANT_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_CONST_SCALAR_USE_TOKEN, {FLOAT_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_PARAM_CONST_VECTOR_TOKEN, {LBRACE_TOKEN, NT_SIGNED_FLOAT_CONSTANT_TOKEN, + NT_PARAM_CONST_VECTOR2_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_PARAM_CONST_VECTOR2_TOKEN,{RBRACE_TOKEN, NULL3}, NO_KW}, + + /* 275: */ + {NT_PARAM_CONST_VECTOR2_TOKEN, {COMMA_TOKEN, NT_SIGNED_FLOAT_CONSTANT_TOKEN, + NT_PARAM_CONST_VECTOR3_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_PARAM_CONST_VECTOR3_TOKEN, {RBRACE_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_CONST_VECTOR3_TOKEN, {COMMA_TOKEN, NT_SIGNED_FLOAT_CONSTANT_TOKEN, + NT_PARAM_CONST_VECTOR4_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_PARAM_CONST_VECTOR4_TOKEN, {RBRACE_TOKEN, NULL3}, NO_KW}, + {NT_PARAM_CONST_VECTOR4_TOKEN, {COMMA_TOKEN, NT_SIGNED_FLOAT_CONSTANT_TOKEN, + RBRACE_TOKEN, NULL_TOKEN}, NO_KW}, + + /* 280: */ + {NT_SIGNED_FLOAT_CONSTANT_TOKEN, {NT_OPTIONAL_SIGN_TOKEN, FLOAT_TOKEN, NULL2}, + {"", "-1", "", ""}}, + {NT_OPTIONAL_SIGN_TOKEN, {NULL4}, NO_KW}, + {NT_OPTIONAL_SIGN_TOKEN, {MINUS_TOKEN, NULL3}, NO_KW}, + {NT_OPTIONAL_SIGN_TOKEN, {PLUS_TOKEN, NULL3}, NO_KW}, + {NT_TEMP_STATEMENT_TOKEN, {TEMP_TOKEN, NT_VAR_NAME_LIST_TOKEN, NULL2}, + NO_KW}, + + /* 285: */ + {NT_ADDRESS_STATEMENT_TOKEN, {ADDRESS_TOKEN, NT_VAR_NAME_LIST_TOKEN, NULL2}, NO_KW}, + {NT_VAR_NAME_LIST_TOKEN, {NT_ESTABLISH_NAME_TOKEN, NULL3}, NO_KW}, + {NT_VAR_NAME_LIST_TOKEN, {NT_ESTABLISH_NAME_TOKEN, COMMA_TOKEN, NT_VAR_NAME_LIST_TOKEN, + NULL_TOKEN}, NO_KW}, + {NT_OUTPUT_STATEMENT_TOKEN, {OUTPUT_TOKEN, NT_ESTABLISH_NAME_TOKEN, EQUAL_TOKEN, + NT_RESULT_BINDING_TOKEN}, NO_KW}, + {NT_RESULT_BINDING_TOKEN, {RESULT_TOKEN, PERIOD_TOKEN, NT_RESULT_BINDING2_TOKEN, NULL_TOKEN}, + NO_KW}, + + /* 290: */ + {NT_RESULT_BINDING2_TOKEN, {ID_TOKEN, NULL3}, {"position", "", "", ""}}, + {NT_RESULT_BINDING2_TOKEN, {ID_TOKEN, NULL3}, {"fogcoord", "", "", ""}}, + {NT_RESULT_BINDING2_TOKEN, {ID_TOKEN, NULL3}, {"pointsize", "", "", ""}}, + {NT_RESULT_BINDING2_TOKEN, {NT_RESULT_COL_BINDING_TOKEN, NULL3}, NO_KW}, + {NT_RESULT_BINDING2_TOKEN, {ID_TOKEN, NT_OPT_TEX_COORD_NUM_TOKEN, NULL2}, + {"texcoord", "", "", ""}}, + + /* 295: */ + {NT_RESULT_COL_BINDING_TOKEN, {ID_TOKEN, NT_RESULT_COL_BINDING2_TOKEN, NULL2}, {"color", "", "", ""}}, + {NT_RESULT_COL_BINDING2_TOKEN, {NULL4}, NO_KW}, + {NT_RESULT_COL_BINDING2_TOKEN, {PERIOD_TOKEN, NT_RESULT_COL_BINDING3_TOKEN, NULL2}, NO_KW}, + {NT_RESULT_COL_BINDING3_TOKEN, {ID_TOKEN, NT_RESULT_COL_BINDING4_TOKEN, NULL2}, {"front", "", "", ""}}, + {NT_RESULT_COL_BINDING3_TOKEN, {ID_TOKEN, NT_RESULT_COL_BINDING4_TOKEN, NULL2}, {"back", "", "", ""}}, + + /* 300: */ + {NT_RESULT_COL_BINDING4_TOKEN, {NULL4}, NO_KW}, + {NT_RESULT_COL_BINDING4_TOKEN, {PERIOD_TOKEN, NT_RESULT_COL_BINDING5_TOKEN, NULL2}, NO_KW}, + {NT_RESULT_COL_BINDING5_TOKEN, {ID_TOKEN, NULL3}, {"primary", "", "", ""}}, + {NT_RESULT_COL_BINDING5_TOKEN, {ID_TOKEN, NULL3}, {"secondary", "", "", ""}}, + {NT_OPT_FACE_TYPE2_TOKEN, {ID_TOKEN, NULL3}, {"front", "", "", ""}}, + + /* 305: */ + {NT_OPT_FACE_TYPE2_TOKEN, {ID_TOKEN, NULL3}, {"back", "", "", ""}}, + {NT_OPT_COLOR_TYPE_TOKEN, {PERIOD_TOKEN, NT_OPT_COLOR_TYPE2_TOKEN, NULL2}, NO_KW}, + {NT_OPT_COLOR_TYPE_TOKEN, {NULL4}, NO_KW}, + {NT_OPT_COLOR_TYPE2_TOKEN, {ID_TOKEN, NULL3}, {"primary", "", "", ""}}, + {NT_OPT_COLOR_TYPE2_TOKEN, {ID_TOKEN, NULL3}, {"secondary", "", "", ""}}, + + /* 310: */ + {NT_OPT_TEX_COORD_NUM_TOKEN, {NULL4}, NO_KW}, + {NT_OPT_TEX_COORD_NUM_TOKEN, + {LBRACKET_TOKEN, NT_TEX_COORD_NUM_TOKEN, RBRACKET_TOKEN, NULL_TOKEN}, NO_KW}, + {NT_TEX_COORD_NUM_TOKEN, {INTEGER_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_ALIAS_STATEMENT_TOKEN, {ALIAS_TOKEN, NT_ESTABLISH_NAME_TOKEN, EQUAL_TOKEN, + NT_ESTABLISHED_NAME_TOKEN}, NO_KW}, + {NT_ESTABLISH_NAME_TOKEN, {ID_TOKEN, NULL3}, {"-1", "", "", ""}}, + + /* 315: */ + {NT_ESTABLISHED_NAME_TOKEN, {ID_TOKEN, NULL3}, {"-1", "", "", ""}}, + {NT_FOO_TOKEN, {NULL4}, NO_KW}, + {NT_SWIZZLE_SUFFIX_TOKEN, {PERIOD_TOKEN, NT_SWIZZLE_SUFFIX2_TOKEN, NULL2}, + NO_KW}, + {NT_SWIZZLE_SUFFIX2_TOKEN, {NT_COMPONENT_TOKEN, NULL3}, NO_KW}, + {NT_SWIZZLE_SUFFIX2_TOKEN, {NT_COMPONENT4_TOKEN, NULL3}, NO_KW}, +}; + +/* This is the look ahead table. See the look_ahead_table struct def for a description */ +look_ahead_table latab[] = { + {NT_PROGRAM_TOKEN, ABS_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, ADD_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, ADDRESS_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, ALIAS_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, ARL_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, ATTRIB_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, DP3_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, DP4_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, DPH_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, DST_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, END_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, EOF_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, EX2_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, EXP_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, FLR_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, FRC_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, LIT_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, LG2_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, LOG_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, MAD_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, MAX_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, MIN_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, MOV_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, MUL_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, OPTION_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, OUTPUT_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, PARAM_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, POW_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, RCP_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, RSQ_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, SGE_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, SLT_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, SUB_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, SWZ_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, XPD_TOKEN, "", 0}, + {NT_PROGRAM_TOKEN, TEMP_TOKEN, "", 0}, + + {NT_OPTION_SEQUENCE_TOKEN, ABS_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, ADD_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, ADDRESS_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, ALIAS_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, ARL_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, ATTRIB_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, DP3_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, DP4_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, DPH_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, DST_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, END_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, EX2_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, EXP_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, FLR_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, FRC_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, LIT_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, LG2_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, LOG_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, MAD_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, MAX_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, MIN_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, MOV_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, MUL_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, OPTION_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, OUTPUT_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, PARAM_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, POW_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, RCP_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, RSQ_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, SGE_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, SLT_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, SUB_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, SWZ_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, XPD_TOKEN, "", 1}, + {NT_OPTION_SEQUENCE_TOKEN, TEMP_TOKEN, "", 1}, + + {NT_OPTION_SEQUENCE2_TOKEN, OPTION_TOKEN, "", 2}, + + {NT_OPTION_SEQUENCE2_TOKEN, ABS_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, ADD_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, ADDRESS_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, ALIAS_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, ARL_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, ATTRIB_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, DP3_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, DP4_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, DPH_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, DST_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, END_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, EX2_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, EXP_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, FLR_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, FRC_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, LIT_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, LG2_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, LOG_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, MAD_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, MAX_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, MIN_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, MOV_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, MUL_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, OUTPUT_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, PARAM_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, POW_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, RCP_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, RSQ_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, SGE_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, SLT_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, SUB_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, SWZ_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, XPD_TOKEN, "", 3}, + {NT_OPTION_SEQUENCE2_TOKEN, TEMP_TOKEN, "", 3}, + + {NT_OPTION_TOKEN, OPTION_TOKEN, "", 4}, + + {NT_STATEMENT_SEQUENCE_TOKEN, ABS_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, ADD_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, ADDRESS_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, ALIAS_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, ARL_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, ATTRIB_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, DP3_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, DP4_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, DPH_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, DST_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, END_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, EX2_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, EXP_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, FLR_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, FRC_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, LIT_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, LG2_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, LOG_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, MAD_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, MAX_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, MIN_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, MOV_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, MUL_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, OUTPUT_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, PARAM_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, POW_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, RCP_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, RSQ_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, SGE_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, SLT_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, SUB_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, SWZ_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, XPD_TOKEN, "", 5}, + {NT_STATEMENT_SEQUENCE_TOKEN, TEMP_TOKEN, "", 5}, + + {NT_STATEMENT_SEQUENCE2_TOKEN, ABS_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, ADD_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, ADDRESS_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, ALIAS_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, ARL_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, ATTRIB_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, DP3_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, DP4_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, DPH_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, DST_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, EX2_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, EXP_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, FLR_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, FRC_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, LIT_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, LG2_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, LOG_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, MAD_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, MAX_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, MIN_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, MOV_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, MUL_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, OUTPUT_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, PARAM_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, POW_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, RCP_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, RSQ_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, SGE_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, SLT_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, SUB_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, SWZ_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, XPD_TOKEN, "", 6}, + {NT_STATEMENT_SEQUENCE2_TOKEN, TEMP_TOKEN, "", 6}, + + {NT_STATEMENT_SEQUENCE2_TOKEN, END_TOKEN, "", 7}, + + + {NT_STATEMENT_TOKEN, ABS_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, ADD_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, ARL_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, DP3_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, DP4_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, DPH_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, DST_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, EX2_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, EXP_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, FLR_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, FRC_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, LIT_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, LG2_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, LOG_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, MAD_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, MAX_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, MIN_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, MOV_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, MUL_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, POW_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, RCP_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, RSQ_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, SGE_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, SLT_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, SUB_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, SWZ_TOKEN, "", 8}, + {NT_STATEMENT_TOKEN, XPD_TOKEN, "", 8}, + + {NT_STATEMENT_TOKEN, ADDRESS_TOKEN, "", 9}, + {NT_STATEMENT_TOKEN, ALIAS_TOKEN, "", 9}, + {NT_STATEMENT_TOKEN, ATTRIB_TOKEN, "", 9}, + {NT_STATEMENT_TOKEN, OUTPUT_TOKEN, "", 9}, + {NT_STATEMENT_TOKEN, PARAM_TOKEN, "", 9}, + {NT_STATEMENT_TOKEN, TEMP_TOKEN, "", 9}, + + {NT_INSTRUCTION_TOKEN, ARL_TOKEN, "", 10}, + + {NT_INSTRUCTION_TOKEN, ABS_TOKEN, "", 11}, + {NT_INSTRUCTION_TOKEN, FLR_TOKEN, "", 11}, + {NT_INSTRUCTION_TOKEN, FRC_TOKEN, "", 11}, + {NT_INSTRUCTION_TOKEN, LIT_TOKEN, "", 11}, + {NT_INSTRUCTION_TOKEN, MOV_TOKEN, "", 11}, + + {NT_INSTRUCTION_TOKEN, EX2_TOKEN, "", 12}, + {NT_INSTRUCTION_TOKEN, EXP_TOKEN, "", 12}, + {NT_INSTRUCTION_TOKEN, LG2_TOKEN, "", 12}, + {NT_INSTRUCTION_TOKEN, LOG_TOKEN, "", 12}, + {NT_INSTRUCTION_TOKEN, RCP_TOKEN, "", 12}, + {NT_INSTRUCTION_TOKEN, RSQ_TOKEN, "", 12}, + + {NT_INSTRUCTION_TOKEN, POW_TOKEN, "", 13}, + + {NT_INSTRUCTION_TOKEN, ADD_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, DP3_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, DP4_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, DPH_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, DST_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, MAX_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, MIN_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, MUL_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, SGE_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, SLT_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, SUB_TOKEN, "", 14}, + {NT_INSTRUCTION_TOKEN, XPD_TOKEN, "", 14}, + + {NT_INSTRUCTION_TOKEN, MAD_TOKEN, "", 15}, + + {NT_INSTRUCTION_TOKEN, SWZ_TOKEN, "", 16}, + + {NT_ARL_INSTRUCTION_TOKEN, ARL_TOKEN, "", 17}, + + {NT_VECTOROP_INSTRUCTION_TOKEN, ABS_TOKEN, "", 18}, + {NT_VECTOROP_INSTRUCTION_TOKEN, FLR_TOKEN, "", 18}, + {NT_VECTOROP_INSTRUCTION_TOKEN, FRC_TOKEN, "", 18}, + {NT_VECTOROP_INSTRUCTION_TOKEN, LIT_TOKEN, "", 18}, + {NT_VECTOROP_INSTRUCTION_TOKEN, MOV_TOKEN, "", 18}, + + {NT_VECTOROP_TOKEN, ABS_TOKEN, "", 19}, + + {NT_VECTOROP_TOKEN, FLR_TOKEN, "", 20}, + + {NT_VECTOROP_TOKEN, FRC_TOKEN, "", 21}, + + {NT_VECTOROP_TOKEN, LIT_TOKEN, "", 22}, + + {NT_VECTOROP_TOKEN, MOV_TOKEN, "", 23}, + + {NT_SCALAROP_INSTRUCTION_TOKEN, EX2_TOKEN, "", 24}, + {NT_SCALAROP_INSTRUCTION_TOKEN, EXP_TOKEN, "", 24}, + {NT_SCALAROP_INSTRUCTION_TOKEN, LG2_TOKEN, "", 24}, + {NT_SCALAROP_INSTRUCTION_TOKEN, LOG_TOKEN, "", 24}, + {NT_SCALAROP_INSTRUCTION_TOKEN, RCP_TOKEN, "", 24}, + {NT_SCALAROP_INSTRUCTION_TOKEN, RSQ_TOKEN, "", 24}, + + {NT_SCALAROP_TOKEN, EX2_TOKEN, "", 25}, + + {NT_SCALAROP_TOKEN, EXP_TOKEN, "", 26}, + + {NT_SCALAROP_TOKEN, LG2_TOKEN, "", 27}, + + {NT_SCALAROP_TOKEN, LOG_TOKEN, "", 28}, + + {NT_SCALAROP_TOKEN, RCP_TOKEN, "", 29}, + + {NT_SCALAROP_TOKEN, RSQ_TOKEN, "", 30}, + + {NT_BINSCOP_INSTRUCTION_TOKEN, POW_TOKEN, "", 31}, + + {NT_BINSCOP_INSTRUCTION2_TOKEN, COMMA_TOKEN, "", 32}, + + {NT_BINSCOP_TOKEN, POW_TOKEN, "", 33}, + + {NT_BINOP_INSTRUCTION_TOKEN, ADD_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, DP3_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, DP4_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, DPH_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, DST_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, MAX_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, MIN_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, MUL_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, SGE_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, SLT_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, SUB_TOKEN, "", 34}, + {NT_BINOP_INSTRUCTION_TOKEN, XPD_TOKEN, "", 34}, + + {NT_BINOP_INSTRUCTION2_TOKEN, COMMA_TOKEN, "", 35}, + + {NT_BINOP_TOKEN, ADD_TOKEN, "", 36}, + {NT_BINOP_TOKEN, DP3_TOKEN, "", 37}, + {NT_BINOP_TOKEN, DP4_TOKEN, "", 38}, + {NT_BINOP_TOKEN, DPH_TOKEN, "", 39}, + {NT_BINOP_TOKEN, DST_TOKEN, "", 40}, + {NT_BINOP_TOKEN, MAX_TOKEN, "", 41}, + {NT_BINOP_TOKEN, MIN_TOKEN, "", 42}, + {NT_BINOP_TOKEN, MUL_TOKEN, "", 43}, + {NT_BINOP_TOKEN, SGE_TOKEN, "", 44}, + {NT_BINOP_TOKEN, SLT_TOKEN, "", 45}, + {NT_BINOP_TOKEN, SUB_TOKEN, "", 46}, + {NT_BINOP_TOKEN, XPD_TOKEN, "", 47}, + + {NT_TRIOP_INSTRUCTION_TOKEN, MAD_TOKEN, "", 48}, + {NT_TRIOP_INSTRUCTION2_TOKEN, COMMA_TOKEN, "", 49}, + {NT_TRIOP_INSTRUCTION3_TOKEN, COMMA_TOKEN, "", 50}, + + {NT_TRIOP_TOKEN, MAD_TOKEN, "", 51}, + {NT_SWZ_INSTRUCTION_TOKEN, SWZ_TOKEN, "", 52}, + {NT_SWZ_INSTRUCTION2_TOKEN, COMMA_TOKEN, "", 53}, + + {NT_SCALAR_SRC_REG_TOKEN, PLUS_TOKEN, "", 54}, + {NT_SCALAR_SRC_REG_TOKEN, MINUS_TOKEN, "", 54}, + {NT_SCALAR_SRC_REG_TOKEN, VERTEX_TOKEN, "", 54}, + {NT_SCALAR_SRC_REG_TOKEN, STATE_TOKEN, "", 54}, + {NT_SCALAR_SRC_REG_TOKEN, PROGRAM_TOKEN, "", 54}, + {NT_SCALAR_SRC_REG_TOKEN, LBRACE_TOKEN, "", 54}, + {NT_SCALAR_SRC_REG_TOKEN, FLOAT_TOKEN, "-1", 54}, + {NT_SCALAR_SRC_REG_TOKEN, INTEGER_TOKEN, "-1", 54}, + {NT_SCALAR_SRC_REG_TOKEN, ID_TOKEN, "-1", 54}, + + {NT_SWIZZLE_SRC_REG_TOKEN, PLUS_TOKEN, "", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, MINUS_TOKEN, "", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, VERTEX_TOKEN, "", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, STATE_TOKEN, "", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, PROGRAM_TOKEN, "", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, LBRACE_TOKEN, "", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, FLOAT_TOKEN, "-1", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, INTEGER_TOKEN, "-1", 55}, + {NT_SWIZZLE_SRC_REG_TOKEN, ID_TOKEN, "-1", 55}, + + {NT_MASKED_DST_REG_TOKEN, ID_TOKEN, "-1", 56}, + {NT_MASKED_DST_REG_TOKEN, RESULT_TOKEN, "", 56}, + {NT_MASKED_ADDR_REG_TOKEN, ID_TOKEN, "-1", 57}, + + {NT_EXTENDED_SWIZZLE_TOKEN, PLUS_TOKEN, "", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, MINUS_TOKEN, "", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, INTEGER_TOKEN, "0", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, INTEGER_TOKEN, "1", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, ID_TOKEN, "x", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, ID_TOKEN, "y", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, ID_TOKEN, "z", 58}, + {NT_EXTENDED_SWIZZLE_TOKEN, ID_TOKEN, "w", 58}, + + {NT_EXTENDED_SWIZZLE2_TOKEN, COMMA_TOKEN, "", 59}, + + {NT_EXT_SWIZ_COMP_TOKEN, PLUS_TOKEN, "", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, MINUS_TOKEN, "", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, INTEGER_TOKEN, "0", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, INTEGER_TOKEN, "1", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, ID_TOKEN, "x", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, ID_TOKEN, "y", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, ID_TOKEN, "z", 60}, + {NT_EXT_SWIZ_COMP_TOKEN, ID_TOKEN, "w", 60}, + + {NT_EXT_SWIZ_SEL_TOKEN, INTEGER_TOKEN, "0", 61}, + {NT_EXT_SWIZ_SEL_TOKEN, INTEGER_TOKEN, "1", 62}, + {NT_EXT_SWIZ_SEL_TOKEN, ID_TOKEN, "x", 63}, + {NT_EXT_SWIZ_SEL_TOKEN, ID_TOKEN, "y", 63}, + {NT_EXT_SWIZ_SEL_TOKEN, ID_TOKEN, "z", 63}, + {NT_EXT_SWIZ_SEL_TOKEN, ID_TOKEN, "w", 63}, + + /* Special case for 64 - 68 */ + + {NT_DST_REG_TOKEN, RESULT_TOKEN, "", 68}, + {NT_VERTEX_ATTRIB_REG_TOKEN, ID_TOKEN, "-1", 69}, + {NT_VERTEX_ATTRIB_REG_TOKEN, VERTEX_TOKEN, "", 70}, + {NT_TEMPORARY_REG_TOKEN, ID_TOKEN, "-1", 71}, + + /* Special case for 72 - 73 */ + + {NT_PROG_PARAM_REG_TOKEN, STATE_TOKEN, "", 74}, + {NT_PROG_PARAM_REG_TOKEN, PROGRAM_TOKEN, "", 74}, + {NT_PROG_PARAM_REG_TOKEN, LBRACE_TOKEN, "", 74}, + {NT_PROG_PARAM_REG_TOKEN, FLOAT_TOKEN, "-1", 74}, + + {NT_PROG_PARAM_SINGLE_TOKEN, ID_TOKEN, "-1", 75}, + {NT_PROG_PARAM_ARRAY_TOKEN, ID_TOKEN, "-1", 76}, + {NT_PROG_PARAM_ARRAY_MEM_TOKEN, INTEGER_TOKEN, "-1", 77}, + {NT_PROG_PARAM_ARRAY_MEM_TOKEN, ID_TOKEN, "-1", 78}, + {NT_PROG_PARAM_ARRAY_ABS_TOKEN, INTEGER_TOKEN, "-1", 79}, + {NT_PROG_PARAM_ARRAY_REL_TOKEN, ID_TOKEN, "-1", 80}, + + {NT_ADDR_REG_REL_OFFSET_TOKEN, RBRACKET_TOKEN, "", 81}, + {NT_ADDR_REG_REL_OFFSET_TOKEN, PLUS_TOKEN, "", 82}, + {NT_ADDR_REG_REL_OFFSET_TOKEN, MINUS_TOKEN, "", 83}, + {NT_ADDR_REG_POS_OFFSET_TOKEN, INTEGER_TOKEN, "-1", 84}, + {NT_ADDR_REG_NEG_OFFSET_TOKEN, INTEGER_TOKEN, "-1", 85}, + + + {NT_VERTEX_RESULT_REG_TOKEN, ID_TOKEN, "-1", 86}, + {NT_VERTEX_RESULT_REG_TOKEN, RESULT_TOKEN, "", 87}, + {NT_ADDR_REG_TOKEN, ID_TOKEN, "-1", 88}, + {NT_ADDR_COMPONENT_TOKEN, PERIOD_TOKEN, "", 89}, + {NT_ADDR_WRITE_MASK_TOKEN, PERIOD_TOKEN, "", 90}, + + {NT_SCALAR_SUFFIX_TOKEN, PERIOD_TOKEN, "", 91}, + + {NT_SWIZZLE_SUFFIX_TOKEN, COMMA_TOKEN, "", 92}, + {NT_SWIZZLE_SUFFIX_TOKEN, SEMICOLON_TOKEN, "", 92}, + {NT_SWIZZLE_SUFFIX_TOKEN, PERIOD_TOKEN, "", 317}, + + {NT_COMPONENT_TOKEN, ID_TOKEN, "x", 93}, + {NT_COMPONENT_TOKEN, ID_TOKEN, "y", 94}, + {NT_COMPONENT_TOKEN, ID_TOKEN, "z", 95}, + {NT_COMPONENT_TOKEN, ID_TOKEN, "w", 96}, + + {NT_OPTIONAL_MASK_TOKEN, PERIOD_TOKEN, "", 97}, + {NT_OPTIONAL_MASK_TOKEN, COMMA_TOKEN, "", 98}, + + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "x", 99}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "y", 100}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xy", 101}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "z", 102}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xz", 103}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "yz", 104}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xyz", 105}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "w", 106}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xw", 107}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "yw", 108}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xyw", 109}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "zw", 110}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xzw", 111}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "yzw", 112}, + {NT_OPTIONAL_MASK2_TOKEN, ID_TOKEN, "xyzw", 113}, + + + {NT_NAMING_STATEMENT_TOKEN, ATTRIB_TOKEN, "", 114}, + {NT_NAMING_STATEMENT_TOKEN, PARAM_TOKEN, "", 115}, + {NT_NAMING_STATEMENT_TOKEN, TEMP_TOKEN, "", 116}, + {NT_NAMING_STATEMENT_TOKEN, ADDRESS_TOKEN, "", 117}, + {NT_NAMING_STATEMENT_TOKEN, OUTPUT_TOKEN, "", 118}, + {NT_NAMING_STATEMENT_TOKEN, ALIAS_TOKEN, "", 119}, + + {NT_ATTRIB_STATEMENT_TOKEN, ATTRIB_TOKEN, "", 120}, + {NT_VTX_ATTRIB_BINDING_TOKEN, VERTEX_TOKEN, "", 121}, + + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "position", 122}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "weight", 123}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "normal", 124}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "color", 125}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "fogcoord", 126}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "texcoord", 127}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "matrixindex", 128}, + {NT_VTX_ATTRIB_ITEM_TOKEN, ID_TOKEN, "attrib", 129}, + + {NT_VTX_ATTRIB_NUM_TOKEN, INTEGER_TOKEN, "-1", 130}, + {NT_VTX_OPT_WEIGHT_NUM_TOKEN, SEMICOLON_TOKEN, "", 131}, + {NT_VTX_OPT_WEIGHT_NUM_TOKEN, COMMA_TOKEN, "", 131}, + {NT_VTX_OPT_WEIGHT_NUM_TOKEN, PERIOD_TOKEN, "", 131}, + {NT_VTX_OPT_WEIGHT_NUM_TOKEN, LBRACKET_TOKEN, "", 132}, + + {NT_VTX_WEIGHT_NUM_TOKEN, INTEGER_TOKEN, "-1", 133}, + {NT_PARAM_STATEMENT_TOKEN, PARAM_TOKEN, "", 134}, + {NT_PARAM_STATEMENT2_TOKEN, EQUAL_TOKEN, "", 135}, + {NT_PARAM_STATEMENT2_TOKEN, LBRACKET_TOKEN, "", 136}, + + {NT_OPT_ARRAY_SIZE_TOKEN, RBRACKET_TOKEN, "", 137}, + {NT_OPT_ARRAY_SIZE_TOKEN, INTEGER_TOKEN, "-1", 138}, + + {NT_PARAM_SINGLE_INIT_TOKEN, EQUAL_TOKEN, "", 139}, + {NT_PARAM_MULTIPLE_INIT_TOKEN, EQUAL_TOKEN, "", 140}, + + {NT_PARAM_MULT_INIT_LIST_TOKEN, STATE_TOKEN, "", 141}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, PROGRAM_TOKEN, "", 141}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, PLUS_TOKEN, "", 141}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, MINUS_TOKEN, "", 141}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, FLOAT_TOKEN, "-1", 141}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, INTEGER_TOKEN, "-1", 141}, + {NT_PARAM_MULT_INIT_LIST_TOKEN, LBRACE_TOKEN, "", 141}, + + + {NT_PARAM_MULT_INIT_LIST2_TOKEN, COMMA_TOKEN, "", 142}, + {NT_PARAM_MULT_INIT_LIST2_TOKEN, RBRACE_TOKEN, "", 143}, + + + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, STATE_TOKEN, "", 144}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, PROGRAM_TOKEN, "", 145}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, PLUS_TOKEN, "", 146}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, MINUS_TOKEN, "", 146}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, FLOAT_TOKEN, "-1", 146}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, INTEGER_TOKEN, "-1", 146}, + {NT_PARAM_SINGLE_ITEM_DECL_TOKEN, LBRACE_TOKEN, "", 146}, + + + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, STATE_TOKEN, "", 147}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, PROGRAM_TOKEN, "", 148}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, LBRACE_TOKEN, "", 149}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, FLOAT_TOKEN, "-1", 149}, + {NT_PARAM_SINGLE_ITEM_USE_TOKEN, INTEGER_TOKEN, "-1", 149}, + + {NT_PARAM_MULTIPLE_ITEM_TOKEN, STATE_TOKEN, "", 150}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, PROGRAM_TOKEN, "", 151}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, PLUS_TOKEN, "", 152}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, MINUS_TOKEN, "", 152}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, FLOAT_TOKEN, "-1", 152}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, INTEGER_TOKEN, "-1", 152}, + {NT_PARAM_MULTIPLE_ITEM_TOKEN, LBRACE_TOKEN, "", 152}, + + {NT_STATE_MULTIPLE_ITEM_TOKEN, STATE_TOKEN, "", 153}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "material", 154}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "light", 155}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "lightmodel", 156}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "lightprod", 157}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "texgen", 158}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "fog", 159}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "clip", 160}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "point", 161}, + {NT_STATE_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "matrix", 162}, + + {NT_FOO_TOKEN, PERIOD_TOKEN, "", 163}, + {NT_FOO_TOKEN, COMMA_TOKEN, "", 316}, + {NT_FOO_TOKEN, RBRACE_TOKEN, "", 316}, + {NT_FOO2_TOKEN, ID_TOKEN, "inverse", 164}, + {NT_FOO2_TOKEN, ID_TOKEN, "transpose", 164}, + {NT_FOO2_TOKEN, ID_TOKEN, "invtrans", 164}, + {NT_FOO2_TOKEN, ID_TOKEN, "row", 165}, + {NT_FOO3_TOKEN, COMMA_TOKEN, "", 166}, + {NT_FOO3_TOKEN, RBRACE_TOKEN, "", 166}, + {NT_FOO3_TOKEN, PERIOD_TOKEN, "", 167}, + + {NT_FOO35_TOKEN, INTEGER_TOKEN, "-1", 168}, + {NT_FOO4_TOKEN, RBRACKET_TOKEN, "", 169}, + {NT_FOO4_TOKEN, DOTDOT_TOKEN, "", 170}, + + {NT_STATE_SINGLE_ITEM_TOKEN, STATE_TOKEN, "", 171}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "material", 172}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "light", 173}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "lightmodel", 174}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "lightprod", 175}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "texgen", 176}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "fog", 177}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "clip", 178}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "point", 179}, + {NT_STATE_SINGLE_ITEM2_TOKEN, ID_TOKEN, "matrix", 180}, + + + {NT_STATE_MATERIAL_ITEM_TOKEN, ID_TOKEN, "material", 181}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, ID_TOKEN, "ambient", 182}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, ID_TOKEN, "diffuse", 182}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, ID_TOKEN, "specular", 182}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, ID_TOKEN, "emission", 182}, + {NT_STATE_MATERIAL_ITEM2_TOKEN, ID_TOKEN, "shininess", 182}, + + {NT_STATE_MATERIAL_ITEM2_TOKEN, PERIOD_TOKEN, "", 183}, + {NT_STATE_MAT_PROPERTY_TOKEN, ID_TOKEN, "ambient", 184}, + {NT_STATE_MAT_PROPERTY_TOKEN, ID_TOKEN, "diffuse", 185}, + {NT_STATE_MAT_PROPERTY_TOKEN, ID_TOKEN, "specular", 186}, + {NT_STATE_MAT_PROPERTY_TOKEN, ID_TOKEN, "emission", 187}, + {NT_STATE_MAT_PROPERTY_TOKEN, ID_TOKEN, "shininess", 188}, + + + {NT_STATE_LIGHT_ITEM_TOKEN, ID_TOKEN, "light", 189}, + {NT_STATE_LIGHT_ITEM2_TOKEN, RBRACKET_TOKEN, "", 190}, + + + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "ambient", 191}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "diffuse", 192}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "specular", 193}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "position", 194}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "attenuation", 195}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "spot", 196}, + {NT_STATE_LIGHT_PROPERTY_TOKEN, ID_TOKEN, "half", 197}, + + {NT_STATE_SPOT_PROPERTY_TOKEN, ID_TOKEN, "direction", 198}, + {NT_STATE_LIGHT_MODEL_ITEM_TOKEN, ID_TOKEN, "lightmodel", 199}, + + + {NT_STATE_LMOD_PROPERTY_TOKEN, PERIOD_TOKEN, "", 200}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, ID_TOKEN, "ambient", 201}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, ID_TOKEN, "scenecolor", 202}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, ID_TOKEN, "front", 203}, + {NT_STATE_LMOD_PROPERTY2_TOKEN, ID_TOKEN, "back", 203}, + + + {NT_STATE_LIGHT_PROD_ITEM_TOKEN, ID_TOKEN, "lightprod", 204}, + {NT_STATE_LIGHT_PROD_ITEM15_TOKEN, RBRACKET_TOKEN, "", 205}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, ID_TOKEN, "ambient", 206}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, ID_TOKEN, "diffuse", 206}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, ID_TOKEN, "specular", 206}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, ID_TOKEN, "front", 207}, + {NT_STATE_LIGHT_PROD_ITEM2_TOKEN, ID_TOKEN, "back", 207}, + + {NT_STATE_LPROD_PROPERTY_TOKEN, ID_TOKEN, "ambient", 208}, + {NT_STATE_LPROD_PROPERTY_TOKEN, ID_TOKEN, "diffuse", 209}, + {NT_STATE_LPROD_PROPERTY_TOKEN, ID_TOKEN, "specular", 210}, + + {NT_STATE_LIGHT_NUMBER_TOKEN, INTEGER_TOKEN, "-1", 211}, + {NT_STATE_TEX_GEN_ITEM_TOKEN, ID_TOKEN, "texgen", 212}, + {NT_STATE_TEX_GEN_ITEM2_TOKEN, PERIOD_TOKEN, "", 213}, + {NT_STATE_TEX_GEN_TYPE_TOKEN, ID_TOKEN, "eye", 214}, + {NT_STATE_TEX_GEN_TYPE_TOKEN, ID_TOKEN, "object", 215}, + + + {NT_STATE_TEX_GEN_COORD_TOKEN, ID_TOKEN, "s", 216}, + {NT_STATE_TEX_GEN_COORD_TOKEN, ID_TOKEN, "t", 217}, + {NT_STATE_TEX_GEN_COORD_TOKEN, ID_TOKEN, "r", 218}, + {NT_STATE_TEX_GEN_COORD_TOKEN, ID_TOKEN, "q", 219}, + + {NT_STATE_FOG_ITEM_TOKEN, ID_TOKEN, "fog", 220}, + + {NT_STATE_FOG_PROPERTY_TOKEN, ID_TOKEN, "color", 221}, + {NT_STATE_FOG_PROPERTY_TOKEN, ID_TOKEN, "params", 222}, + + {NT_STATE_CLIP_PLANE_ITEM_TOKEN, ID_TOKEN, "clip", 223}, + {NT_STATE_CLIP_PLANE_ITEM2_TOKEN, RBRACKET_TOKEN, "", 224}, + {NT_STATE_CLIP_PLANE_NUM_TOKEN, INTEGER_TOKEN, "-1", 225}, + {NT_STATE_POINT_ITEM_TOKEN, ID_TOKEN, "point", 226}, + {NT_STATE_POINT_PROPERTY_TOKEN, ID_TOKEN, "size", 227}, + {NT_STATE_POINT_PROPERTY_TOKEN, ID_TOKEN, "attenuation", 228}, + + + {NT_STATE_MATRIX_ROW_TOKEN, ID_TOKEN, "matrix", 229}, + {NT_STATE_MATRIX_ROW15_TOKEN, PERIOD_TOKEN, "", 230}, + {NT_STATE_MATRIX_ROW2_TOKEN, ID_TOKEN, "row", 231}, + {NT_STATE_MATRIX_ROW2_TOKEN, ID_TOKEN, "inverse", 232}, + {NT_STATE_MATRIX_ROW2_TOKEN, ID_TOKEN, "transpose", 232}, + {NT_STATE_MATRIX_ROW2_TOKEN, ID_TOKEN, "invtrans", 232}, + {NT_STATE_MATRIX_ROW3_TOKEN, LBRACKET_TOKEN, "", 233}, + + {NT_STATE_MAT_MODIFIER_TOKEN, ID_TOKEN, "inverse", 234}, + {NT_STATE_MAT_MODIFIER_TOKEN, ID_TOKEN, "transpose", 235}, + {NT_STATE_MAT_MODIFIER_TOKEN, ID_TOKEN, "invtrans", 236}, + {NT_STATE_MATRIX_ROW_NUM_TOKEN, INTEGER_TOKEN, "-1", 237}, + + + {NT_STATE_MATRIX_NAME_TOKEN, ID_TOKEN, "modelview", 238}, + {NT_STATE_MATRIX_NAME_TOKEN, ID_TOKEN, "projection", 239}, + {NT_STATE_MATRIX_NAME_TOKEN, ID_TOKEN, "mvp", 240}, + {NT_STATE_MATRIX_NAME_TOKEN, ID_TOKEN, "texture", 241}, + {NT_STATE_MATRIX_NAME_TOKEN, ID_TOKEN, "palette", 242}, + {NT_STATE_MATRIX_NAME_TOKEN, PROGRAM_TOKEN, "", 243}, + + {NT_STATE_OPT_MOD_MAT_NUM_TOKEN, PERIOD_TOKEN, "", 244}, + {NT_STATE_OPT_MOD_MAT_NUM_TOKEN, COMMA_TOKEN, "", 244}, + {NT_STATE_OPT_MOD_MAT_NUM_TOKEN, RBRACE_TOKEN, "", 244}, + {NT_STATE_OPT_MOD_MAT_NUM_TOKEN, LBRACKET_TOKEN, "", 245}, + + {NT_STATE_MOD_MAT_NUM_TOKEN, INTEGER_TOKEN, "-1", 246}, + {NT_STATE_PALETTE_MAT_NUM_TOKEN, INTEGER_TOKEN, "-1", 247}, + {NT_STATE_PROGRAM_MAT_NUM_TOKEN, INTEGER_TOKEN, "-1", 248}, + + {NT_PROGRAM_SINGLE_ITEM_TOKEN, PROGRAM_TOKEN, "", 249}, + {NT_PROGRAM_SINGLE_ITEM2_TOKEN, ID_TOKEN, "env", 250}, + {NT_PROGRAM_SINGLE_ITEM2_TOKEN, ID_TOKEN, "local", 251}, + + + {NT_PROGRAM_MULTIPLE_ITEM_TOKEN, PROGRAM_TOKEN, "", 252}, + {NT_PROGRAM_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "env", 253}, + {NT_PROGRAM_MULTIPLE_ITEM2_TOKEN, ID_TOKEN, "local", 254}, + {NT_PROG_ENV_PARAMS_TOKEN, ID_TOKEN, "env", 255}, + {NT_PROG_ENV_PARAM_NUMS_TOKEN, INTEGER_TOKEN, "-1", 256}, + {NT_PROG_ENV_PARAM_NUMS2_TOKEN, DOTDOT_TOKEN, "", 257}, + {NT_PROG_ENV_PARAM_NUMS2_TOKEN, RBRACKET_TOKEN, "", 258}, + {NT_PROG_ENV_PARAM_TOKEN, ID_TOKEN, "env", 259}, + + {NT_PROG_LOCAL_PARAMS_TOKEN, ID_TOKEN, "local", 260}, + {NT_PROG_LOCAL_PARAM_NUMS_TOKEN, INTEGER_TOKEN, "-1", 261}, + {NT_PROG_LOCAL_PARAM_NUMS2_TOKEN, DOTDOT_TOKEN, "", 262}, + {NT_PROG_LOCAL_PARAM_NUMS2_TOKEN, RBRACKET_TOKEN, "", 263}, + {NT_PROG_LOCAL_PARAM_TOKEN, ID_TOKEN, "local", 264}, + {NT_PROG_ENV_PARAM_NUM_TOKEN, INTEGER_TOKEN, "-1", 265}, + {NT_PROG_LOCAL_PARAM_NUM_TOKEN, INTEGER_TOKEN, "-1", 266}, + {NT_PARAM_CONST_DECL_TOKEN, PLUS_TOKEN, "", 267}, + {NT_PARAM_CONST_DECL_TOKEN, MINUS_TOKEN, "", 267}, + {NT_PARAM_CONST_DECL_TOKEN, FLOAT_TOKEN, "-1", 267}, + {NT_PARAM_CONST_DECL_TOKEN, INTEGER_TOKEN, "-1", 267}, + {NT_PARAM_CONST_DECL_TOKEN, LBRACE_TOKEN, "", 268}, + + {NT_PARAM_CONST_USE_TOKEN, FLOAT_TOKEN, "-1", 269}, + {NT_PARAM_CONST_USE_TOKEN, INTEGER_TOKEN, "-1", 269}, + {NT_PARAM_CONST_USE_TOKEN, LBRACE_TOKEN, "", 270}, + + + {NT_PARAM_CONST_SCALAR_DECL_TOKEN, PLUS_TOKEN, "", 271}, + {NT_PARAM_CONST_SCALAR_DECL_TOKEN, MINUS_TOKEN, "", 271}, + {NT_PARAM_CONST_SCALAR_DECL_TOKEN, FLOAT_TOKEN, "-1", 271}, + {NT_PARAM_CONST_SCALAR_DECL_TOKEN, INTEGER_TOKEN, "-1", 271}, + + {NT_PARAM_CONST_SCALAR_USE_TOKEN, FLOAT_TOKEN, "-1", 272}, + {NT_PARAM_CONST_SCALAR_USE_TOKEN, INTEGER_TOKEN, "-1", 272}, + {NT_PARAM_CONST_VECTOR_TOKEN, LBRACE_TOKEN, "", 273}, + {NT_PARAM_CONST_VECTOR2_TOKEN, RBRACE_TOKEN, "", 274}, + {NT_PARAM_CONST_VECTOR2_TOKEN, COMMA_TOKEN, "", 275}, + {NT_PARAM_CONST_VECTOR3_TOKEN, RBRACE_TOKEN, "", 276}, + {NT_PARAM_CONST_VECTOR3_TOKEN, COMMA_TOKEN, "", 277}, + {NT_PARAM_CONST_VECTOR4_TOKEN, RBRACE_TOKEN, "", 278}, + {NT_PARAM_CONST_VECTOR4_TOKEN, COMMA_TOKEN, "", 279}, + + {NT_SIGNED_FLOAT_CONSTANT_TOKEN, PLUS_TOKEN, "", 280}, + {NT_SIGNED_FLOAT_CONSTANT_TOKEN, MINUS_TOKEN, "", 280}, + {NT_SIGNED_FLOAT_CONSTANT_TOKEN, FLOAT_TOKEN, "-1", 280}, + {NT_SIGNED_FLOAT_CONSTANT_TOKEN, INTEGER_TOKEN, "-1", 280}, + + {NT_OPTIONAL_SIGN_TOKEN, FLOAT_TOKEN, "-1", 281}, + {NT_OPTIONAL_SIGN_TOKEN, INTEGER_TOKEN, "0", 281}, + {NT_OPTIONAL_SIGN_TOKEN, INTEGER_TOKEN, "1", 281}, + {NT_OPTIONAL_SIGN_TOKEN, INTEGER_TOKEN, "-1", 281}, + {NT_OPTIONAL_SIGN_TOKEN, ID_TOKEN, "-1", 281}, + {NT_OPTIONAL_SIGN_TOKEN, STATE_TOKEN, "", 281}, + {NT_OPTIONAL_SIGN_TOKEN, PROGRAM_TOKEN, "", 281}, + {NT_OPTIONAL_SIGN_TOKEN, VERTEX_TOKEN, "", 281}, + {NT_OPTIONAL_SIGN_TOKEN, LBRACE_TOKEN, "", 281}, + + + {NT_OPTIONAL_SIGN_TOKEN, MINUS_TOKEN, "", 282}, + {NT_OPTIONAL_SIGN_TOKEN, PLUS_TOKEN, "", 283}, + + {NT_TEMP_STATEMENT_TOKEN, TEMP_TOKEN, "", 284}, + {NT_ADDRESS_STATEMENT_TOKEN, ADDRESS_TOKEN, "", 285}, + + /* Special case 286-7 */ + + {NT_OUTPUT_STATEMENT_TOKEN, OUTPUT_TOKEN, "", 288}, + {NT_RESULT_BINDING_TOKEN, RESULT_TOKEN, "", 289}, + {NT_RESULT_BINDING2_TOKEN, ID_TOKEN, "position", 290}, + {NT_RESULT_BINDING2_TOKEN, ID_TOKEN, "fogcoord", 291}, + {NT_RESULT_BINDING2_TOKEN, ID_TOKEN, "pointsize", 292}, + {NT_RESULT_BINDING2_TOKEN, ID_TOKEN, "color", 293}, + {NT_RESULT_BINDING2_TOKEN, ID_TOKEN, "texcoord", 294}, + + {NT_RESULT_COL_BINDING_TOKEN, ID_TOKEN, "color", 295}, + + /* Special case 296-7 */ + + {NT_RESULT_COL_BINDING3_TOKEN, ID_TOKEN, "front", 298}, + {NT_RESULT_COL_BINDING3_TOKEN, ID_TOKEN, "back", 299}, + + /* Special case 300-301 */ + + {NT_RESULT_COL_BINDING5_TOKEN, ID_TOKEN, "primary", 302}, + {NT_RESULT_COL_BINDING5_TOKEN, ID_TOKEN, "secondary", 303}, + {NT_OPT_FACE_TYPE2_TOKEN, ID_TOKEN, "front", 304}, + {NT_OPT_FACE_TYPE2_TOKEN, ID_TOKEN, "back", 305}, + + /* Special case 306-7 */ + + {NT_OPT_COLOR_TYPE2_TOKEN, ID_TOKEN, "primary", 308}, + {NT_OPT_COLOR_TYPE2_TOKEN, ID_TOKEN, "secondary", 309}, + + {NT_OPT_TEX_COORD_NUM_TOKEN, PERIOD_TOKEN, "", 310}, + {NT_OPT_TEX_COORD_NUM_TOKEN, SEMICOLON_TOKEN, "", 310}, + {NT_OPT_TEX_COORD_NUM_TOKEN, COMMA_TOKEN, "", 310}, + {NT_OPT_TEX_COORD_NUM_TOKEN, RBRACE_TOKEN, "", 310}, + {NT_OPT_TEX_COORD_NUM_TOKEN, LBRACKET_TOKEN, "", 311}, + + {NT_TEX_COORD_NUM_TOKEN, INTEGER_TOKEN, "-1", 312}, + + /* Special case for 313 to get aliasing correct */ + + {NT_ESTABLISH_NAME_TOKEN, ID_TOKEN, "-1", 314}, + {NT_ESTABLISHED_NAME_TOKEN, ID_TOKEN, "-1", 315}, + + /* Special case for 318-9 */ +}; + +static GLint nprods = sizeof(ptab) / sizeof(prod_table); +static GLint nlas = sizeof(latab) / sizeof(look_ahead_table); + +/** + * This is a gigantic FSA to recognize the keywords put forth in the + * GL_ARB_vertex_program spec. + * + * All other tokens are deemed 'identifiers', and shoved into the + * identifier symbol table (as opposed to the GLint and GLfloat symbol tables) + * + * \param s The parse state + * \param token The next token seen is returned in this value + * \param token_attr The token attribute for the next token is returned here. This + * is the index into the approprate symbol table if token is INTEGER_TOKEN, + * FLOAT_TOKEN, or ID_TOKEN + * + * \return ARB_VP_ERROR on lex error, ARB_VP_SUCESS on sucess + */ +static GLint +get_next_token(parse_state * s, GLint * token, GLint * token_attr) +{ + GLubyte curr; + + while (s->start_pos < s->len) { + curr = s->str[s->curr_pos]; + + switch (s->curr_state) { + /* Default state */ + case STATE_BASE: + if (IS_WHITESPACE(curr)) { + s->start_pos++; + s->curr_pos++; + } + else { + if (IS_IDCHAR(curr)) { + switch (curr) { + case 'A': + ADV_TO_STATE(STATE_A); + break; + + case 'D': + ADV_TO_STATE(STATE_D); + break; + + case 'E': + ADV_TO_STATE(STATE_E); + break; + + case 'F': + ADV_TO_STATE(STATE_F); + break; + + case 'L': + ADV_TO_STATE(STATE_L); + break; + + case 'M': + ADV_TO_STATE(STATE_M); + break; + + case 'O': + ADV_TO_STATE(STATE_O); + break; + + case 'P': + ADV_TO_STATE(STATE_P); + break; + + case 'R': + ADV_TO_STATE(STATE_R); + break; + + case 'S': + ADV_TO_STATE(STATE_S); + break; + + case 'T': + ADV_TO_STATE(STATE_T); + break; + + case 'X': + ADV_TO_STATE(STATE_X); + break; + + case 'p': + ADV_TO_STATE(STATE_LC_P); + break; + + case 'r': + ADV_TO_STATE(STATE_LC_R); + break; + + case 's': + ADV_TO_STATE(STATE_LC_S); + break; + + case 'v': + ADV_TO_STATE(STATE_LC_V); + break; + + default: + s->curr_state = 1; + s->start_pos = s->curr_pos; + s->curr_pos++; + } + } + else if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N4); + } + else { + switch (curr) { + case '#': + ADV_TO_STATE(STATE_COMMENT); + break; + case ';': + ADV_AND_FINISH(SEMICOLON_TOKEN); + break; + case ',': + ADV_AND_FINISH(COMMA_TOKEN); + break; + case '+': + ADV_AND_FINISH(PLUS_TOKEN); + break; + case '-': + ADV_AND_FINISH(MINUS_TOKEN); + break; + case '[': + ADV_AND_FINISH(LBRACKET_TOKEN); + break; + case ']': + ADV_AND_FINISH(RBRACKET_TOKEN); + break; + case '{': + ADV_AND_FINISH(LBRACE_TOKEN); + break; + case '}': + ADV_AND_FINISH(RBRACE_TOKEN); + break; + case '=': + ADV_AND_FINISH(EQUAL_TOKEN); + break; + + case '.': + ADV_TO_STATE(STATE_N1); + break; + + default: + return ARB_VP_ERROR; + break; + } + } + } + break; + + + /* Main identifier state */ + case STATE_IDENT: + if (IS_CD(curr)) { + s->curr_pos++; + } + else { + *token = ID_TOKEN; + *token_attr = + id_table_add(&s->idents, s->str, s->start_pos, s->curr_pos); + + s->curr_state = 0; + s->start_pos = s->curr_pos; + return ARB_VP_SUCESS; + } + break; + + /* ----------------------------------------------------- + * Beginning of the A* keywords + */ + case STATE_A: + if (IS_CD(curr)) { + switch (curr) { + case 'B': + ADV_TO_STATE(STATE_AB); + break; + case 'D': + ADV_TO_STATE(STATE_AD); + break; + case 'L': + ADV_TO_STATE(STATE_AL); + break; + case 'R': + ADV_TO_STATE(STATE_AR); + break; + case 'T': + ADV_TO_STATE(STATE_AT); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_AB: + ADV_OR_FALLBACK('S', STATE_ABS); + break; + + case STATE_ABS: + FINISH_OR_FALLBACK(ABS_TOKEN); + break; + + case STATE_AD: + ADV_OR_FALLBACK('D', STATE_ADD); + break; + + case STATE_ADD: + if (curr == 'R') { + ADV_TO_STATE(STATE_ADDR); + } + else if (IS_CD(curr)) { + ADV_TO_STATE(STATE_IDENT); + } + else { + FINISH(ADD_TOKEN); + } + break; + + case STATE_ADDR: + ADV_OR_FALLBACK('E', STATE_ADDRE); + break; + + case STATE_ADDRE: + ADV_OR_FALLBACK('S', STATE_ADDRES); + break; + + case STATE_ADDRES: + ADV_OR_FALLBACK('S', STATE_ADDRESS); + break; + + case STATE_ADDRESS: + FINISH_OR_FALLBACK(ADDRESS_TOKEN); + break; + + case STATE_AL: + ADV_OR_FALLBACK('I', STATE_ALI); + break; + + case STATE_ALI: + ADV_OR_FALLBACK('A', STATE_ALIA); + break; + + case STATE_ALIA: + ADV_OR_FALLBACK('S', STATE_ALIAS); + break; + + case STATE_ALIAS: + FINISH_OR_FALLBACK(ALIAS_TOKEN); + break; + + case STATE_AR: + ADV_OR_FALLBACK('L', STATE_ARL); + break; + + case STATE_ARL: + FINISH_OR_FALLBACK(ARL_TOKEN); + break; + + case STATE_AT: + ADV_OR_FALLBACK('T', STATE_ATT); + break; + + case STATE_ATT: + ADV_OR_FALLBACK('R', STATE_ATTR); + break; + + case STATE_ATTR: + ADV_OR_FALLBACK('I', STATE_ATTRI); + break; + + case STATE_ATTRI: + ADV_OR_FALLBACK('B', STATE_ATTRIB); + break; + + case STATE_ATTRIB: + FINISH_OR_FALLBACK(ATTRIB_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the D* keywords + */ + case STATE_D: + if (IS_CD(curr)) { + switch (curr) { + case 'P': + ADV_TO_STATE(STATE_DP); + break; + case 'S': + ADV_TO_STATE(STATE_DS); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_DP: + if (IS_CD(curr)) { + switch (curr) { + case '3': + ADV_TO_STATE(STATE_DP3); + break; + case '4': + ADV_TO_STATE(STATE_DP4); + break; + case 'H': + ADV_TO_STATE(STATE_DPH); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_DP3: + FINISH_OR_FALLBACK(DP3_TOKEN); + break; + + case STATE_DP4: + FINISH_OR_FALLBACK(DP4_TOKEN); + break; + + case STATE_DPH: + FINISH_OR_FALLBACK(DPH_TOKEN); + break; + + case STATE_DS: + ADV_OR_FALLBACK('T', STATE_DST); + break; + + case STATE_DST: + FINISH_OR_FALLBACK(DST_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the E* keywords + */ + case STATE_E: + if (IS_CD(curr)) { + switch (curr) { + case 'N': + ADV_TO_STATE(STATE_EN); + break; + case 'X': + ADV_TO_STATE(STATE_EX); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_EN: + ADV_OR_FALLBACK('D', STATE_END); + break; + + case STATE_END: + FINISH_OR_FALLBACK(END_TOKEN); + break; + + case STATE_EX: + if (IS_CD(curr)) { + switch (curr) { + case '2': + ADV_TO_STATE(STATE_EX2); + break; + case 'P': + ADV_TO_STATE(STATE_EXP); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_EX2: + FINISH_OR_FALLBACK(EX2_TOKEN); + break; + + case STATE_EXP: + FINISH_OR_FALLBACK(EXP_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the F* keywords + */ + case STATE_F: + if (IS_CD(curr)) { + switch (curr) { + case 'L': + ADV_TO_STATE(STATE_FL); + break; + case 'R': + ADV_TO_STATE(STATE_FR); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_FL: + ADV_OR_FALLBACK('R', STATE_FLR); + break; + + case STATE_FLR: + FINISH_OR_FALLBACK(FLR_TOKEN); + break; + + case STATE_FR: + ADV_OR_FALLBACK('C', STATE_FRC); + break; + + case STATE_FRC: + FINISH_OR_FALLBACK(FRC_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the L* keywords + */ + case STATE_L: + if (IS_CD(curr)) { + switch (curr) { + case 'G': + ADV_TO_STATE(STATE_LG); + break; + case 'I': + ADV_TO_STATE(STATE_LI); + break; + case 'O': + ADV_TO_STATE(STATE_LO); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_LG: + ADV_OR_FALLBACK('2', STATE_LG2); + break; + + case STATE_LG2: + FINISH_OR_FALLBACK(LG2_TOKEN); + break; + + case STATE_LI: + ADV_OR_FALLBACK('T', STATE_LIT); + break; + + case STATE_LIT: + FINISH_OR_FALLBACK(LIT_TOKEN); + break; + + case STATE_LO: + ADV_OR_FALLBACK('G', STATE_LOG); + break; + + case STATE_LOG: + FINISH_OR_FALLBACK(LOG_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the M* keywords + */ + case STATE_M: + if (IS_CD(curr)) { + switch (curr) { + case 'A': + ADV_TO_STATE(STATE_MA); + break; + case 'I': + ADV_TO_STATE(STATE_MI); + break; + case 'O': + ADV_TO_STATE(STATE_MO); + break; + case 'U': + ADV_TO_STATE(STATE_MU); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_MA: + if (IS_CD(curr)) { + switch (curr) { + case 'D': + ADV_TO_STATE(STATE_MAD); + break; + case 'X': + ADV_TO_STATE(STATE_MAX); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_MAD: + FINISH_OR_FALLBACK(MAD_TOKEN); + break; + + case STATE_MAX: + FINISH_OR_FALLBACK(MAX_TOKEN); + break; + + case STATE_MI: + ADV_OR_FALLBACK('N', STATE_MIN); + break; + + case STATE_MIN: + FINISH_OR_FALLBACK(MIN_TOKEN); + break; + + case STATE_MO: + ADV_OR_FALLBACK('V', STATE_MOV); + break; + + case STATE_MOV: + FINISH_OR_FALLBACK(MOV_TOKEN); + break; + + case STATE_MU: + ADV_OR_FALLBACK('L', STATE_MUL); + break; + + case STATE_MUL: + FINISH_OR_FALLBACK(MUL_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the O* keywords + */ + case STATE_O: + if (IS_CD(curr)) { + switch (curr) { + case 'P': + ADV_TO_STATE(STATE_OP); + break; + case 'U': + ADV_TO_STATE(STATE_OU); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_OP: + ADV_OR_FALLBACK('T', STATE_OPT); + break; + + case STATE_OPT: + ADV_OR_FALLBACK('I', STATE_OPTI); + break; + + case STATE_OPTI: + ADV_OR_FALLBACK('O', STATE_OPTIO); + break; + + case STATE_OPTIO: + ADV_OR_FALLBACK('N', STATE_OPTION); + break; + + case STATE_OPTION: + FINISH_OR_FALLBACK(OPTION_TOKEN); + break; + + case STATE_OU: + ADV_OR_FALLBACK('T', STATE_OUT); + break; + + case STATE_OUT: + ADV_OR_FALLBACK('P', STATE_OUTP); + break; + + case STATE_OUTP: + ADV_OR_FALLBACK('U', STATE_OUTPU); + break; + + case STATE_OUTPU: + ADV_OR_FALLBACK('T', STATE_OUTPUT); + break; + + case STATE_OUTPUT: + FINISH_OR_FALLBACK(OUTPUT_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the P* keywords + */ + case STATE_P: + if (IS_CD(curr)) { + switch (curr) { + case 'A': + ADV_TO_STATE(STATE_PA); + break; + case 'O': + ADV_TO_STATE(STATE_PO); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_PA: + ADV_OR_FALLBACK('R', STATE_PAR); + break; + + case STATE_PAR: + ADV_OR_FALLBACK('A', STATE_PARA); + break; + + case STATE_PARA: + ADV_OR_FALLBACK('M', STATE_PARAM); + break; + + case STATE_PARAM: + FINISH_OR_FALLBACK(PARAM_TOKEN); + break; + + case STATE_PO: + ADV_OR_FALLBACK('W', STATE_POW); + break; + + case STATE_POW: + FINISH_OR_FALLBACK(POW_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the R* keywords + */ + case STATE_R: + if (IS_CD(curr)) { + switch (curr) { + case 'C': + ADV_TO_STATE(STATE_RC); + break; + case 'S': + ADV_TO_STATE(STATE_RS); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_RC: + ADV_OR_FALLBACK('P', STATE_RCP); + break; + + case STATE_RCP: + FINISH_OR_FALLBACK(RCP_TOKEN); + break; + + case STATE_RS: + ADV_OR_FALLBACK('Q', STATE_RSQ); + break; + + case STATE_RSQ: + FINISH_OR_FALLBACK(RSQ_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the S* keywords + */ + case STATE_S: + if (IS_CD(curr)) { + switch (curr) { + case 'G': + ADV_TO_STATE(STATE_SG); + break; + case 'L': + ADV_TO_STATE(STATE_SL); + break; + case 'U': + ADV_TO_STATE(STATE_SU); + break; + case 'W': + ADV_TO_STATE(STATE_SW); + break; + default: + ADV_TO_STATE(STATE_IDENT); + break; + } + } + else { + s->curr_state = 1; + } + break; + + case STATE_SG: + ADV_OR_FALLBACK('E', STATE_SGE); + break; + + case STATE_SGE: + FINISH_OR_FALLBACK(SGE_TOKEN); + break; + + case STATE_SL: + ADV_OR_FALLBACK('T', STATE_SLT); + break; + + case STATE_SLT: + FINISH_OR_FALLBACK(SLT_TOKEN); + break; + + case STATE_SU: + ADV_OR_FALLBACK('B', STATE_SUB); + break; + + case STATE_SUB: + FINISH_OR_FALLBACK(SUB_TOKEN); + break; + + case STATE_SW: + ADV_OR_FALLBACK('Z', STATE_SWZ); + break; + + case STATE_SWZ: + FINISH_OR_FALLBACK(SWZ_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the T* keywords + */ + case STATE_T: + ADV_OR_FALLBACK('E', STATE_TE); + break; + + case STATE_TE: + ADV_OR_FALLBACK('M', STATE_TEM); + break; + + case STATE_TEM: + ADV_OR_FALLBACK('P', STATE_TEMP); + break; + + case STATE_TEMP: + FINISH_OR_FALLBACK(TEMP_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the X* keywords + */ + case STATE_X: + ADV_OR_FALLBACK('P', STATE_XP); + break; + + case STATE_XP: + ADV_OR_FALLBACK('D', STATE_XPD); + break; + + case STATE_XPD: + FINISH_OR_FALLBACK(XPD_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the p* keywords + */ + case STATE_LC_P: + ADV_OR_FALLBACK('r', STATE_LC_PR); + break; + + case STATE_LC_PR: + ADV_OR_FALLBACK('o', STATE_LC_PRO); + break; + + case STATE_LC_PRO: + ADV_OR_FALLBACK('g', STATE_LC_PROG); + break; + + case STATE_LC_PROG: + ADV_OR_FALLBACK('r', STATE_LC_PROGR); + break; + + case STATE_LC_PROGR: + ADV_OR_FALLBACK('a', STATE_LC_PROGRA); + break; + + case STATE_LC_PROGRA: + ADV_OR_FALLBACK('m', STATE_LC_PROGRAM); + break; + + case STATE_LC_PROGRAM: + FINISH_OR_FALLBACK(PROGRAM_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the r* keywords + */ + case STATE_LC_R: + ADV_OR_FALLBACK('e', STATE_LC_RE); + break; + + case STATE_LC_RE: + ADV_OR_FALLBACK('s', STATE_LC_RES); + break; + + case STATE_LC_RES: + ADV_OR_FALLBACK('u', STATE_LC_RESU); + break; + + case STATE_LC_RESU: + ADV_OR_FALLBACK('l', STATE_LC_RESUL); + break; + + case STATE_LC_RESUL: + ADV_OR_FALLBACK('t', STATE_LC_RESULT); + break; + + case STATE_LC_RESULT: + FINISH_OR_FALLBACK(RESULT_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the s* keywords + */ + case STATE_LC_S: + ADV_OR_FALLBACK('t', STATE_LC_ST); + break; + + case STATE_LC_ST: + ADV_OR_FALLBACK('a', STATE_LC_STA); + break; + + case STATE_LC_STA: + ADV_OR_FALLBACK('t', STATE_LC_STAT); + break; + + case STATE_LC_STAT: + ADV_OR_FALLBACK('e', STATE_LC_STATE); + break; + + case STATE_LC_STATE: + FINISH_OR_FALLBACK(STATE_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the v* keywords + */ + case STATE_LC_V: + ADV_OR_FALLBACK('e', STATE_LC_VE); + break; + + case STATE_LC_VE: + ADV_OR_FALLBACK('r', STATE_LC_VER); + break; + + case STATE_LC_VER: + ADV_OR_FALLBACK('t', STATE_LC_VERT); + break; + + case STATE_LC_VERT: + ADV_OR_FALLBACK('e', STATE_LC_VERTE); + break; + + case STATE_LC_VERTE: + ADV_OR_FALLBACK('x', STATE_LC_VERTEX); + break; + + case STATE_LC_VERTEX: + FINISH_OR_FALLBACK(VERTEX_TOKEN); + break; + + /* ----------------------------------------------------- + * Beginning of the number & comment FSAs + */ + case STATE_N1: + if (curr == '.') { + ADV_TO_STATE(STATE_N2); + } + else if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N3); + } + else { + //ADV_AND_FINISH(PERIOD_TOKEN); + FINISH(PERIOD_TOKEN); + } + break; + + case STATE_N2: +#if 1 + //ADV_AND_FINISH(DOTDOT_TOKEN); + FINISH(DOTDOT_TOKEN); +#else + FINISH(PERIOD_TOKEN); +#endif + break; + + case STATE_N3: + if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N3); + } + else if ((curr == 'E') || (curr == 'e')) { + ADV_TO_STATE(STATE_N5); + } + else if (curr == '.') { + /* Blech! we have something like 1.. -> have to backup */ + s->curr_pos -= 1; + *token_attr = + int_table_add(&s->ints, s->str, s->start_pos, s->curr_pos); + FINISH(INTEGER_TOKEN); + } + else { + *token_attr = + float_table_add(&s->floats, s->str, s->start_pos, s->curr_pos); + //ADV_AND_FINISH(FLOAT_TOKEN); + FINISH(FLOAT_TOKEN); + } + break; + + case STATE_N4: + if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N4); + } + else if ((curr == 'E') || (curr == 'e')) { + ADV_TO_STATE(STATE_N5); + } + else if (curr == '.') { + ADV_TO_STATE(STATE_N3); + } + else { + *token_attr = + int_table_add(&s->ints, s->str, s->start_pos, s->curr_pos); + //ADV_AND_FINISH(INTEGER_TOKEN); + FINISH(INTEGER_TOKEN); + } + break; + + case STATE_N5: + if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N6); + } + else if ((curr == '+') || (curr == '-')) { + ADV_TO_STATE(STATE_N7) + } + else { + return ARB_VP_ERROR; + } + break; + + case STATE_N6: + if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N6); + } + else { + *token_attr = + float_table_add(&s->floats, s->str, s->start_pos, s->curr_pos); + //ADV_AND_FINISH(FLOAT_TOKEN); + FINISH(FLOAT_TOKEN); + } + break; + + case STATE_N7: + if (IS_DIGIT(curr)) { + ADV_TO_STATE(STATE_N6); + } + else { + return ARB_VP_ERROR; + } + + break; + + case STATE_COMMENT: + if ((curr == '\n') || (curr == '\r')) { + s->start_pos = s->curr_pos + 1; + s->curr_pos++; + s->curr_state = 0; + } + else { + ADV_TO_STATE(STATE_COMMENT); + } + } + } + + *token = EOF_TOKEN; + return ARB_VP_SUCESS; +} + +/** + * This does the same as get_next_token(), but it does not advance the + * position pointers (Err, rather it does, but then it resets them) + * + * \param s The parse state + * \param token The next token seen is returned in this value + * \param token_attr The token attribute for the next token is returned here. This + * is the index into the approprate symbol table if token is INTEGER_TOKEN, + * FLOAT_TOKEN, or ID_TOKEN + * \param how_many How many tokens to peek ahead + * + * \return ARB_VP_ERROR on lex error, ARB_VP_SUCESS on sucess + */ +static GLint +peek_next_token(parse_state * s, GLint * token, GLint * token_attr, + GLint how_many) +{ + GLint tmp_state = s->curr_state; + GLint tmp_sp = s->start_pos; + GLint tmp_cp = s->curr_pos; + GLint a, retval; + + for (a = 0; a < how_many; a++) { + retval = get_next_token(s, token, token_attr); + + if (retval == ARB_VP_ERROR) + return retval; + } + + s->curr_state = tmp_state; + s->start_pos = tmp_sp; + s->curr_pos = tmp_cp; + + return retval; +} + +/** + * Print out the value of a token + */ +static void +debug_token(parse_state * state, GLint t, GLint ta) +{ + switch (t) { + case EOF_TOKEN: + printf("EOF\n"); + break; + case ID_TOKEN: + printf("|%s| ", state->idents.data[ta]); + break; + case INTEGER_TOKEN: + printf("|%d| ", state->ints.data[ta]); + break; + case FLOAT_TOKEN: + printf("|%f| ", state->floats.data[ta]); + break; + + case ABS_TOKEN: + printf("ABS "); + break; + case ADD_TOKEN: + printf("ADD "); + break; + case ADDRESS_TOKEN: + printf("ADDRESS "); + break; + case ALIAS_TOKEN: + printf("ALIAS "); + break; + case ARL_TOKEN: + printf("ARL "); + break; + case ATTRIB_TOKEN: + printf("ATTRIB "); + break; + + case DP3_TOKEN: + printf("DP3 "); + break; + case DP4_TOKEN: + printf("DP4 "); + break; + case DPH_TOKEN: + printf("DPH "); + break; + case DST_TOKEN: + printf("DST "); + break; + + case END_TOKEN: + printf("END "); + break; + case EX2_TOKEN: + printf("EX2 "); + break; + case EXP_TOKEN: + printf("EXP "); + break; + + case FLR_TOKEN: + printf("FLR "); + break; + case FRC_TOKEN: + printf("FRC "); + break; + + case LG2_TOKEN: + printf("LG2 "); + break; + case LIT_TOKEN: + printf("LIT "); + break; + case LOG_TOKEN: + printf("LOG "); + break; + + case MAD_TOKEN: + printf("MAD "); + break; + case MAX_TOKEN: + printf("MAX "); + break; + case MIN_TOKEN: + printf("MIN "); + break; + case MOV_TOKEN: + printf("MOV "); + break; + case MUL_TOKEN: + printf("MUL "); + break; + + case OPTION_TOKEN: + printf("OPTION "); + break; + case OUTPUT_TOKEN: + printf("OUTPUT "); + break; + + case PARAM_TOKEN: + printf("PARAM "); + break; + case POW_TOKEN: + printf("POW "); + break; + + case RCP_TOKEN: + printf("RCP "); + break; + case RSQ_TOKEN: + printf("RSQ "); + break; + + case SGE_TOKEN: + printf("SGE "); + break; + case SLT_TOKEN: + printf("SLT "); + break; + case SUB_TOKEN: + printf("SUB "); + break; + case SWZ_TOKEN: + printf("SWZ "); + break; + + case TEMP_TOKEN: + printf("TEMP "); + break; + + case XPD_TOKEN: + printf("XPD "); + break; + + case SEMICOLON_TOKEN: + printf("; "); + break; + case COMMA_TOKEN: + printf(", "); + break; + case PLUS_TOKEN: + printf("+ "); + break; + case MINUS_TOKEN: + printf("- "); + break; + case PERIOD_TOKEN: + printf(". "); + break; + case DOTDOT_TOKEN: + printf(".. "); + break; + case LBRACKET_TOKEN: + printf("[ "); + break; + case RBRACKET_TOKEN: + printf("] "); + break; + case LBRACE_TOKEN: + printf("{ "); + break; + case RBRACE_TOKEN: + printf("} "); + break; + case EQUAL_TOKEN: + printf("= "); + break; + + case PROGRAM_TOKEN: + printf("program "); + break; + case RESULT_TOKEN: + printf("result "); + break; + case STATE_TOKEN: + printf("state "); + break; + case VERTEX_TOKEN: + printf("vertex "); + break; + default: + printf("Unknown token type %d\n", t); + } +} + +/** + * Setup the state used by the parser / lex + * + * \param str The program string, with the !!ARBvp1.0 token stripped off + * \param len The lenght of the given string + * + * \return A parse_state struct to keep track of all the things we need while parsing + */ +static parse_state * +parse_state_init(GLubyte * str, GLint len) +{ + parse_state *s = (parse_state *) _mesa_malloc(sizeof(parse_state)); + + s->str = _mesa_strdup(str); + s->len = len; + s->curr_pos = 0; + s->start_pos = 0; + + s->curr_state = 0; + + s->idents.len = 0; + s->idents.data = NULL; + + s->ints.len = 0; + s->ints.data = NULL; + + s->floats.len = 0; + s->floats.data = NULL; + printf("%s\n", s->str); + + s->binds.len = 0; + s->binds.type = NULL; + s->binds.offset = NULL; + s->binds.row = NULL; + s->binds.consts = NULL; + + s->arrays.len = 0; + s->arrays.num_elements = NULL; + s->arrays.data = NULL; + + s->stack_head = NULL; + s->stack_free_list = NULL; + + s->pt_head = NULL; + + return s; +} + +/** + * This frees all the things we hold while parsing. + * + * \param s The struct created by parse_state_init() + */ +static void +parse_state_cleanup(parse_state * s) +{ + GLint a; + token_list *tl, *next; + + /* Free our copy of the string [Mesa has its own] */ + _mesa_free(s->str); + + /* Free all the tables ident, int, float, bind, mat */ + _mesa_free(s->idents.type); + _mesa_free(s->idents.attr); + for (a = 0; a < s->idents.len; a++) + _mesa_free(s->idents.data[a]); + + _mesa_free(s->ints.data); + _mesa_free(s->floats.data); + + _mesa_free(s->arrays.num_elements); + for (a = 0; a < s->arrays.len; a++) + _mesa_free(s->arrays.data[a]); + + _mesa_free(s->binds.type); + _mesa_free(s->binds.offset); + _mesa_free(s->binds.row); + _mesa_free(s->binds.num_rows); + _mesa_free(s->binds.reg_num); +#if 0 + for (a = 0; a < s->binds.len; a++) { + printf("6: %d/%d\n", a, s->binds.len - 1); + _mesa_free(s->binds.consts[a]); + } +#endif + + /* Free the stack */ + tl = s->stack_head; + while (tl) { + next = tl->next; + free(tl); + tl = next; + } + tl = s->stack_free_list; + while (tl) { + next = tl->next; + free(tl); + tl = next; + } + printf("freed stack free list\n"); + +#if 0 + /* Free the parse tree */ + parse_tree_free_children(s->pt_head); + printf("freed parse_tree\n"); +#endif + free(s); + printf("freed state\n"); +} + +/** + * Alloc a new node for a parse tree. + * + * \return An empty node to fill and stick into the parse tree + */ +static parse_tree_node * +parse_tree_node_init(void) +{ + GLint a; + parse_tree_node *pt; + + pt = (parse_tree_node *) _mesa_malloc(sizeof(parse_tree_node)); + pt->tok = -1; + pt->tok_attr = -1; + pt->is_terminal = 0; + pt->prod_applied = -1; + + for (a = 0; a < 4; a++) + pt->children[a] = NULL; + + return pt; +} + +/** + * We maintain a stack of nonterminals used for predictive parsing. To keep + * from thrashing malloc/free, we keep a free list of token_list structs + * to be used for this stack. This function is called to refill the free + * list, when we try to grab a new token_list struct, and find that there are none + * available + * + * \param s The parse state + */ +static void +_fill_free_list(parse_state * s) +{ + GLint a; + token_list *tl; + + if (s->stack_free_list) + return; + + for (a = 0; a < 20; a++) { + tl = (token_list *) _mesa_malloc(sizeof(token_list)); + + tl->next = s->stack_free_list; + s->stack_free_list = tl; + } +} + +/** + * Peek at the head of the nonterminal stack, + * + * \param s The parse state + * \param token Return for the nonterminal token on the top of the stack + * \param token_attr Return for the the token attribute on the top of the stack + * + * \return ARB_VP_ERROR on an empty stack [not necessarily a bad thing], else ARB_VP_SUCESS + */ +static GLint +_stack_peek(parse_state * s, GLint * token, GLint * token_attr) +{ + if (!s->stack_head) { + fprintf(stderr, "ACK! Empty stack on peek!\n"); + return ARB_VP_ERROR; + } + + *token = s->stack_head->tok; + *token_attr = s->stack_head->tok_attr; + + return ARB_VP_SUCESS; +} + +/** + * Remove the token at the head of the nonterminal stack + * \param s The parse state + * \param token Return for the nonterminal token on the top of the stack + * \param token_attr Return for the the token attribute on the top of the stack + * \param ptn Return for a pointer to the place in the parse tree where + * the token lives + * + * \return ARB_VP_ERROR on an empty stack [not necessarily a bad thing], else ARB_VP_SUCESS + */ +static GLint +_stack_pop(parse_state * s, GLint * token, GLint * token_attr, + parse_tree_node ** ptn) +{ + token_list *tl; + + if (!s->stack_head) { + fprintf(stderr, "ACK! Empty stack!\n"); + return ARB_VP_ERROR; + } + + *token = s->stack_head->tok; + *token_attr = s->stack_head->tok_attr; + if (ptn) + *ptn = s->stack_head->pt; + tl = s->stack_head; + + s->stack_head = tl->next; + tl->next = s->stack_free_list; + s->stack_free_list = tl; + + return ARB_VP_SUCESS; +} + +/** + * Put a token, its attribute, and the the parse tree node where the token is stored, onto + * the parse stack. + * + * \param s The parse state + * \param token Return for the nonterminal token on the top of the stack + * \param token_attr Return for the the token attribute on the top of the stack + * \param ptn Return for a pointer to the place in the parse tree where + * the token lives + * + * \return ARB_VP_ERROR on out of memory while allocing more storage for the stack, + * else ARB_VP_SUCESS + */ +static GLint +_stack_push(parse_state * s, GLint token, GLint token_attr, + parse_tree_node * ptn) +{ + token_list *tl; + + if (!s->stack_free_list) { + _fill_free_list(s); + if (!s->stack_free_list) { + fprintf(stderr, "ACK! Error filling stack free list\n"); + return ARB_VP_ERROR; + } + } + + tl = s->stack_free_list; + + s->stack_free_list = tl->next; + + tl->tok = token; + tl->tok_attr = token_attr; + tl->pt = ptn; + tl->next = s->stack_head; + + s->stack_head = tl; + + return ARB_VP_SUCESS; +} + +/** + * Allocate a new entry in the array table + * + * \param tab The array table to add a new element too + * + * \return The index into the array table where the new element is. + */ +static GLint +array_table_new(array_table * tab) +{ + GLint idx; + if (tab->len == 0) { + tab->num_elements = (GLint *) _mesa_malloc(sizeof(GLint)); + tab->data = (GLint **) _mesa_malloc(sizeof(GLint *)); + idx = 0; + } + else { + tab->num_elements = + (GLint *) _mesa_realloc(tab->num_elements, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + tab->data = + (GLint **) _mesa_realloc(tab->data, tab->len * sizeof(GLint *), + (tab->len + 1) * sizeof(GLint *)); + idx = tab->len; + } + + tab->len++; + tab->num_elements[idx] = 0; + tab->data[idx] = NULL; + + return idx; +} + +/** + * Add a new element to a array in a array table + * + * \param tab The array table + * \param idx The index into the array table of the array we want to append an item onto + * \param data The program parameter that goes into the idx-th array + */ +static void +array_table_add_data(array_table * tab, GLint idx, GLint data) +{ + if ((idx < 0) || (idx >= tab->len)) { + printf("Bad matrix index %d!\n", idx); + return; + } + + if (tab->data[idx] == NULL) { + tab->data[idx] = (GLint *) _mesa_malloc(sizeof(GLint)); + } + else { + tab->data[idx] = + (GLint *) _mesa_realloc(tab->data[idx], + tab->num_elements[idx] * sizeof(GLint), + (tab->num_elements[idx] + + 1) * sizeof(GLint)); + } + + tab->data[idx][tab->num_elements[idx]] = data; + tab->num_elements[idx]++; +} + + +/** + * This adds a new entry into the binding table. + * + * \param tab The binding table + * \param type The type of the state + * \param offset For matrix bindings, e.g. MATRIXROWS_MODELVIEW, this gives the matrix number. + * For PROGRAM_ENV_* and PROGRAM_LOCAL_* bindings, this gives the number of the first parameter + * + * \param row For MATRIXROWS bindings, this is the first row in the matrix we're bound to + * \param nrows For MATRIXROWS bindings, this is the number of rows of the matrix we have. + * For PROGRAM_ENV/LOCAL bindings, this is the number of parameters in the array we're bound to + * \param values For CONSTANT bindings, these are the constant values we're bound to + * \return The index into the binding table where this state is bound + */ +static GLint +binding_table_add(binding_table * tab, GLint type, GLint offset, GLint row, + GLint nrows, GLfloat * values) +{ + GLint key, a; + + key = tab->len; + + /* test for existance */ + for (a = 0; a < tab->len; a++) { + if ((tab->type[a] == type) && (tab->offset[a] == offset) + && (tab->row[a] == row) && (tab->num_rows[a] == nrows) && + (fabs(tab->consts[a][0] - values[0]) < .0001) && + (fabs(tab->consts[a][1] - values[1]) < .0001) && + (fabs(tab->consts[a][2] - values[2]) < .0001) && + (fabs(tab->consts[a][3] - values[3]) < .0001)) + return a; + } + + if (tab->len == 0) { + tab->type = (GLint *) _mesa_malloc(sizeof(GLint)); + tab->offset = (GLint *) _mesa_malloc(sizeof(GLint)); + tab->row = (GLint *) _mesa_malloc(sizeof(GLint)); + tab->num_rows = (GLint *) _mesa_malloc(sizeof(GLint)); + tab->consts = (GLfloat **) _mesa_malloc(sizeof(GLfloat *)); + tab->consts[0] = (GLfloat *) _mesa_malloc(4 * sizeof(GLfloat)); + tab->reg_num = (GLint *) _mesa_malloc(sizeof(GLint)); + } + else { + tab->type = + (GLint *) _mesa_realloc(tab->type, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + tab->offset = + (GLint *) _mesa_realloc(tab->offset, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + tab->row = + (GLint *) _mesa_realloc(tab->row, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + tab->num_rows = + (GLint *) _mesa_realloc(tab->num_rows, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + tab->consts = + (GLfloat **) _mesa_realloc(tab->consts, tab->len * sizeof(GLfloat), + (tab->len + 1) * sizeof(GLfloat *)); + tab->consts[tab->len] = (GLfloat *) _mesa_malloc(4 * sizeof(GLfloat)); + tab->reg_num = + (GLint *) _mesa_realloc(tab->reg_num, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + } + + tab->type[key] = type; + tab->offset[key] = offset; + tab->row[key] = row; //key; + tab->num_rows[key] = nrows; + tab->reg_num[key] = 0; + _mesa_memcpy(tab->consts[key], values, 4 * sizeof(GLfloat)); + tab->len++; + + return key; +} + +/** + * Given a string and a start/end point, add a string into the float + * symbol table (and convert it into a float) + * + * If we already have this GLfloat in the table, don't bother + * adding another, just return the key to the existing one + * + * \param tab The float table + * \param str The string containing the float + * \param start The starting position of the float in str + * \param end The ending position of the float in str + * + * \return The index of the float, after we insert it, in the float table + */ +static GLint +float_table_add(float_table * tab, GLubyte * str, GLint start, GLint end) +{ + GLint key, a; + GLubyte *newstr; + + key = tab->len; + + newstr = (GLubyte *) _mesa_malloc(end - start + 2); + _mesa_memset(newstr, 0, end - start + 2); + _mesa_memcpy(newstr, str + start, end - start); + + /* test for existance */ + for (a = 0; a < tab->len; a++) { + if (tab->data[a] == atof(newstr)) { + _mesa_free(newstr); + return a; + } + } + + if (tab->len == 0) { + tab->data = (GLdouble *) _mesa_malloc(sizeof(GLdouble)); + } + else { + tab->data = + (GLdouble *) _mesa_realloc(tab->data, tab->len * sizeof(GLdouble), + (tab->len + 1) * sizeof(GLdouble)); + } + + tab->data[key] = atof(newstr); + tab->len++; + + _mesa_free(newstr); + return key; +} + +/** + * Given a string and a start/end point, add a string into the int + * symbol table (and convert it into a int) + * + * If we already have this int in the table, don't bother + * adding another, just return the key to the existing one + * + * \param tab The int table + * \param str The string containing the int + * \param start The starting position of the int in str + * \param end The ending position of the int in str + * + * \return The index of the int, after we insert it, in the int table + */ +static GLint +int_table_add(int_table * tab, GLubyte * str, GLint start, GLint end) +{ + GLint key, a; + GLubyte *newstr; + + key = tab->len; + + newstr = (GLubyte *) _mesa_malloc(end - start + 2); + _mesa_memset(newstr, 0, end - start + 2); + _mesa_memcpy(newstr, str + start, end - start); + + for (a = 0; a < tab->len; a++) { + if (tab->data[a] == _mesa_atoi(newstr)) { + _mesa_free(newstr); + return a; + } + } + + if (tab->len == 0) { + tab->data = (GLint *) _mesa_malloc(sizeof(GLint)); + } + else { + tab->data = + (GLint *) _mesa_realloc(tab->data, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + } + + tab->data[key] = _mesa_atoi(newstr); + tab->len++; + + _mesa_free(newstr); + return key; +} + +/** + * Insert an identifier into the identifier symbol table + * + * If we already have this id in the table, don't bother + * adding another, just return the key to the existing one + * + * If we already have this id in the table, and it has been + * initialized to an ALIAS, return what the alias points + * to, not the alias var + * + * \param tab The ID table + * \param str The string containing the id + * \param start The position in str where the id begins + * \param end The position in str where the id ends + * + * \return either: + * 1) The index into the id table where the id is + * 2) The index into the id table where the alias of id, if we already have id + * in the table, and it has been initialized to type ALIAS + */ +static GLint +id_table_add(id_table * tab, GLubyte * str, GLint start, GLint end) +{ + GLint key, a; + GLubyte *newstr; + + key = tab->len; + + if (tab->len == 0) { + tab->data = (GLubyte **) _mesa_malloc(sizeof(GLubyte *)); + tab->type = (GLint *) _mesa_malloc(sizeof(GLint)); + tab->attr = (GLint *) _mesa_malloc(sizeof(GLint)); + } + else { + tab->data = + (GLubyte **) _mesa_realloc(tab->data, tab->len * sizeof(GLubyte *), + (tab->len + 1) * sizeof(GLubyte *)); + tab->type = + (GLint *) _mesa_realloc(tab->type, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + tab->attr = + (GLint *) _mesa_realloc(tab->attr, tab->len * sizeof(GLint), + (tab->len + 1) * sizeof(GLint)); + } + + //tab->type[key] = TYPE_NONE; + + newstr = (GLubyte *) _mesa_malloc((end - start + 2) * sizeof(GLubyte)); + _mesa_memset(newstr, 0, end - start + 2); + _mesa_memcpy(newstr, str + start, end - start); + + for (a = 0; a < tab->len; a++) { + /* aha! we found it in the table */ + if (!_mesa_strcmp(tab->data[a], newstr)) { + _mesa_free(newstr); + + key = a; + while ((tab->type[key] == TYPE_ALIAS) && (tab->attr[key] != -1)) { + printf("----------- %s is an alias, renaming to %s\n", + tab->data[key], tab->data[tab->attr[key]]); + key = tab->attr[key]; + } + + return key; + } + } + + /* oh, we really have a new id */ + tab->data[key] = newstr; + tab->type[key] = TYPE_NONE; + tab->attr[key] = -1; + tab->len++; + + return key; +} + +//#define SHOW_STEPS 1 + + +/** + * Apply the specified production number to the parse state. This handles + * looking at the production table and sticking new tokens onto the + * parse stack. + * + * It also handles the construction of the parse tree + * + * \param s The parse state + * \param num The production number to apply [the idx in the production table] + * + */ +static void +apply_production(parse_state * s, int num) +{ + GLint a, str_key, stack_tok, stack_tok_attr; + GLint tok, nnptr = 0; + parse_tree_node *ptn; + parse_tree_node *pt_ptr_new[4]; + + _stack_pop(s, &stack_tok, &stack_tok_attr, &ptn); + /*printf("apply prod %d\n", num); */ + + ptn->prod_applied = num; + for (a = 3; a >= 0; a--) { + str_key = 0; + tok = ptab[num].rhs[a]; + + if (tok == NULL_TOKEN) + continue; + + /* If we are pushing an identifier or a number, we need to translate the string literal + * in the production table into an entry in the approprate symbol table + */ + if (tok == ID_TOKEN) { + str_key = + id_table_add(&s->idents, ptab[num].key[a], 0, + strlen(ptab[num].key[a])); + } + else if (tok == INTEGER_TOKEN) { + str_key = + int_table_add(&s->ints, ptab[num].key[a], 0, + strlen(ptab[num].key[a])); + } + else if (tok == FLOAT_TOKEN) { + str_key = + float_table_add(&s->floats, ptab[num].key[a], 0, + strlen(ptab[num].key[a])); + } + + /* "-1" is a wildcard flag, accept any id/float/int */ + if ((!_mesa_strcmp(ptab[num].key[a], "-1")) && + ((tok == FLOAT_TOKEN) || (tok == INTEGER_TOKEN) + || (tok == ID_TOKEN))) { + pt_ptr_new[nnptr] = parse_tree_node_init(); + pt_ptr_new[nnptr]->is_terminal = 0; + pt_ptr_new[nnptr]->tok = tok; + pt_ptr_new[nnptr]->tok_attr = str_key; + nnptr++; + _stack_push(s, ptab[num].rhs[a], str_key, pt_ptr_new[nnptr - 1]); + } + else if (tok >= NT_PROGRAM_TOKEN) { + pt_ptr_new[nnptr] = parse_tree_node_init(); + pt_ptr_new[nnptr]->is_terminal = 0; + pt_ptr_new[nnptr]->tok = tok; + nnptr++; + _stack_push(s, ptab[num].rhs[a], str_key, pt_ptr_new[nnptr - 1]); + } + else + _stack_push(s, ptab[num].rhs[a], str_key, NULL); + } + + tok = 0; + if (ptn) { + /*printf("%x %d:[%x %x %x %x]\n", ptn, nnptr, pt_ptr_new[0], pt_ptr_new[1], pt_ptr_new[2], pt_ptr_new[3]); */ + + for (a = nnptr - 1; a >= 0; a--) { + ptn->children[tok] = pt_ptr_new[a]; + /*printf("%x->children[%d] = %x\n", ptn, tok, pt_ptr_new[a]); */ + tok++; + } + } +} + +/** + * Here we initialize a bunch of variables to a given type (e.g. TEMP). + * + * We stick the variable type into the 0-th element in the var_queue array, followed by var_queue_size + * indicies into the identifier table which designate the variables we are to init. + * + * \param s The parse state + * \param var_queue The queue of variables to initialize. The first element in the array is variable + * type. It is followed by var_queue_size indicies into the identifier table + * who we are supposed to init to type var_queue[0]. + * \param var_queue_size The number of variables listed in var_queue[]. + * + * \return ARB_VP_ERROR if we have already initilized a variable in var_queue, otherwise + * ARB_VP_SUCESS + */ +static GLint +init_vars(parse_state * s, GLint * var_queue, GLint var_queue_size) +{ + GLint a; + + a = 1; + while (a < var_queue_size) { + /* Make sure we haven't already init'd this var. This will + * catch multiple definations of the same symbol + */ + if (s->idents.type[var_queue[a]] != TYPE_NONE) { + printf("%s already init'd! (%d)\n", s->idents.data[var_queue[a]], + s->idents.type[var_queue[a]]); + return ARB_VP_ERROR; + } + + s->idents.type[var_queue[a]] = var_queue[0]; + s->idents.attr[var_queue[a]] = -1; + a++; + } + + return ARB_VP_SUCESS; +} + +/** + * The main parsing loop. This applies productions and builds the parse tree. + * + * \param s The parse state + * + * \return ARB_VP_ERROR on a parse error, else ARB_VP_SUCESS + */ +static GLint +parse(parse_state * s) +{ + GLint input_tok, input_tok_attr; + GLint stack_tok, stack_tok_attr; + GLint peek_tok, peek_tok_attr, ret; + GLint idx, str_key; + GLint var_queue_size = 0; + GLint *var_queue; + parse_tree_node *ptn, *ptn2; + + /* This should be MAX_VAR + 1 */ + var_queue = (GLint *) _mesa_malloc(1000 * sizeof(int)); + + s->stack_head = NULL; + + /* init the system by pushing the start symbol onto the stack */ + ptn = parse_tree_node_init(); + ptn->is_terminal = 0; + ptn->tok = NT_PROGRAM_TOKEN; + s->pt_head = ptn; + _stack_push(s, NT_PROGRAM_TOKEN, 0, ptn); + + /* and get the first token */ + if (get_next_token(s, &input_tok, &input_tok_attr) == ARB_VP_ERROR) { + fprintf(stderr, "LEX ERROR!!\n"); + return ARB_VP_ERROR; + } + + while (1) { + GLint la, is_nonterm; + + /* If the stack is empty, and we've eaten all the input, we're done */ + if ((_stack_peek(s, &stack_tok, &stack_tok_attr) == ARB_VP_ERROR) && + (input_tok == EOF_TOKEN)) + break; + +#ifdef SHOW_STEPS + printf("stack: %d input: ", stack_tok); + debug_token(s, input_tok, input_tok_attr); + printf("\n"); +#endif + + /* We [may] have a non-terminal on top of the stack, apply + * productions! + */ + switch (stack_tok) { + /* Special case non-terminals */ + + /* productions 64-66 */ + case NT_SRC_REG_TOKEN: + if ((input_tok == VERTEX_TOKEN) || + ((input_tok == ID_TOKEN) + && (s->idents.type[input_tok_attr] == TYPE_ATTRIB))) { + apply_production(s, 64); + } + else + if ((input_tok == ID_TOKEN) + && (s->idents.type[input_tok_attr] == TYPE_TEMP)) { + apply_production(s, 65); + } + else + if ((input_tok == STATE_TOKEN) || + (input_tok == PROGRAM_TOKEN) || + (input_tok == LBRACE_TOKEN) || + (input_tok == FLOAT_TOKEN) || + (input_tok == INTEGER_TOKEN) || + ((input_tok == ID_TOKEN) + && (s->idents.type[input_tok_attr] == TYPE_PARAM_SINGLE)) + || ((input_tok == ID_TOKEN) + && (s->idents.type[input_tok_attr] == + TYPE_PARAM_ARRAY))) { + apply_production(s, 66); + } + else { + return ARB_VP_ERROR; + } + break; + + /* productions 67-68 */ + case NT_DST_REG_TOKEN: + /* We can only write to result.*, TEMP vars, or OUTPUT vars */ + if (input_tok == RESULT_TOKEN) { + apply_production(s, 68); + } + else if (input_tok == ID_TOKEN) { + if (s->idents.type[input_tok_attr] == TYPE_TEMP) { + apply_production(s, 67); + } + else if (s->idents.type[input_tok_attr] == TYPE_OUTPUT) { + apply_production(s, 68); + } + else { + return ARB_VP_ERROR; + } + } + else { + return ARB_VP_ERROR; + } + break; + + /* productions 72-4 */ + case NT_PROG_PARAM_REG_TOKEN: + if ((input_tok == ID_TOKEN) + && (s->idents.type[input_tok_attr] == TYPE_PARAM_SINGLE)) { + apply_production(s, 72); + } + else + if ((input_tok == ID_TOKEN) + && (s->idents.type[input_tok_attr] == TYPE_PARAM_ARRAY)) { + apply_production(s, 73); + } + else + if ((input_tok == STATE_TOKEN) || + (input_tok == PROGRAM_TOKEN) || + (input_tok == FLOAT_TOKEN) || + (input_tok == INTEGER_TOKEN) || (input_tok == LBRACE_TOKEN)) { + apply_production(s, 74); + } + else { + return ARB_VP_ERROR; + } + break; + + /* productions 286-7 */ + case NT_VAR_NAME_LIST_TOKEN: + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + + var_queue[var_queue_size] = input_tok_attr; + var_queue_size++; + + if ((ret == ARB_VP_ERROR) || (peek_tok != COMMA_TOKEN)) { + apply_production(s, 286); + + /* Dump the var_queue & assign types */ + if (init_vars(s, var_queue, var_queue_size) == ARB_VP_ERROR) + return ARB_VP_ERROR; + } + else { + apply_production(s, 287); + } + break; + + /* productions 296-7 */ + case NT_RESULT_COL_BINDING2_TOKEN: + if ((input_tok == SEMICOLON_TOKEN) || (input_tok == COMMA_TOKEN)) { + apply_production(s, 296); + } + else if (input_tok == PERIOD_TOKEN) { + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + if ((peek_tok == ID_TOKEN) && + ((!_mesa_strcmp(s->idents.data[peek_tok_attr], "back")) || + (!_mesa_strcmp(s->idents.data[peek_tok_attr], "front")))) { + apply_production(s, 297); + } + else { + apply_production(s, 296); + } + } + else { + return ARB_VP_ERROR; + } + break; + + /* productions 300-1 */ + case NT_RESULT_COL_BINDING4_TOKEN: + if ((input_tok == SEMICOLON_TOKEN) || (input_tok == COMMA_TOKEN)) { + apply_production(s, 300); + } + else if (input_tok == PERIOD_TOKEN) { + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + if ((ret == ARB_VP_SUCESS) && (peek_tok == ID_TOKEN) && + ((!_mesa_strcmp(s->idents.data[peek_tok_attr], "primary")) || + (!_mesa_strcmp(s->idents.data[peek_tok_attr], "secondary")))) + { + apply_production(s, 301); + } + else { + apply_production(s, 300); + } + } + else { + return ARB_VP_ERROR; + } + break; + + /* productions 306-7 */ + case NT_OPT_COLOR_TYPE_TOKEN: + if ((input_tok == SEMICOLON_TOKEN) || (input_tok == COMMA_TOKEN)) { + apply_production(s, 307); + } + else if (input_tok == PERIOD_TOKEN) { + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + if ((ret == ARB_VP_SUCESS) && (peek_tok == ID_TOKEN) && + ((!_mesa_strcmp(s->idents.data[peek_tok_attr], "primary")) || + (!_mesa_strcmp(s->idents.data[peek_tok_attr], "secondary")))) + { + apply_production(s, 306); + } + else { + apply_production(s, 307); + } + } + else { + return ARB_VP_ERROR; + } + break; + + /* production 313 -- Do this so we can mangle IDs as they are + * added into the ID table for the lex + */ + case NT_ALIAS_STATEMENT_TOKEN: + if (input_tok == ALIAS_TOKEN) { + GLint alias_to; + + apply_production(s, 313); + + /* stack ALIAS */ + var_queue_size = 1; + var_queue[0] = TYPE_ALIAS; + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + var_queue[var_queue_size] = peek_tok_attr; + var_queue_size++; + + if (init_vars(s, var_queue, var_queue_size) == ARB_VP_ERROR) + return ARB_VP_ERROR; + + /* Now, peek ahead and see what we are aliasing _to_ */ + alias_to = peek_tok_attr; + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 3); + if (ret == ARB_VP_SUCESS) { + s->idents.attr[alias_to] = peek_tok_attr; + } + else + return ARB_VP_ERROR; + } + else { + return ARB_VP_ERROR; + } + break; + + /* productions 314 (ESTABLISH_NAME) duplicates are caught by the ID symbol table */ + + /* productions 315 */ + case NT_ESTABLISHED_NAME_TOKEN: + if (input_tok == ID_TOKEN) { + if (s->idents.type[input_tok_attr] == TYPE_NONE) { + printf("Trying to use variable %s before initializing!\n", + s->idents.data[input_tok_attr]); + return ARB_VP_ERROR; + } + else { + apply_production(s, 315); + } + } + else { + return ARB_VP_ERROR; + } + break; + + + /* productions 318-9 */ + case NT_SWIZZLE_SUFFIX2_TOKEN: + if (strlen(s->idents.data[input_tok_attr]) == 1) { + apply_production(s, 318); + } + else if (strlen(s->idents.data[input_tok_attr]) == 4) { + apply_production(s, 319); + } + else { + return ARB_VP_ERROR; + } + break; + + /* 4-component swizzle mask -- this is a total hack */ +#define IS_SWZ_CMP(foo) ((foo == 'x') || (foo == 'y') || (foo == 'z') || (foo == 'w')) + case NT_COMPONENT4_TOKEN: + { + GLubyte *str = s->idents.data[input_tok_attr]; + + if (IS_SWZ_CMP(str[0]) && IS_SWZ_CMP(str[1]) && IS_SWZ_CMP(str[2]) + && IS_SWZ_CMP(str[3])) { + _stack_pop(s, &stack_tok, &stack_tok_attr, &ptn); +// _stack_push(s, input_tok, input_tok_attr, NULL); + + ptn2 = parse_tree_node_init(); + ptn2->tok = input_tok; + ptn2->tok_attr = input_tok_attr; + ptn2->is_terminal = 1; + ptn->children[0] = ptn2; + _stack_push(s, input_tok, input_tok_attr, ptn2); + } + else { + return ARB_VP_ERROR; + } + } + break; + + /* Handle general non-terminals using tables, and terminals */ + default: + is_nonterm = 0; + for (la = 0; la < nlas; la++) { + if (latab[la].lhs != stack_tok) + continue; + + if (latab[la].la != input_tok) + continue; + + if (input_tok == ID_TOKEN) { + str_key = + id_table_add(&s->idents, latab[la].la_kw, 0, + strlen(latab[la].la_kw)); + if ((str_key != input_tok_attr) + && (_mesa_strcmp(latab[la].la_kw, "-1"))) + continue; + } + else if (input_tok == INTEGER_TOKEN) { + if ((s->ints.data[input_tok_attr] != + _mesa_atoi(latab[la].la_kw)) + && (_mesa_atoi(latab[la].la_kw) != -1)) { + continue; + } + } + else if (input_tok == FLOAT_TOKEN) { + if ((s->floats.data[input_tok_attr] != atof(latab[la].la_kw)) + && (atof(latab[la].la_kw) != -1)) + continue; + } + idx = latab[la].prod_idx; + + /* Here we stack identifiers onto the var_queue */ + switch (idx) { + /* setup ATTRIB */ + case 120: + var_queue_size = 1; + var_queue[0] = TYPE_ATTRIB; + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + var_queue[var_queue_size] = peek_tok_attr; + var_queue_size++; + + if (init_vars(s, var_queue, var_queue_size) == ARB_VP_ERROR) + return ARB_VP_ERROR; + break; + + /* stack PARAM */ + case 134: + var_queue_size = 1; + var_queue[0] = TYPE_PARAM; + + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + var_queue[var_queue_size] = peek_tok_attr; + var_queue_size++; + + break; + + case 135: + var_queue[0] = TYPE_PARAM_SINGLE; + + if (init_vars(s, var_queue, var_queue_size) == ARB_VP_ERROR) + return ARB_VP_ERROR; + break; + + case 136: + var_queue[0] = TYPE_PARAM_ARRAY; + + if (init_vars(s, var_queue, var_queue_size) == ARB_VP_ERROR) + return ARB_VP_ERROR; + break; + + /* stack TEMP */ + case 284: + var_queue_size = 1; + var_queue[0] = TYPE_TEMP; + break; + + /* stack ADDRESS */ + case 285: + var_queue_size = 1; + var_queue[0] = TYPE_ADDRESS; + break; + + /* stack OUTPUT */ + case 288: + var_queue_size = 1; + var_queue[0] = TYPE_OUTPUT; + ret = peek_next_token(s, &peek_tok, &peek_tok_attr, 1); + var_queue[var_queue_size] = peek_tok_attr; + var_queue_size++; + + if (init_vars(s, var_queue, var_queue_size) == ARB_VP_ERROR) + return ARB_VP_ERROR; + break; + + + /* stack opts for varNameList -- see above */ + + } + + /* finally.. we match! apply the production */ + if ((idx < 0) || (idx >= nprods)) { + fprintf(stderr, + "Prod IDX of %d in look ahead table [%d] is horked!\n", + idx, la); + exit(1); + } + + apply_production(s, idx); + is_nonterm = 1; + break; + } + + if (!is_nonterm) { + if ((stack_tok == EOF_TOKEN) && (s->stack_head == NULL)) + return ARB_VP_SUCESS; + + if ((input_tok == stack_tok) || + ((stack_tok == FLOAT_TOKEN) + && (input_tok == INTEGER_TOKEN))) { + /* XXX: Need to check values for int/id/GLfloat tokens here -- yes! */ + + _stack_pop(s, &stack_tok, &stack_tok_attr, &ptn); + if ((ptn) + && ((stack_tok == FLOAT_TOKEN) + || (stack_tok == INTEGER_TOKEN) + || (stack_tok == ID_TOKEN))) { + ptn->is_terminal = 1; + ptn->tok = input_tok; + ptn->tok_attr = input_tok_attr; + } + + if (get_next_token(s, &input_tok, &input_tok_attr) == + ARB_VP_ERROR) { + fprintf(stderr, "PARSE ERROR!!\n"); + return ARB_VP_ERROR; + } + } + else { + fprintf(stderr, "PARSE ERROR!\n"); + return ARB_VP_ERROR; + } + } + break; + } + } + + return ARB_VP_SUCESS; + + +} + +/** + * Print out the parse tree from a given point. Just for debugging. + * + * \param s The parse state + * \param ptn The root to start printing from + */ +static void +print_parse_tree(parse_state * s, parse_tree_node * ptn) +{ + GLint a; + + /* If we're terminal, prGLint and exit */ + if (ptn->is_terminal) { + debug_token(s, ptn->tok, ptn->tok_attr); + printf("\n"); + return; + } + + /* Else, recurse on all our children */ + for (a = 0; a < 4; a++) { + if (!ptn->children[a]) + return; + + print_parse_tree(s, ptn->children[a]); + } +} + +/** + * Free all of the children of a given parse tree node. + * + * \param ptn The root node whose children we recursively free + */ +static void +parse_tree_free_children(parse_tree_node * ptn) +{ + GLint a; + + if (!ptn) + return; + if (!ptn->children[0]) + return; + + for (a = 0; a < 4; a++) { + if (ptn->children[a]) { + parse_tree_free_children(ptn->children[a]); + _mesa_free(ptn->children[a]); + ptn->children[a] = NULL; + } + } +} + +/** + * Given the name of a matrix, and a modifier, expand into a binding type. + * + * names: 0 -- modelview + * 1 -- projection + * 2 -- mvp + * 3 -- texture + * 4 -- palette + * 5 -- program + * + * mods: 0 -- normal + * 1 -- inverse + * 2 -- invtrans + * 3 -- transpose + * + * \param name The number of the matrix type + * \param mod The number of the matrix modifier + * + * \return The binding state corresponding to name & mod + */ +static GLint +name_and_mod_to_matrixrows(GLint name, GLint mod) +{ + switch (name) { + case 0: /* modelview */ + switch (mod) { + case 0: + return MATRIXROWS_MODELVIEW; + case 1: + return MATRIXROWS_MODELVIEW_INVERSE; + case 2: + return MATRIXROWS_MODELVIEW_INVTRANS; + case 3: + return MATRIXROWS_MODELVIEW_TRANSPOSE; + } + break; + case 1: /* projection */ + switch (mod) { + case 0: + return MATRIXROWS_PROJECTION; + case 1: + return MATRIXROWS_PROJECTION_INVERSE; + case 2: + return MATRIXROWS_PROJECTION_INVTRANS; + case 3: + return MATRIXROWS_PROJECTION_TRANSPOSE; + } + + break; + case 2: /* mvp */ + switch (mod) { + case 0: + return MATRIXROWS_MVP; + case 1: + return MATRIXROWS_MVP_INVERSE; + case 2: + return MATRIXROWS_MVP_INVTRANS; + case 3: + return MATRIXROWS_MVP_TRANSPOSE; + } + + break; + case 3: /* texture */ + switch (mod) { + case 0: + return MATRIXROWS_TEXTURE; + case 1: + return MATRIXROWS_TEXTURE_INVERSE; + case 2: + return MATRIXROWS_TEXTURE_INVTRANS; + case 3: + return MATRIXROWS_TEXTURE_TRANSPOSE; + } + break; + case 4: /* palette */ + switch (mod) { + case 0: + return MATRIXROWS_PALETTE; + case 1: + return MATRIXROWS_PALETTE_INVERSE; + case 2: + return MATRIXROWS_PALETTE_INVTRANS; + case 3: + return MATRIXROWS_PALETTE_TRANSPOSE; + } + break; + case 5: /* program */ + switch (mod) { + case 0: + return MATRIXROWS_PROGRAM; + case 1: + return MATRIXROWS_PROGRAM_INVERSE; + case 2: + return MATRIXROWS_PROGRAM_INVTRANS; + case 3: + return MATRIXROWS_PROGRAM_TRANSPOSE; + } + break; + } + + return 0; +} + +/** + * This takes a node in the parse tree for an OPTIONAL_MASK token + * being derived into a write mask for a register. + * + * This will expand the production number into a 4-component + * write mask. + * + * \param mask_node The parse tree node for the optional_mask non-termina + * \param mask 4-component write mask + */ +static void +get_optional_mask(parse_tree_node * mask_node, GLint * mask) +{ + if (mask_node->prod_applied == 97) { + switch (mask_node->children[0]->prod_applied) { + case 99: /* x */ + mask[0] = 1; + mask[1] = 0; + mask[2] = 0; + mask[3] = 0; + break; + + case 100: /* y */ + mask[0] = 0; + mask[1] = 1; + mask[2] = 0; + mask[3] = 0; + break; + + case 101: /* xy */ + mask[0] = 1; + mask[1] = 1; + mask[2] = 0; + mask[3] = 0; + break; + + case 102: /* z */ + mask[0] = 0; + mask[1] = 0; + mask[2] = 1; + mask[3] = 0; + break; + + case 103: /* xz */ + mask[0] = 1; + mask[1] = 0; + mask[2] = 1; + mask[3] = 0; + break; + + case 104: /* yz */ + mask[0] = 0; + mask[1] = 1; + mask[2] = 1; + mask[3] = 0; + break; + + case 105: /* xyz */ + mask[0] = 1; + mask[1] = 1; + mask[2] = 1; + mask[3] = 0; + break; + + case 106: /* w */ + mask[0] = 0; + mask[1] = 0; + mask[2] = 0; + mask[3] = 1; + break; + + case 107: /* xw */ + mask[0] = 1; + mask[1] = 0; + mask[2] = 0; + mask[3] = 1; + break; + + case 108: /* yw */ + mask[0] = 0; + mask[1] = 1; + mask[2] = 0; + mask[3] = 1; + break; + + case 109: /* xyw */ + mask[0] = 1; + mask[1] = 1; + mask[2] = 0; + mask[3] = 1; + break; + + case 110: /* zw */ + mask[0] = 0; + mask[1] = 0; + mask[2] = 1; + mask[3] = 1; + break; + + case 111: /* xzw */ + mask[0] = 1; + mask[1] = 0; + mask[2] = 1; + mask[3] = 1; + break; + + case 112: /* yzw */ + mask[0] = 0; + mask[1] = 1; + mask[2] = 1; + mask[3] = 1; + break; + + case 113: /* xyzw */ + mask[0] = 1; + mask[1] = 1; + mask[2] = 1; + mask[3] = 1; + break; + } + } +} + +/** + * Given a MASKED_DST_REG token in a parse tree node, figure out what + * register number and write mask the production results in. + * + * \param s The parse state + * \param mdr The parse tree node + * \param dest The destination register number + * \param dest_mask The 4-component write mask + */ +static void +get_masked_dst_reg(parse_state * s, parse_tree_node * mdr, GLint * dest, + GLint * dest_mask) +{ + GLint a; + + /* dest is a TEMP variable */ + if (mdr->children[0]->prod_applied == 67) { + a = mdr->children[0]->children[0]->children[0]->children[0]->tok_attr; + *dest = s->binds.reg_num[s->idents.attr[a]]; + printf("dst reg: %d (%s)\n", *dest, s->idents.data[a]); + } + else { + /* dest is a result variable */ + if (mdr->children[0]->children[0]->prod_applied == 86) { + a = mdr->children[0]->children[0]->children[0]->children[0]-> + tok_attr; + *dest = s->binds.reg_num[s->idents.attr[a]]; + printf("dest reg: %d (%s)\n", *dest, s->idents.data[a]); + } + /* dest is an implicit binding to result/output state */ + else { + a = mdr->children[0]->children[0]->children[0]->tok_attr; + *dest = s->binds.reg_num[a]; + printf("dst: %d\n", *dest); + } + } + + /* mdr->children[1] is the write mask */ + get_optional_mask(mdr->children[1], dest_mask); +} + + +/** + * Given a parse tree node with a swizzled src token, figure out the swizzle + * mask. + * + * \param s The parse state + * \param ssr The parse tree node + * \param swz The 4-component swizzle, 0 - x, 1 - y, 2 - z, 3 - w + */ +static void +get_src_swizzle(parse_state * s, parse_tree_node * ssr, GLint * swz) +{ + GLint a; + GLubyte *c; + + if (ssr->prod_applied == 317) { + if (ssr->children[0]->prod_applied == 318) { /* single component */ + switch (ssr->children[0]->children[0]->prod_applied) { + case 93: /* x */ + for (a = 0; a < 4; a++) + swz[a] = 0; + break; + + case 94: /* y */ + for (a = 0; a < 4; a++) + swz[a] = 1; + break; + + case 95: /* z */ + for (a = 0; a < 4; a++) + swz[a] = 2; + break; + + case 96: /* w */ + for (a = 0; a < 4; a++) + swz[a] = 3; + break; + } + } + else { /* 4-component */ + + c = s->idents.data[ssr->children[0]->children[0]->children[0]-> + tok_attr]; + for (a = 0; a < 4; a++) { + switch (c[a]) { + case 'x': + swz[a] = 0; + break; + case 'y': + swz[a] = 1; + break; + case 'z': + swz[a] = 2; + break; + case 'w': + swz[a] = 3; + break; + } + } + } + } +} + + +/** + * Given a parse tree node for a src register with an optional sign, figure out + * what register the src maps to, and what the sign is + * + * \param s The parse state + * \param ssr The parse tree node to work from + * \param sign The sign (1 or -1) + * \param ssrc The src register number + */ +static void +get_optional_sign_and_src_reg(parse_state * s, parse_tree_node * ssr, + int *sign, int *ssrc) +{ + GLint a; + + /* ssr->children[0] is the optionalSign */ + if (ssr->children[0]->prod_applied == 282) { /* - */ + *sign = -1; + } + + /* ssr->children[1] is the srcReg */ + + /* The src is a vertex attrib */ + if (ssr->children[1]->prod_applied == 64) { + if (ssr->children[1]->children[0]->prod_applied == 69) { /* variable */ + a = ssr->children[1]->children[0]->children[0]->children[0]-> + tok_attr; + *ssrc = s->binds.reg_num[s->idents.attr[a]]; + printf("src reg: %d (%s)\n", *ssrc, s->idents.data[a]); + } + else { /* implicit binding */ + + a = ssr->children[1]->children[0]->children[0]->tok_attr; + *ssrc = s->binds.reg_num[a]; + printf("src reg: %d %d (implicit binding)\n", + *ssrc, s->binds.type[a]); + } + } + else + /* The src is a temp variable */ + if (ssr->children[1]->prod_applied == 65) { + a = ssr->children[1]->children[0]->children[0]->children[0]->tok_attr; + *ssrc = s->binds.reg_num[s->idents.attr[a]]; + printf("src reg: %d (%s)\n", *ssrc, s->idents.data[a]); + } + /* The src is a param */ + else { + /* We have a single item */ + if (ssr->children[1]->children[0]->prod_applied == 72) { + a = ssr->children[1]->children[0]->children[0]->children[0]-> + children[0]->tok_attr; + *ssrc = s->binds.reg_num[s->idents.attr[a]]; + printf("src reg: %d (%s)\n", *ssrc, s->idents.data[a]); + } + else + /* We have an array of items */ + if (ssr->children[1]->children[0]->prod_applied == 73) { + a = ssr->children[1]->children[0]->children[0]->children[0]-> + children[0]->tok_attr; + *ssrc = s->binds.reg_num[s->idents.attr[a]]; + + /* We have an absolute offset into the array */ + if (ssr->children[1]->children[0]->children[1]->prod_applied == 77) { + /* Ok, are array will be layed out fully in registers, so we can compute the reg */ + printf("array base: %s\n", s->idents.data[a]); + a = ssr->children[1]->children[0]->children[1]->children[0]-> + children[0]->tok_attr; + printf("array absolute offset: %d\n", s->ints.data[a]); + *ssrc += s->ints.data[a]; + } + /* Otherwise, we have to grab the offset register */ + else { /* progParamArrayRel */ + + /* XXX: We don't know the offset, so we have to grab the offset register # */ + } + } + /* Otherwise, we have an implicit binding */ + else { /* paramSingleItemUse */ + + if (ssr->children[1]->children[0]->children[0]->prod_applied == 148) { /* programSingleItem */ + a = ssr->children[1]->children[0]->children[0]->children[0]-> + tok_attr; + } + else { + a = ssr->children[1]->children[0]->children[0]->children[0]-> + children[0]->tok_attr; + } + *ssrc = s->binds.reg_num[a]; + printf("src reg: %d %d (implicit binding)\n", *ssrc, + s->binds.type[a]); + } + } +} + + +/** + * Figure out what register a src reg is in, as well as the swizzle mask and the + * sign + * + * \param s The parse state + * \param ssr The swizzeled src reg parse tree node + * \param sign The return value for the sign {1, -1} + * \param ssrc The return value for the register number + * \param swz The 4-component swizzle mask + */ +static void +get_swizzle_src_reg(parse_state * s, parse_tree_node * ssr, GLint * sign, + GLint * ssrc, GLint * swz) +{ + get_optional_sign_and_src_reg(s, ssr, sign, ssrc); + + /* ssr->children[2] is the swizzleSuffix */ + get_src_swizzle(s, ssr->children[2], swz); +} + +/** + * Just like get_swizzle_src_reg, but find the scalar value to use from the register instead + * of the swizzle mask + * + * \param s The parse state + * \param ssr The swizzeled src reg parse tree node + * \param sign The return value for the sign {1, -1} + * \param ssrc The return value for the register number + * \param scalar The 1-component scalar number + */ +static void +get_scalar_src_reg(parse_state * s, parse_tree_node * ssr, GLint * sign, + GLint * ssrc, GLint * scalar) +{ + get_optional_sign_and_src_reg(s, ssr, sign, ssrc); + + /* sn->children[2] is a scalarSuffix */ + switch (ssr->children[2]->children[0]->prod_applied) { + case 93: + *scalar = 0; + break; + case 94: + *scalar = 1; + break; + case 95: + *scalar = 2; + break; + case 96: + *scalar = 3; + break; + } +} + +/** + * Recursivly traverse the parse tree and generate Mesa opcodes + * + * \param s The parse state + * \param ptn The parse tree node to process + */ +static void +parse_tree_generate_opcodes(parse_state * s, parse_tree_node * ptn) +{ + GLint a; + GLint opcode, dst, src[3]; + GLint dst_mask[4], src_swz[3][4], src_scalar[2], src_sign[3]; + parse_tree_node *dn, *sn[3]; + + src_sign[0] = src_sign[1] = src_sign[2] = 1; + for (a = 0; a < 4; a++) { + src_swz[0][a] = a; + src_swz[1][a] = a; + src_swz[2][a] = a; + } + src_scalar[0] = src_scalar[1] = src_scalar[2] = 0; + dst_mask[0] = dst_mask[1] = dst_mask[2] = dst_mask[3] = 1; + + switch (ptn->prod_applied) { + case 17: /* ARL */ + opcode = VP_OPCODE_ARL; + + dn = ptn->children[0]; + sn[0] = ptn->children[1]; + + /* dn is a maskedAddrReg */ + /* dn->children[0] is an addrReg */ + /* dn->children[1] is an addrWriteMask */ + /* XXX: do this.. */ + break; + + case 18: /* VECTORop */ + switch (ptn->children[0]->prod_applied) { + case 19: /* ABS */ + opcode = VP_OPCODE_ABS; + break; + case 20: /* FLR */ + opcode = VP_OPCODE_FLR; + break; + case 21: /* FRC */ + opcode = VP_OPCODE_FRC; + break; + case 22: /* LIT */ + opcode = VP_OPCODE_LIT; + break; + case 23: /* MOV */ + opcode = VP_OPCODE_MOV; + break; + } + printf("opcode: %d\n", opcode); + + /* dn is a maskedDstReg */ + dn = ptn->children[1]; + + /* sn is a swizzleSrcReg */ + sn[0] = ptn->children[2]; + + get_masked_dst_reg(s, dn, &dst, dst_mask); + printf("dst: %d mask: %d %d %d %d\n", dst, dst_mask[0], dst_mask[1], + dst_mask[2], dst_mask[3]); + + get_swizzle_src_reg(s, sn[0], &src_sign[0], &src[0], src_swz[0]); + + printf("src sign: %d reg: %d swz: %d %d %d %d\n", + src_sign[0], src[0], src_swz[0][0], src_swz[0][1], src_swz[0][2], + src_swz[0][3]); + break; + + case 24: /* SCALARop */ + switch (ptn->children[0]->prod_applied) { + case 25: /* EX2 */ + opcode = VP_OPCODE_EX2; + break; + case 26: /* EXP */ + opcode = VP_OPCODE_EXP; + break; + case 27: /* LG2 */ + opcode = VP_OPCODE_LG2; + break; + case 28: /* LOG */ + opcode = VP_OPCODE_LOG; + break; + case 29: /* RCP */ + opcode = VP_OPCODE_RCP; + break; + case 30: /* RSQ */ + opcode = VP_OPCODE_RSQ; + break; + } + + printf("opcode: %d\n", opcode); + /* dn is a maskedDstReg */ + dn = ptn->children[1]; + + get_masked_dst_reg(s, dn, &dst, dst_mask); + printf("dst: %d mask: %d %d %d %d\n", dst, dst_mask[0], dst_mask[1], + dst_mask[2], dst_mask[3]); + + /* sn is a scalarSrcReg */ + sn[0] = ptn->children[2]; + + get_scalar_src_reg(s, sn[0], &src_sign[0], &src[0], &src_scalar[0]); + printf("src sign: %d reg: %d scalar: %d\n", src_sign[0], src[0], + src_scalar[0]); + break; + + case 31: /* BINSC */ + opcode = VP_OPCODE_POW; + + printf("opcode: %d\n", opcode); + /* maskedDstReg */ + dn = ptn->children[1]; + get_masked_dst_reg(s, dn, &dst, dst_mask); + printf("dst: %d mask: %d %d %d %d\n", dst, dst_mask[0], dst_mask[1], + dst_mask[2], dst_mask[3]); + + /* sn are scalarSrcReg's */ + sn[0] = ptn->children[2]->children[0]; + sn[1] = ptn->children[2]->children[1]; + + get_scalar_src_reg(s, sn[0], &src_sign[0], &src[0], &src_scalar[0]); + get_scalar_src_reg(s, sn[1], &src_sign[1], &src[1], &src_scalar[1]); + + printf("src0 sign: %d reg: %d scalar: %d\n", src_sign[0], src[0], + src_scalar[0]); + printf("src1 sign: %d reg: %d scalar: %d\n", src_sign[1], src[1], + src_scalar[1]); + break; + + + case 34: /* BIN */ + switch (ptn->children[0]->prod_applied) { + case 36: /* ADD */ + opcode = VP_OPCODE_ADD; + break; + case 37: /* DP3 */ + opcode = VP_OPCODE_DP3; + break; + case 38: /* DP4 */ + opcode = VP_OPCODE_DP4; + break; + case 39: /* DPH */ + opcode = VP_OPCODE_DPH; + break; + case 40: /* DST */ + opcode = VP_OPCODE_DST; + break; + case 41: /* MAX */ + opcode = VP_OPCODE_MAX; + break; + case 42: /* MIN */ + opcode = VP_OPCODE_MIN; + break; + case 43: /* MUL */ + opcode = VP_OPCODE_MUL; + break; + case 44: /* SGE */ + opcode = VP_OPCODE_SGE; + break; + case 45: /* SLT */ + opcode = VP_OPCODE_SLT; + break; + case 46: /* SUB */ + opcode = VP_OPCODE_SUB; + break; + case 47: /* XPD */ + opcode = VP_OPCODE_XPD; + break; + } + + printf("opcode: %d\n", opcode); + + /* maskedDstReg */ + dn = ptn->children[1]; + get_masked_dst_reg(s, dn, &dst, dst_mask); + printf("dst: %d mask: %d %d %d %d\n", dst, dst_mask[0], dst_mask[1], + dst_mask[2], dst_mask[3]); + + /* sn are scalarSrcReg's */ + sn[0] = ptn->children[2]->children[0]; + sn[1] = ptn->children[2]->children[1]; + + get_swizzle_src_reg(s, sn[0], &src_sign[0], &src[0], src_swz[0]); + get_swizzle_src_reg(s, sn[1], &src_sign[1], &src[1], src_swz[1]); + + printf("src0 sign: %d reg: %d swz: %d %d %d %d\n", + src_sign[0], src[0], src_swz[0][0], src_swz[0][1], src_swz[0][2], + src_swz[0][3]); + printf("src1 sign: %d reg: %d swz: %d %d %d %d\n", src_sign[1], src[1], + src_swz[1][0], src_swz[1][1], src_swz[1][2], src_swz[1][3]); + break; + + case 48: /* TRI */ + opcode = VP_OPCODE_MAD; + + printf("opcode: %d\n", opcode); + + /* maskedDstReg */ + dn = ptn->children[1]; + get_masked_dst_reg(s, dn, &dst, dst_mask); + printf("dst: %d mask: %d %d %d %d\n", dst, dst_mask[0], dst_mask[1], + dst_mask[2], dst_mask[3]); + + /* sn are scalarSrcReg's */ + sn[0] = ptn->children[2]->children[0]; + sn[1] = ptn->children[2]->children[1]->children[0]; + sn[2] = ptn->children[2]->children[1]->children[1]; + + get_swizzle_src_reg(s, sn[0], &src_sign[0], &src[0], src_swz[0]); + get_swizzle_src_reg(s, sn[1], &src_sign[1], &src[1], src_swz[1]); + get_swizzle_src_reg(s, sn[2], &src_sign[2], &src[2], src_swz[2]); + + printf("src0 sign: %d reg: %d swz: %d %d %d %d\n", + src_sign[0], src[0], src_swz[0][0], src_swz[0][1], src_swz[0][2], + src_swz[0][3]); + printf("src1 sign: %d reg: %d swz: %d %d %d %d\n", src_sign[1], src[1], + src_swz[1][0], src_swz[1][1], src_swz[1][2], src_swz[1][3]); + printf("src2 sign: %d reg: %d swz: %d %d %d %d\n", src_sign[2], src[2], + src_swz[2][0], src_swz[2][1], src_swz[2][2], src_swz[2][3]); + + } + + for (a = 0; a < 4; a++) { + if (!ptn->children[a]) + return; + parse_tree_generate_opcodes(s, ptn->children[a]); + } +} + +/** + * When we go to examine the parse tree to generate opcodes, things are not exactly pretty to deal with. + * Parameters, constants, matricies, attribute bindings, and the like are represented by large numbers + * of nodes. + * + * In order to keep the code generation code cleaner, we make a recursive pass over the parse tree and 'roll up' these deep + * derivations of the attribs, and replace them with a single token, BINDING_TOKEN. The token attribute for + * BINDING_TOKEN is a index in the 'binding table' where all the relavant info on the chunk of state is stored, + * e.g its type. + * + * For example, the string 'vertex.color.secondary' is represented by 4 productions, and 4 nodes in the parse + * tree. The token at the root of this derivation is NT_VTX_ATTRIB_BINDING_TOKEN. After this folding, + * the token at the root is BINDING_TOKEN, and s->binds[token_attr_at_the_root].type = ATTRIB_COLOR_SECONDARY. + * + * \param s The parse state + * \param ptn The root parse tree node to start folding bindings + */ +static void +parse_tree_fold_bindings(parse_state * s, parse_tree_node * ptn) +{ + GLint a, b; + GLint eat_children, bind_type, bind_idx, bind_row, bind_nrows; + GLfloat bind_vals[4]; + parse_tree_node *ptmp; + + eat_children = 0; + bind_row = 0; + bind_nrows = 1; + bind_vals[0] = bind_vals[1] = bind_vals[2] = bind_vals[3]; + switch (ptn->prod_applied) { + /* vertex */ + case 121: + eat_children = 1; + bind_idx = 0; + switch (ptn->children[0]->prod_applied) { + case 122: /* position */ + bind_type = ATTRIB_POSITION; + break; + case 123: /* weight */ + bind_type = ATTRIB_WEIGHT; + if (ptn->children[0]->children[0]->prod_applied == 132) { + bind_idx = + s->ints.data[ptn->children[0]->children[0]->children[0]-> + children[0]->tok_attr]; + } + break; + case 124: /* normal */ + bind_type = ATTRIB_NORMAL; + break; + case 125: /* color */ + bind_type = ATTRIB_COLOR_PRIMARY; + if (ptn->children[0]->children[0]->prod_applied == 306) { + if (ptn->children[0]->children[0]->children[0]->prod_applied == + 309) + bind_type = ATTRIB_COLOR_SECONDARY; + } + break; + case 126: /* fogcoord */ + bind_type = ATTRIB_FOGCOORD; + break; + case 127: /* texcoord */ + bind_type = ATTRIB_TEXCOORD; + if (ptn->children[0]->children[0]->prod_applied == 311) { + bind_idx = + s->ints.data[ptn->children[0]->children[0]->children[0]-> + children[0]->tok_attr]; + } + break; + case 128: /* matrixindex */ + bind_type = ATTRIB_MATRIXINDEX; + bind_idx = + s->ints.data[ptn->children[0]->children[0]->children[0]-> + tok_attr]; + break; + case 129: /* attrib */ + bind_type = ATTRIB_ATTRIB; + bind_idx = + s->ints.data[ptn->children[0]->children[0]->children[0]-> + tok_attr]; + break; + } + break; + + /* state */ + case 154: + case 172: /* material */ + eat_children = 2; + bind_idx = 0; + ptmp = ptn->children[0]->children[0]; + + a = 0; + if (ptmp->prod_applied == 182) { + a = 1; + b = 0; + } + else + if ((ptmp->prod_applied == 183) + && (ptmp->children[0]->prod_applied == 305)) { + a = 1; + b = 1; + } + + /* no explicit face, or explicit front */ + if (a) { + switch (ptmp->children[b]->prod_applied) { + case 184: /* ambient */ + bind_type = MATERIAL_FRONT_AMBIENT; + break; + case 185: /* diffuse */ + bind_type = MATERIAL_FRONT_DIFFUSE; + break; + case 186: /* specular */ + bind_type = MATERIAL_FRONT_SPECULAR; + break; + case 187: /* emission */ + bind_type = MATERIAL_FRONT_EMISSION; + break; + case 188: /* shininess */ + bind_type = MATERIAL_FRONT_SHININESS; + break; + } + } + /* has explicit back face */ + else { + switch (ptmp->children[1]->prod_applied) { + case 184: /* ambient */ + bind_type = MATERIAL_BACK_AMBIENT; + break; + case 185: /* diffuse */ + bind_type = MATERIAL_BACK_DIFFUSE; + break; + case 186: /* specular */ + bind_type = MATERIAL_BACK_SPECULAR; + break; + case 187: /* emission */ + bind_type = MATERIAL_BACK_EMISSION; + break; + case 188: /* shininess */ + bind_type = MATERIAL_BACK_SHININESS; + break; + } + } + break; + case 155: + case 173: /* light */ + eat_children = 2; + bind_idx = 0; + printf("FOLDING LIGHT!\n"); + ptmp = ptn->children[0]; + bind_idx = s->ints.data[ptmp->children[0]->children[0]->tok_attr]; + switch (ptmp->children[1]->children[0]->prod_applied) { + case 191: /* ambient */ + bind_type = LIGHT_AMBIENT; + break; + case 192: /* diffuse */ + bind_type = LIGHT_DIFFUSE; + break; + case 193: /* specular */ + bind_type = LIGHT_SPECULAR; + break; + case 194: /* position */ + bind_type = LIGHT_POSITION; + break; + case 195: /* attenuation */ + bind_type = LIGHT_ATTENUATION; + break; + case 196: /* spot */ + bind_type = LIGHT_SPOT_DIRECTION; + break; + case 197: /* half */ + bind_type = LIGHT_HALF; + break; + } + break; + + case 156: + case 174: /* lightmodel */ + eat_children = 2; + bind_idx = 0; + + ptmp = ptn->children[0]; + switch (ptmp->prod_applied) { + case 201: /* ambient */ + bind_type = LIGHTMODEL_AMBIENT; + break; + case 202: /* scenecolor */ + bind_type = LIGHTMODEL_FRONT_SCENECOLOR; + break; + case 203: /* foo.scenecolor */ + if (ptmp->children[0]->prod_applied == 304) + bind_type = LIGHTMODEL_FRONT_SCENECOLOR; + else + bind_type = LIGHTMODEL_BACK_SCENECOLOR; + } + break; + case 157: + case 175: /* lightprod */ + eat_children = 2; + bind_idx = 0; + + ptmp = ptn->children[0]; + bind_idx = s->ints.data[ptmp->children[0]->children[0]->tok_attr]; + /* No explicit face */ + if (ptmp->children[1]->children[0]->prod_applied == 206) { + a = 1; /* front */ + b = 0; /* 0-th child */ + } + else + if ((ptmp->children[1]->children[0]->prod_applied == 207) && + (ptmp->children[1]->children[0]->children[0]->prod_applied == + 304)) { + a = 1; /* front */ + b = 1; /* 1-th child */ + } + else { + a = 0; + b = 1; + } + if (a) { + switch (ptmp->children[1]->children[0]->children[b]->prod_applied) { + case 208: /* ambient */ + bind_type = LIGHTPROD_FRONT_AMBIENT; + break; + case 209: /* diffuse */ + bind_type = LIGHTPROD_FRONT_DIFFUSE; + break; + case 210: /* specular */ + bind_type = LIGHTPROD_FRONT_SPECULAR; + break; + } + } + else { + switch (ptmp->children[1]->children[0]->children[b]->prod_applied) { + case 208: /* ambient */ + bind_type = LIGHTPROD_BACK_AMBIENT; + break; + case 209: /* diffuse */ + bind_type = LIGHTPROD_BACK_DIFFUSE; + break; + case 210: /* specular */ + bind_type = LIGHTPROD_BACK_SPECULAR; + break; + } + } + break; + case 158: + case 176: /* texgen */ + eat_children = 2; + bind_idx = 0; + + ptmp = ptn->children[0]; + if (ptmp->children[0]->prod_applied == 311) + bind_idx = + s->ints.data[ptmp->children[0]->children[0]->children[0]-> + tok_attr]; + ptmp = ptn->children[0]->children[1]; + if (ptmp->children[0]->prod_applied == 214) + a = 1; /* eye */ + else + a = 0; /* object */ + b = ptmp->children[1]->prod_applied - 216; + if (a == 1) { + switch (b) { + case 0: + bind_type = TEXGEN_EYE_S; + break; + case 1: + bind_type = TEXGEN_EYE_T; + break; + case 2: + bind_type = TEXGEN_EYE_R; + break; + case 3: + bind_type = TEXGEN_EYE_Q; + break; + } + } + else { + switch (b) { + case 0: + bind_type = TEXGEN_OBJECT_S; + break; + case 1: + bind_type = TEXGEN_OBJECT_T; + break; + case 2: + bind_type = TEXGEN_OBJECT_R; + break; + case 3: + bind_type = TEXGEN_OBJECT_Q; + break; + } + } + break; + case 159: + case 177: /* fog */ + eat_children = 2; + bind_idx = 0; + + ptmp = ptn->children[0]; + if (ptmp->children[0]->prod_applied == 221) + bind_type = FOG_COLOR; + else + bind_type = FOG_PARAMS; + break; + case 160: + case 178: /* clip */ + eat_children = 2; + bind_idx = 0; + + ptmp = ptn->children[0]; + bind_idx = s->ints.data[ptmp->children[0]->children[0]->tok_attr]; + bind_type = CLIP_PLANE; + break; + case 161: + case 179: /* point */ + eat_children = 2; + bind_idx = 0; + + ptmp = ptn->children[0]; + if (ptmp->children[0]->prod_applied == 227) + bind_type = POINT_SIZE; + else + bind_type = POINT_ATTENUATION; + break; + + case 162: /* matrix rows/whole matrix */ + eat_children = 2; + bind_idx = 0; + { + parse_tree_node *mname; + GLint mod = 0; + GLint name = 0; + + mname = ptn->children[0]; + switch (mname->prod_applied) { + case 238: /* modelview */ + name = 0; + if (mname->children[0]->prod_applied == 245) + bind_idx = + s->ints.data[mname->children[0]->children[0]->children[0]-> + tok_attr]; + break; + case 239: /* projection */ + name = 1; + break; + case 240: /* mvp */ + name = 2; + break; + case 241: /* texture */ + if (mname->children[0]->prod_applied == 311) + bind_idx = + s->ints.data[mname->children[0]->children[0]->children[0]-> + tok_attr]; + name = 3; + break; + case 242: /* palette */ + bind_idx = + s->ints.data[mname->children[0]->children[0]->tok_attr]; + name = 4; + break; + case 243: /* program */ + bind_idx = + s->ints.data[mname->children[0]->children[0]->tok_attr]; + name = 5; + break; + } + + ptmp = ptn->children[1]; + if (ptmp->prod_applied == 316) { + bind_type = name_and_mod_to_matrixrows(name, mod); + bind_row = 0; + bind_nrows = 4; + } + else { + if (ptmp->children[0]->prod_applied == 164) { + switch (ptmp->children[0]->children[0]->prod_applied) { + case 234: /* inverse */ + mod = 1; + break; + case 235: /* transpose */ + mod = 3; + break; + case 236: /* invtrans */ + mod = 2; + break; + } + if (ptmp->children[0]->children[1]->prod_applied == 166) { + bind_type = name_and_mod_to_matrixrows(name, mod); + bind_row = 0; + bind_nrows = 4; + } + else { /* prod 167 */ + + bind_type = name_and_mod_to_matrixrows(name, mod); + bind_row = + s->ints.data[ptmp->children[0]->children[1]-> + children[0]->children[0]->children[0]-> + tok_attr]; + if (ptmp->children[0]->children[1]->children[0]-> + children[1]->prod_applied == 169) + bind_nrows = 1; + else { + bind_nrows = + s->ints.data[ptmp->children[0]->children[1]-> + children[0]->children[1]->children[0]-> + children[0]->tok_attr] - bind_row + 1; + } + } + } + else { /* prod 165 */ + + bind_type = name_and_mod_to_matrixrows(name, mod); + + bind_row = + s->ints.data[ptmp->children[0]->children[0]->children[0]-> + tok_attr]; + if (ptmp->children[0]->children[1]->prod_applied == 169) + bind_nrows = 1; + else + bind_nrows = + s->ints.data[ptmp->children[0]->children[1]-> + children[0]->children[0]->tok_attr] - + bind_row + 1; + } + } + } + + printf("folding matrixrows: %d %d %d %d\n", bind_type, bind_idx, + bind_row, bind_nrows); + break; + + case 180: /* matrix row */ + eat_children = 2; + bind_idx = 0; + + { + GLint mod; + parse_tree_node *mname, *mrow; + + ptmp = ptn->children[0]; + mname = ptmp->children[0]; + mod = 0; + if (ptmp->children[1]->children[0]->prod_applied == 232) { + mrow = + ptmp->children[1]->children[0]->children[1]->children[0]-> + children[0]; + switch (ptmp->children[1]->children[0]->children[0]->prod_applied) { + case 234: + mod = 1; /* inverse */ + break; + case 235: + mod = 2; /* transpose */ + break; + case 236: + mod = 3; /* invtrans */ + break; + } + } + else { + mrow = ptmp->children[1]->children[0]->children[0]->children[0]; + } + bind_row = s->ints.data[mrow->tok_attr]; + + switch (mname->prod_applied) { + case 238: /* modelview */ + if (mname->children[0]->prod_applied == 245) { + bind_idx = + s->ints.data[mname->children[0]->children[0]->children[0]-> + tok_attr]; + } + switch (mod) { + case 0: + bind_type = MATRIXROW_MODELVIEW; + break; + case 1: + bind_type = MATRIXROW_MODELVIEW_INVERSE; + break; + case 2: + bind_type = MATRIXROW_MODELVIEW_TRANSPOSE; + break; + case 3: + bind_type = MATRIXROW_MODELVIEW_INVTRANS; + } + break; + + case 239: /* projection */ + switch (mod) { + case 0: + bind_type = MATRIXROW_PROJECTION; + break; + case 1: + bind_type = MATRIXROW_PROJECTION_INVERSE; + break; + case 2: + bind_type = MATRIXROW_PROJECTION_TRANSPOSE; + break; + case 3: + bind_type = MATRIXROW_PROJECTION_INVTRANS; + } + break; + + case 240: /* mvp */ + switch (mod) { + case 0: + bind_type = MATRIXROW_MVP; + break; + case 1: + bind_type = MATRIXROW_MVP_INVERSE; + break; + case 2: + bind_type = MATRIXROW_MVP_TRANSPOSE; + break; + case 3: + bind_type = MATRIXROW_MVP_INVTRANS; + } + break; + + case 241: /* texture */ + if (mname->children[0]->prod_applied == 311) { + bind_idx = + s->ints.data[mname->children[0]->children[0]->children[0]-> + tok_attr]; + } + switch (mod) { + case 0: + bind_type = MATRIXROW_TEXTURE; + break; + case 1: + bind_type = MATRIXROW_TEXTURE_INVERSE; + break; + case 2: + bind_type = MATRIXROW_TEXTURE_TRANSPOSE; + break; + case 3: + bind_type = MATRIXROW_TEXTURE_INVTRANS; + } + break; + + case 242: /* palette */ + bind_idx = + s->ints.data[mname->children[0]->children[0]->tok_attr]; + switch (mod) { + case 0: + bind_type = MATRIXROW_PALETTE; + break; + case 1: + bind_type = MATRIXROW_PALETTE_INVERSE; + break; + case 2: + bind_type = MATRIXROW_PALETTE_TRANSPOSE; + break; + case 3: + bind_type = MATRIXROW_PALETTE_INVTRANS; + } + break; + + case 243: /* program */ + bind_idx = + s->ints.data[mname->children[0]->children[0]->tok_attr]; + switch (mod) { + case 0: + bind_type = MATRIXROW_PROGRAM; + break; + case 1: + bind_type = MATRIXROW_PROGRAM_INVERSE; + break; + case 2: + bind_type = MATRIXROW_PROGRAM_TRANSPOSE; + break; + case 3: + bind_type = MATRIXROW_PROGRAM_INVTRANS; + } + break; + } + } + break; + + /* program (single) */ + case 249: + eat_children = 1; + bind_idx = 0; + switch (ptn->children[0]->prod_applied) { + case 250: /* env */ + bind_type = PROGRAM_ENV_SINGLE; + break; + case 251: /* local */ + bind_type = PROGRAM_LOCAL_SINGLE; + break; + } + bind_idx = + s->ints.data[ptn->children[0]->children[0]->children[0]-> + children[0]->tok_attr]; + break; + + /* program (multi) */ + case 252: + eat_children = 1; + bind_idx = 0; + switch (ptn->children[0]->prod_applied) { + case 253: /* env */ + case 254: /* local */ + if (ptn->children[0]->prod_applied == 253) + bind_type = PROGRAM_ENV_MULTI; + else + bind_type = PROGRAM_LOCAL_MULTI; + + ptmp = ptn->children[0]->children[0]->children[0]; + bind_idx = bind_row = + s->ints.data[ptmp->children[0]->children[0]->tok_attr]; + bind_nrows = 1; + + ptmp = ptn->children[0]->children[0]->children[0]->children[1]; + if ((ptmp->prod_applied == 257) || (ptmp->prod_applied == 262)) + bind_nrows = + s->ints.data[ptmp->children[0]->children[0]->tok_attr] - + bind_idx; + break; + } + break; + +#define FOLD_FLOAT_CONSTANT(float_ptr, bind_vals_idx, sign) \ + if (float_ptr->tok == 49) /* GLfloat */ {\ + bind_vals[bind_vals_idx] = sign * s->floats.data[float_ptr->tok_attr];\ + }\ + else /* GLint */ {\ + bind_vals[bind_vals_idx] = sign * s->ints.data[float_ptr->tok_attr];\ + } + +#define FOLD_SIGNED_FLOAT_CONSTANT(sf_ptr, bind_vals_idx) \ + {\ + GLfloat __mul = 1.;\ + if (sf_ptr->children[0]->prod_applied == 282) \ + __mul = -1.;\ + FOLD_FLOAT_CONSTANT(sf_ptr->children[1], bind_vals_idx, __mul);\ + } + + /* const scalar decl */ + case 271: + eat_children = 1; + bind_idx = 0; + bind_type = CONSTANT; + + FOLD_SIGNED_FLOAT_CONSTANT(ptn->children[0], 0); +#if 0 + { + GLfloat mul = 1.; + if (ptn->children[0]->children[0]->prod_applied == 282) { + mul = -1; + } + + FOLD_FLOAT_CONSTANT(ptn->children[0]->children[1], 0, mul); + } +#endif + break; + + /* const vector */ + case 273: + eat_children = 1; + bind_idx = 0; + bind_type = CONSTANT; + + FOLD_SIGNED_FLOAT_CONSTANT(ptn->children[0], 0); + if (ptn->children[1]->prod_applied == 275) { + FOLD_SIGNED_FLOAT_CONSTANT(ptn->children[1]->children[0], 1); + if (ptn->children[1]->children[1]->prod_applied == 277) { + FOLD_SIGNED_FLOAT_CONSTANT(ptn->children[1]->children[1]-> + children[0], 2); + if (ptn->children[1]->children[1]->children[1]->prod_applied == + 279) { + FOLD_SIGNED_FLOAT_CONSTANT(ptn->children[1]->children[1]-> + children[1]->children[0], 3); + } + } + } + break; + + /* result */ + case 289: + eat_children = 1; + bind_idx = 0; + switch (ptn->children[0]->prod_applied) { + case 290: /* position */ + bind_type = RESULT_POSITION; + break; + case 291: /* fogcoord */ + bind_type = RESULT_FOGCOORD; + break; + case 292: /* pointsize */ + bind_type = RESULT_POINTSIZE; + break; + case 293: /* color */ + bind_type = RESULT_COLOR_FRONT_PRIMARY; + ptmp = ptn->children[0]->children[0]->children[0]; + if (ptmp->prod_applied == 297) { + if (ptmp->children[0]->prod_applied == 298) { /* front */ + if (ptmp->children[0]->children[0]->prod_applied == 301) { + if (ptmp->children[0]->children[0]->children[0]->prod_applied == 303) /* secondary */ + bind_type = RESULT_COLOR_FRONT_SECONDARY; + } + } + else { /* back */ + + bind_type = RESULT_COLOR_BACK_PRIMARY; + if (ptmp->children[0]->children[0]->prod_applied == 301) { + if (ptmp->children[0]->children[0]->children[0]->prod_applied == 303) /* secondary */ + bind_type = RESULT_COLOR_BACK_SECONDARY; + } + + } + } + break; + case 294: /* texcoord */ + bind_type = RESULT_TEXCOORD; + if (ptn->children[0]->children[0]->prod_applied == 311) { + bind_idx = + s->ints.data[ptn->children[0]->children[0]->children[0]-> + children[0]->tok_attr]; + } + break; + } + break; + } + + /* Mmmmm... baaaaby */ + if (eat_children) { + if (eat_children == 2) + parse_tree_free_children(ptn->children[0]); + else + parse_tree_free_children(ptn); + + /* Insert the binding into the binding table */ + ptn->tok = BINDING_TOKEN; + ptn->tok_attr = + binding_table_add(&s->binds, bind_type, bind_idx, bind_row, + bind_nrows, bind_vals); + + printf("Got binding %d %d %d %d at pos %d in bind tab [%f %f %f %f]\n", + bind_type, bind_idx, bind_row, bind_nrows, ptn->tok_attr, + bind_vals[0], bind_vals[1], bind_vals[2], bind_vals[3]); + } + + + for (a = 0; a < 4; a++) { + if (!ptn->children[a]) + return; + + parse_tree_fold_bindings(s, ptn->children[a]); + } +} + +/** + * After we have figured out what mess of parse tree actually represents GL state (or constants, or + * whatnot), we have to line up variables with the state. For example, a line something like + * + * OUTPUT foo = result.position; + * + * We would have 'foo' in the identifier table at some position foo_idx, and 'result.position' in the + * binding table at some position res_pos_idx. To set things up such that 'foo' is associated with + * the result position state, we need to set ident[foo_idx].attr = res_pos_idx so we can generate + * opcodes without going bonkers. + * + * This function works on OUTPUT, ATTRIB, and PARAM single bindings. PARAM array bindings are handled in + * parse_tree_assign_param_arrays(). + * + * \param s The parse state + * \param ptn The root of the parse tree from which to start lining up state and variables + */ +static void +parse_tree_assign_bindings(parse_state * s, parse_tree_node * ptn) +{ + GLint a; + parse_tree_node *var_name, *attr_item; + + /* OUTPUT, ATTRIB */ + if ((ptn->prod_applied == 288) || (ptn->prod_applied == 120)) { + var_name = ptn->children[0]->children[0]; + attr_item = ptn->children[1]; + + if (attr_item->tok != BINDING_TOKEN) { + fprintf(stderr, + "sanity check: trying to bind an output variable to something funky!\n"); + return; + } + + s->idents.attr[var_name->tok_attr] = attr_item->tok_attr; + printf("result: %s bound to %d\n", s->idents.data[var_name->tok_attr], + s->binds.type[s->idents.attr[var_name->tok_attr]]); + return; + } + + /* stateSingleItemDecl */ + if (ptn->prod_applied == 134) { + var_name = ptn->children[0]->children[0]; + if (ptn->children[1]->prod_applied == 135) { + if (ptn->children[1]->children[0]->prod_applied == 139) { + if (ptn->children[1]->children[0]->children[0]->prod_applied == + 144) + attr_item = + ptn->children[1]->children[0]->children[0]->children[0]-> + children[0]; + else if (ptn->children[1]->children[0]->children[0]-> + prod_applied == 145) + attr_item = + ptn->children[1]->children[0]->children[0]->children[0]; + else + attr_item = + ptn->children[1]->children[0]->children[0]->children[0]-> + children[0]; + + if (attr_item->tok != BINDING_TOKEN) { + fprintf(stderr, + "sanity check: trying to bind an param variable (%s) to something funky! [%d]\n", + s->idents.data[var_name->tok_attr], attr_item->tok); + exit(1); + } + + s->idents.attr[var_name->tok_attr] = attr_item->tok_attr; + printf("result: %s bound to %d\n", + s->idents.data[var_name->tok_attr], + s->binds.type[s->idents.attr[var_name->tok_attr]]); + return; + } + } + + } + + /* else, recurse on all our children */ + for (a = 0; a < 4; a++) { + if (!ptn->children[a]) + return; + + parse_tree_assign_bindings(s, ptn->children[a]); + } + +} + +/** + * This handles lining up PARAM arrays with variables, much like parse_tree_assign_bindings(). + * + * In parse_tree_assign_bindings, we set the identifier attr to the index into the binding table of + * the bound state. + * + * Here, instead, we allocate a slot in the 'array table' to stick the bound state into. Instead + * of an index into the binding table, the identifier attr now holds the index into the array table. + * + * \param s The parse state + * \param pnt The root parse tree node to handle arrays from + * + */ +static void +parse_tree_assign_param_arrays(parse_state * s, parse_tree_node * ptn) +{ + GLint a, is_mult, array_len; + parse_tree_node *var_name, *binding, *arraysize, *ptmp; + + /* If we're a param */ + if (ptn->prod_applied == 134) { + /* establish name */ + var_name = ptn->children[0]; + + /* param_statement2 */ + binding = ptn->children[1]; + if (binding->prod_applied == 136) { + /* optarraysize */ + arraysize = binding->children[0]; + + is_mult = 0; + + /* foo[3] */ + if (arraysize->prod_applied == 138) { + debug_token(s, var_name->children[0]->tok, + var_name->children[0]->tok_attr); + debug_token(s, arraysize->children[0]->tok, + arraysize->children[0]->tok_attr); + printf("\n"); + is_mult = 1; + } + else + /* foo[] */ + if (arraysize->prod_applied == 137) { + arraysize = NULL; + printf("How do I init a PARAM array like foo[]?? \n"); + is_mult = 1; + } + + if (!is_mult) + return; + + s->idents.attr[var_name->tok_attr] = array_table_new(&s->arrays); + + binding = binding->children[1]->children[0]; + ptmp = binding->children[0]; + array_len = 0; + + if (ptmp->prod_applied == 150) { /* state */ + printf("matrix 0 [state]:\n"); + printf("%d %d\n", ptmp->children[0]->children[0]->tok, + ptmp->children[0]->children[0]->tok_attr); + array_table_add_data(&s->arrays, + s->idents.attr[var_name->tok_attr], + ptmp->children[0]->children[0]->tok_attr); + array_len += + s->binds.num_rows[ptmp->children[0]->children[0]->tok_attr]; + } + else if (ptmp->prod_applied == 151) { /* program */ + printf("matrix 0 [program]:\n"); + printf("%d %d\n", ptmp->children[0]->tok, + ptmp->children[0]->tok_attr); + array_table_add_data(&s->arrays, + s->idents.attr[var_name->tok_attr], + ptmp->children[0]->tok_attr); + array_len += s->binds.num_rows[ptmp->children[0]->tok_attr]; + } + else { /* constant */ + + printf("matrix 0 [constant]:\n"); + printf("%d %d\n", ptmp->children[0]->children[0]->tok, + ptmp->children[0]->children[0]->tok_attr); + array_table_add_data(&s->arrays, + s->idents.attr[var_name->tok_attr], + ptmp->children[0]->children[0]->tok_attr); + array_len += + s->binds.num_rows[ptmp->children[0]->children[0]->tok_attr]; + } + binding = binding->children[1]; + + while (binding->prod_applied != 143) { + ptmp = binding->children[0]->children[0]; + printf("mat: %d\n", ptmp->prod_applied); + if (ptmp->prod_applied == 150) { /* state */ + printf("matrix %d:\n", array_len); + printf("%d %d\n", ptmp->children[0]->children[0]->tok, + ptmp->children[0]->children[0]->tok_attr); + array_table_add_data(&s->arrays, + s->idents.attr[var_name->tok_attr], + ptmp->children[0]->children[0]->tok_attr); + array_len += + s->binds.num_rows[ptmp->children[0]->children[0]->tok_attr]; + } + else if (ptmp->prod_applied == 151) { /* program */ + printf("matrix %d [program]:\n", array_len); + printf("%d %d\n", ptmp->children[0]->tok, + ptmp->children[0]->tok_attr); + array_table_add_data(&s->arrays, + s->idents.attr[var_name->tok_attr], + ptmp->children[0]->tok_attr); + array_len += s->binds.num_rows[ptmp->children[0]->tok_attr]; + } + else { /* constant */ + + printf("matrix %d [constant]:\n", array_len); + printf("%d %d\n", ptmp->children[0]->children[0]->tok, + ptmp->children[0]->children[0]->tok_attr); + array_table_add_data(&s->arrays, + s->idents.attr[var_name->tok_attr], + ptmp->children[0]->children[0]->tok_attr); + array_len += + s->binds.num_rows[ptmp->children[0]->children[0]->tok_attr]; + } + binding = binding->children[0]->children[1]; + } + + /* XXX: have to compare the requested size, and the actual + * size, and fix up any inconsistancies + */ + if (arraysize) { + printf("matrix wants to get %d rows\n", + s->ints.data[arraysize->children[0]->tok_attr]); + } + printf("matrix num rows: %d\n", array_len); + } + + return; + } + + /* Else, recurse on all our children */ + for (a = 0; a < 4; a++) { + if (!ptn->children[a]) + return; + + parse_tree_assign_param_arrays(s, ptn->children[a]); + } + +} + +/* XXX: This needs to be written properly. */ +/** + * Here we allocate 'registers' for all of the various variables and bound state. + * + * The 'register' number is given by the reg_num field in the binding table. Note that this field + * is not stored in the identifier table. If it were, we would need a different mechanism for handling + * implicit bindings. + * + * However, after some discussion with Brian, implicit bindings may be handled by grabbing state + * directly from Mesa's state structs. This might be a little hairy here, maybe not.. Implicit + * bindings are those in the binding table that are not pointed to by any ident.attr or array.data + * + * This should also do various error checking, like the multiple vertex attrib error, or 'too many bindings' + * error. + * + * \param s The parse state + */ +static void +assign_regs(parse_state * s) +{ + GLint a; + GLfloat foo[4]; + + for (a = 0; a < s->idents.len; a++) { + if (s->idents.type[a] == TYPE_TEMP) { + s->idents.attr[a] = + binding_table_add(&s->binds, TYPE_TEMP, 0, 0, 0, foo); + } + } +} + +/** + * Parse/compile the 'str' returning the compiled 'program'. + * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos + * indicates the position of the error in 'str'. + */ +void +_mesa_parse_arb_vertex_program(GLcontext * ctx, GLenum target, + const GLubyte * string, GLsizei len, + struct vertex_program *program) +{ + GLubyte *our_string; + parse_state *state; + + printf("len: %d\n", len); + + /* XXX: How do I handle these errors? */ + if (len < 10) + return; + if (_mesa_strncmp(string, "!!ARBvp1.0", 10)) + return; + + /* Make a null-terminated copy of the program string */ + our_string = (GLubyte *) MALLOC(len + 1); + if (!our_string) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB"); + return; + } + MEMCPY(our_string, string, len); + our_string[len] = 0; + + state = parse_state_init(our_string + 10, strlen(our_string) - 10); + + if (parse(state) == ARB_VP_SUCESS) { + printf("parse sucess!\n"); + } + else { + printf("*** error\n"); + parse_state_cleanup(state); + return; + } + + /* First, we 'fold' bindings from a big mess of productions and + * tokens into one BINDING_TOKEN, which points to an entry + * in the binding sym table that holds all of the relevant + * info for the binding destination. + */ + parse_tree_fold_bindings(state, state->pt_head); + + /* Now, for each type of binding, walk the parse tree and stick + * the index into the binding sym table + */ + parse_tree_assign_bindings(state, state->pt_head); + + /* XXX: this still needs a' fixin to get folded bindings + * -- it does? wtf do I mean? */ + parse_tree_assign_param_arrays(state, state->pt_head); + + /* XXX: Now, assign registers. For this, we'll need to create + * bindings for all temps (and what else?? ) + */ + assign_regs(state); + + /* Ok, now generate code */ + parse_tree_generate_opcodes(state, state->pt_head); + + /* Just for testing.. */ + program->Base.Target = target; + if (program->Base.String) { + FREE(program->Base.String); + } + program->Base.String = our_string; + program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB; + + if (program->Instructions) { + FREE(program->Instructions); + } + + program->Instructions = + (struct vp_instruction *) _mesa_malloc(sizeof(struct vp_instruction)); + program->Instructions[0].Opcode = VP_OPCODE_END; + program->InputsRead = 0; + program->OutputsWritten = 0; + program->IsPositionInvariant = 0; + + parse_state_cleanup(state); + + /* TODO: + * - handle implicit state grabbing & register allocation like discussed + * - implicit param declarations -- see above + * + * - variable bindings -- ADDRESS + * - deal with explicit array sizes & size mismatches + * - shuddup all my debugging crap + * - grep for XXX + * - multiple vtx attrib binding error + * - What do I do on look ahead for prod 54 & 55? (see arbvp_grammar.txt) + * - misc errors + * - check integer ranges + * - check array index ranges + * - check variable counts + * - param register allocation + * - exercise swizzles and masks + * - error handling + * - generate opcodes + * + Get addres registers for relative offsets in PARAM arrays + * + Properly encode implicit PARAMs and ATTRIBs. + * + ARL + * + SWZ + * + actually emit Mesa opcodes + * - segfaults while freeing stuff + * - OPTION + */ +} diff --git a/src/mesa/main/arbvertparse.h b/src/mesa/main/arbvertparse.h new file mode 100644 index 00000000000..4b4c3fe120f --- /dev/null +++ b/src/mesa/main/arbvertparse.h @@ -0,0 +1,36 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * 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 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 + * BRIAN PAUL 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. + * + * Authors: + * Brian Paul + */ + +#ifndef ARBVERTPARSE_H +#define ARBVERTPARSE_H + +extern void +_mesa_parse_arb_vertex_program(GLcontext * ctx, GLenum target, + const GLubyte * str, GLsizei len, + struct vertex_program *program); + +#endif -- 2.30.2