summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/arbprogram.syn5450
-rw-r--r--src/mesa/shader/arbprogram_syn.h2658
-rw-r--r--src/mesa/shader/grammar.c5559
-rw-r--r--src/mesa/shader/grammar.h160
-rw-r--r--src/mesa/shader/grammar_mesa.c144
-rw-r--r--src/mesa/shader/grammar_mesa.h62
-rw-r--r--src/mesa/shader/grammar_syn.h422
7 files changed, 7316 insertions, 7139 deletions
diff --git a/src/mesa/shader/arbprogram.syn b/src/mesa/shader/arbprogram.syn
index 0fc03e734ac..e6249abd30b 100644
--- a/src/mesa/shader/arbprogram.syn
+++ b/src/mesa/shader/arbprogram.syn
@@ -1,2725 +1,2725 @@
-.syntax program;
-
-/*
- This value must be incremented every time emit code values or structure of the production
- array changes. This value is placed at the beginning of the production array. The loader
- compares the value with its REVISION value. If they do not match, the loader is not up
- to date.
-*/
-.emtcode REVISION 0x07
-
-/* program type */
-.emtcode FRAGMENT_PROGRAM 0x01
-.emtcode VERTEX_PROGRAM 0x02
-
-/* program section */
-.emtcode OPTION 0x01
-.emtcode INSTRUCTION 0x02
-.emtcode DECLARATION 0x03
-.emtcode END 0x04
-
-/* GL_ARB_fragment_program option flags */
-.emtcode ARB_PRECISION_HINT_FASTEST 0x01
-.emtcode ARB_PRECISION_HINT_NICEST 0x02
-.emtcode ARB_FOG_EXP 0x04
-.emtcode ARB_FOG_EXP2 0x08
-.emtcode ARB_FOG_LINEAR 0x10
-
-/* GL_ARB_vertex_program option flags */
-.emtcode ARB_POSITION_INVARIANT 0x20
-
-/* GL_ARB_fragment_program_shadow option flags */
-.emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40
-
-/* GL_ARB_fragment_program instruction class */
-.emtcode OP_ALU_INST 0x00
-.emtcode OP_TEX_INST 0x01
-
-/* GL_ARB_vertex_program instruction class */
-/* OP_ALU_INST */
-
-/* GL_ARB_fragment_program instruction type */
-.emtcode OP_ALU_VECTOR 0x00
-.emtcode OP_ALU_SCALAR 0x01
-.emtcode OP_ALU_BINSC 0x02
-.emtcode OP_ALU_BIN 0x03
-.emtcode OP_ALU_TRI 0x04
-.emtcode OP_ALU_SWZ 0x05
-.emtcode OP_TEX_SAMPLE 0x06
-.emtcode OP_TEX_KIL 0x07
-
-/* GL_ARB_vertex_program instruction type */
-.emtcode OP_ALU_ARL 0x08
-/* OP_ALU_VECTOR */
-/* OP_ALU_SCALAR */
-/* OP_ALU_BINSC */
-/* OP_ALU_BIN */
-/* OP_ALU_TRI */
-/* OP_ALU_SWZ */
-
-/* GL_ARB_fragment_program instruction code */
-.emtcode OP_ABS 0x00
-.emtcode OP_ABS_SAT 0x1B
-.emtcode OP_FLR 0x09
-.emtcode OP_FLR_SAT 0x26
-.emtcode OP_FRC 0x0A
-.emtcode OP_FRC_SAT 0x27
-.emtcode OP_LIT 0x0C
-.emtcode OP_LIT_SAT 0x2A
-.emtcode OP_MOV 0x11
-.emtcode OP_MOV_SAT 0x30
-.emtcode OP_COS 0x1F
-.emtcode OP_COS_SAT 0x20
-.emtcode OP_EX2 0x07
-.emtcode OP_EX2_SAT 0x25
-.emtcode OP_LG2 0x0B
-.emtcode OP_LG2_SAT 0x29
-.emtcode OP_RCP 0x14
-.emtcode OP_RCP_SAT 0x33
-.emtcode OP_RSQ 0x15
-.emtcode OP_RSQ_SAT 0x34
-.emtcode OP_SIN 0x38
-.emtcode OP_SIN_SAT 0x39
-.emtcode OP_SCS 0x35
-.emtcode OP_SCS_SAT 0x36
-.emtcode OP_POW 0x13
-.emtcode OP_POW_SAT 0x32
-.emtcode OP_ADD 0x01
-.emtcode OP_ADD_SAT 0x1C
-.emtcode OP_DP3 0x03
-.emtcode OP_DP3_SAT 0x21
-.emtcode OP_DP4 0x04
-.emtcode OP_DP4_SAT 0x22
-.emtcode OP_DPH 0x05
-.emtcode OP_DPH_SAT 0x23
-.emtcode OP_DST 0x06
-.emtcode OP_DST_SAT 0x24
-.emtcode OP_MAX 0x0F
-.emtcode OP_MAX_SAT 0x2E
-.emtcode OP_MIN 0x10
-.emtcode OP_MIN_SAT 0x2F
-.emtcode OP_MUL 0x12
-.emtcode OP_MUL_SAT 0x31
-.emtcode OP_SGE 0x16
-.emtcode OP_SGE_SAT 0x37
-.emtcode OP_SLT 0x17
-.emtcode OP_SLT_SAT 0x3A
-.emtcode OP_SUB 0x18
-.emtcode OP_SUB_SAT 0x3B
-.emtcode OP_XPD 0x1A
-.emtcode OP_XPD_SAT 0x43
-.emtcode OP_CMP 0x1D
-.emtcode OP_CMP_SAT 0x1E
-.emtcode OP_LRP 0x2B
-.emtcode OP_LRP_SAT 0x2C
-.emtcode OP_MAD 0x0E
-.emtcode OP_MAD_SAT 0x2D
-.emtcode OP_SWZ 0x19
-.emtcode OP_SWZ_SAT 0x3C
-.emtcode OP_TEX 0x3D
-.emtcode OP_TEX_SAT 0x3E
-.emtcode OP_TXB 0x3F
-.emtcode OP_TXB_SAT 0x40
-.emtcode OP_TXP 0x41
-.emtcode OP_TXP_SAT 0x42
-.emtcode OP_KIL 0x28
-
-/* GL_ARB_vertex_program instruction code */
-.emtcode OP_ARL 0x02
-/* OP_ABS */
-/* OP_FLR */
-/* OP_FRC */
-/* OP_LIT */
-/* OP_MOV */
-/* OP_EX2 */
-.emtcode OP_EXP 0x08
-/* OP_LG2 */
-.emtcode OP_LOG 0x0D
-/* OP_RCP */
-/* OP_RSQ */
-/* OP_POW */
-/* OP_ADD */
-/* OP_DP3 */
-/* OP_DP4 */
-/* OP_DPH */
-/* OP_DST */
-/* OP_MAX */
-/* OP_MIN */
-/* OP_MUL */
-/* OP_SGE */
-/* OP_SLT */
-/* OP_SUB */
-/* OP_XPD */
-/* OP_MAD */
-/* OP_SWZ */
-
-/* fragment attribute binding */
-.emtcode FRAGMENT_ATTRIB_COLOR 0x01
-.emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02
-.emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03
-.emtcode FRAGMENT_ATTRIB_POSITION 0x04
-
-/* vertex attribute binding */
-.emtcode VERTEX_ATTRIB_POSITION 0x01
-.emtcode VERTEX_ATTRIB_WEIGHT 0x02
-.emtcode VERTEX_ATTRIB_NORMAL 0x03
-.emtcode VERTEX_ATTRIB_COLOR 0x04
-.emtcode VERTEX_ATTRIB_FOGCOORD 0x05
-.emtcode VERTEX_ATTRIB_TEXCOORD 0x06
-.emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07
-.emtcode VERTEX_ATTRIB_GENERIC 0x08
-
-/* fragment result binding */
-.emtcode FRAGMENT_RESULT_COLOR 0x01
-.emtcode FRAGMENT_RESULT_DEPTH 0x02
-
-/* vertex result binding */
-.emtcode VERTEX_RESULT_POSITION 0x01
-.emtcode VERTEX_RESULT_COLOR 0x02
-.emtcode VERTEX_RESULT_FOGCOORD 0x03
-.emtcode VERTEX_RESULT_POINTSIZE 0x04
-.emtcode VERTEX_RESULT_TEXCOORD 0x05
-
-/* texture target */
-.emtcode TEXTARGET_1D 0x01
-.emtcode TEXTARGET_2D 0x02
-.emtcode TEXTARGET_3D 0x03
-.emtcode TEXTARGET_RECT 0x04
-.emtcode TEXTARGET_CUBE 0x05
-/* GL_ARB_fragment_program_shadow */
-.emtcode TEXTARGET_SHADOW1D 0x06
-.emtcode TEXTARGET_SHADOW2D 0x07
-.emtcode TEXTARGET_SHADOWRECT 0x08
-
-/* face type */
-.emtcode FACE_FRONT 0x00
-.emtcode FACE_BACK 0x01
-
-/* color type */
-.emtcode COLOR_PRIMARY 0x00
-.emtcode COLOR_SECONDARY 0x01
-
-/* component */
-.emtcode COMPONENT_X 0x00
-.emtcode COMPONENT_Y 0x01
-.emtcode COMPONENT_Z 0x02
-.emtcode COMPONENT_W 0x03
-.emtcode COMPONENT_0 0x04
-.emtcode COMPONENT_1 0x05
-
-/* array index type */
-.emtcode ARRAY_INDEX_ABSOLUTE 0x00
-.emtcode ARRAY_INDEX_RELATIVE 0x01
-
-/* matrix name */
-.emtcode MATRIX_MODELVIEW 0x01
-.emtcode MATRIX_PROJECTION 0x02
-.emtcode MATRIX_MVP 0x03
-.emtcode MATRIX_TEXTURE 0x04
-.emtcode MATRIX_PALETTE 0x05
-.emtcode MATRIX_PROGRAM 0x06
-
-/* matrix modifier */
-.emtcode MATRIX_MODIFIER_IDENTITY 0x00
-.emtcode MATRIX_MODIFIER_INVERSE 0x01
-.emtcode MATRIX_MODIFIER_TRANSPOSE 0x02
-.emtcode MATRIX_MODIFIER_INVTRANS 0x03
-
-/* constant type */
-.emtcode CONSTANT_SCALAR 0x01
-.emtcode CONSTANT_VECTOR 0x02
-
-/* program param type */
-.emtcode PROGRAM_PARAM_ENV 0x01
-.emtcode PROGRAM_PARAM_LOCAL 0x02
-
-/* register type */
-.emtcode REGISTER_ATTRIB 0x01
-.emtcode REGISTER_PARAM 0x02
-.emtcode REGISTER_RESULT 0x03
-.emtcode REGISTER_ESTABLISHED_NAME 0x04
-
-/* param binding */
-.emtcode PARAM_NULL 0x00
-.emtcode PARAM_ARRAY_ELEMENT 0x01
-.emtcode PARAM_STATE_ELEMENT 0x02
-.emtcode PARAM_PROGRAM_ELEMENT 0x03
-.emtcode PARAM_PROGRAM_ELEMENTS 0x04
-.emtcode PARAM_CONSTANT 0x05
-
-/* param state property */
-.emtcode STATE_MATERIAL 0x01
-.emtcode STATE_LIGHT 0x02
-.emtcode STATE_LIGHT_MODEL 0x03
-.emtcode STATE_LIGHT_PROD 0x04
-.emtcode STATE_FOG 0x05
-.emtcode STATE_MATRIX_ROWS 0x06
-/* GL_ARB_fragment_program */
-.emtcode STATE_TEX_ENV 0x07
-.emtcode STATE_DEPTH 0x08
-/* GL_ARB_vertex_program */
-.emtcode STATE_TEX_GEN 0x09
-.emtcode STATE_CLIP_PLANE 0x0A
-.emtcode STATE_POINT 0x0B
-
-/* state material property */
-.emtcode MATERIAL_AMBIENT 0x01
-.emtcode MATERIAL_DIFFUSE 0x02
-.emtcode MATERIAL_SPECULAR 0x03
-.emtcode MATERIAL_EMISSION 0x04
-.emtcode MATERIAL_SHININESS 0x05
-
-/* state light property */
-.emtcode LIGHT_AMBIENT 0x01
-.emtcode LIGHT_DIFFUSE 0x02
-.emtcode LIGHT_SPECULAR 0x03
-.emtcode LIGHT_POSITION 0x04
-.emtcode LIGHT_ATTENUATION 0x05
-.emtcode LIGHT_HALF 0x06
-.emtcode LIGHT_SPOT_DIRECTION 0x07
-
-/* state light model property */
-.emtcode LIGHT_MODEL_AMBIENT 0x01
-.emtcode LIGHT_MODEL_SCENECOLOR 0x02
-
-/* state light product property */
-.emtcode LIGHT_PROD_AMBIENT 0x01
-.emtcode LIGHT_PROD_DIFFUSE 0x02
-.emtcode LIGHT_PROD_SPECULAR 0x03
-
-/* state texture environment property */
-.emtcode TEX_ENV_COLOR 0x01
-
-/* state texture generation coord property */
-.emtcode TEX_GEN_EYE 0x01
-.emtcode TEX_GEN_OBJECT 0x02
-
-/* state fog property */
-.emtcode FOG_COLOR 0x01
-.emtcode FOG_PARAMS 0x02
-
-/* state depth property */
-.emtcode DEPTH_RANGE 0x01
-
-/* state point parameters property */
-.emtcode POINT_SIZE 0x01
-.emtcode POINT_ATTENUATION 0x02
-
-/* declaration */
-.emtcode ATTRIB 0x01
-.emtcode PARAM 0x02
-.emtcode TEMP 0x03
-.emtcode OUTPUT 0x04
-.emtcode ALIAS 0x05
-/* GL_ARB_vertex_program */
-.emtcode ADDRESS 0x06
-
-/* error messages */
-.errtext UNKNOWN_PROGRAM_SIGNATURE "1001: '$e_signature$': unknown program signature"
-.errtext MISSING_END_OR_INVALID_STATEMENT "1002: '$e_statement$': invalid statement"
-.errtext CODE_AFTER_END "1003: '$e_statement$': code after 'END' keyword"
-.errtext INVALID_PROGRAM_OPTION "1004: '$e_identifier$': invalid program option"
-.errtext EXT_SWIZ_COMP_EXPECTED "1005: extended swizzle component expected but '$e_token$' found"
-.errtext TEX_TARGET_EXPECTED "1006: texture target expected but '$e_token$' found"
-.errtext TEXTURE_EXPECTED "1007: 'texture' expected but '$e_identifier$' found"
-.errtext SOURCE_REGISTER_EXPECTED "1008: source register expected but '$e_token$' found"
-.errtext DESTINATION_REGISTER_EXPECTED "1009: destination register expected but '$e_token$' found"
-.errtext INVALID_ADDRESS_COMPONENT "1010: '$e_identifier$': invalid address component"
-.errtext INVALID_ADDRESS_WRITEMASK "1011: '$e_identifier$': invalid address writemask"
-.errtext INVALID_COMPONENT "1012: '$e_charordigit$': invalid component"
-.errtext INVALID_SUFFIX "1013: '$e_identifier$': invalid suffix"
-.errtext INVALID_WRITEMASK "1014: '$e_identifier$': invalid writemask"
-.errtext FRAGMENT_EXPECTED "1015: 'fragment' expected but '$e_identifier$' found"
-.errtext VERTEX_EXPECTED "1016: 'vertex' expected but '$e_identifier$' found"
-.errtext INVALID_FRAGMENT_PROPERTY "1017: '$e_identifier$': invalid fragment property"
-.errtext INVALID_VERTEX_PROPERTY "1018: '$e_identifier$': invalid vertex property"
-.errtext INVALID_STATE_PROPERTY "1019: '$e_identifier$': invalid state property"
-.errtext INVALID_MATERIAL_PROPERTY "1020: '$e_identifier$': invalid material property"
-.errtext INVALID_LIGHT_PROPERTY "1021: '$e_identifier$': invalid light property"
-.errtext INVALID_SPOT_PROPERTY "1022: '$e_identifier$': invalid spot property"
-.errtext INVALID_LIGHTMODEL_PROPERTY "1023: '$e_identifier$': invalid light model property"
-.errtext INVALID_LIGHTPROD_PROPERTY "1024: '$e_identifier$': invalid light product property"
-.errtext INVALID_TEXENV_PROPERTY "1025: '$e_identifier$': invalid texture environment property"
-.errtext INVALID_TEXGEN_PROPERTY "1026: '$e_identifier$': invalid texture generating property"
-.errtext INVALID_TEXGEN_COORD "1027: '$e_identifier$': invalid texture generating coord"
-.errtext INVALID_FOG_PROPERTY "1028: '$e_identifier$': invalid fog property"
-.errtext INVALID_DEPTH_PROPERTY "1029: '$e_identifier$': invalid depth property"
-.errtext INVALID_CLIPPLANE_PROPERTY "1030: '$e_identifier$': invalid clip plane property"
-.errtext INVALID_POINT_PROPERTY "1031: '$e_identifier$': invalid point property"
-.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED "1032: matrix row selector or modifier expected but '$e_token$' found"
-.errtext INVALID_MATRIX_NAME "1033: '$e_identifier$': invalid matrix name"
-.errtext INVALID_PROGRAM_PROPERTY "1034: '$e_identifier$': invalid program property"
-.errtext RESULT_EXPECTED "1035: 'result' expected but '$e_token$' found"
-.errtext INVALID_RESULT_PROPERTY "1036: '$e_identifier$': invalid result property"
-.errtext INVALID_FACE_PROPERTY "1037: '$e_identifier$': invalid face property"
-.errtext INVALID_COLOR_PROPERTY "1038: '$e_identifier$': invalid color property"
-.errtext IDENTIFIER_EXPECTED "1039: identifier expected but '$e_token$' found"
-.errtext RESERVED_KEYWORD "1040: use of reserved keyword as an identifier"
-.errtext INTEGER_EXPECTED "1041: integer value expected but '$e_token$' found"
-.errtext MISSING_SEMICOLON "1042: ';' expected but '$e_token$' found"
-.errtext MISSING_COMMA "1043: ',' expected but '$e_token$' found"
-.errtext MISSING_LBRACKET "1044: '[' expected but '$e_token$' found"
-.errtext MISSING_RBRACKET "1045: ']' expected but '$e_token$' found"
-.errtext MISSING_DOT "1046: '.' expected but '$e_token$' found"
-.errtext MISSING_EQUAL "1047: '=' expected but '$e_token$' found"
-.errtext MISSING_LBRACE "1048: '{' expected but '$e_token$' found"
-.errtext MISSING_RBRACE "1049: '}' expected but '$e_token$' found"
-.errtext MISSING_DOTDOT "1050: '..' expected but '$e_token$' found"
-.errtext MISSING_FRACTION_OR_EXPONENT "1051: missing fraction part or exponent"
-.errtext MISSING_DOT_OR_EXPONENT "1052: missing '.' or exponent"
-.errtext EXPONENT_VALUE_EXPECTED "1053: exponent value expected"
-.errtext INTEGER_OUT_OF_RANGE "1054: integer value out of range"
-.errtext OPERATION_NEEDS_DESTINATION_VARIABLE "1055: operation needs destination variable"
-.errtext OPERATION_NEEDS_SOURCE_VARIABLE "1056: operation needs source variable"
-.errtext ADDRESS_REGISTER_EXPECTED "1057: address register expected but '$e_token$' found"
-.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED "1058: address register or integer literal expected but '$e_token$' found"
-
-/* extension presence condition registers */
-
-/* GL_ARB_vertex_blend */
-/* GL_EXT_vertex_weighting */
-.regbyte vertex_blend 0x00
-
-/* GL_ARB_matrix_palette */
-.regbyte matrix_palette 0x00
-
-/* GL_ARB_point_parameters */
-/* GL_EXT_point_parameters */
-.regbyte point_parameters 0x01
-
-/* GL_EXT_secondary_color */
-.regbyte secondary_color 0x01
-
-/* GL_EXT_fog_coord */
-.regbyte fog_coord 0x01
-
-/* GL_EXT_texture_rectangle */
-/* GL_NV_texture_rectangle */
-.regbyte texture_rectangle 0x01
-
-/* GL_ARB_fragment_program_shadow */
-.regbyte fragment_program_shadow 0x00
-
-/* option presence condition registers */
-/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */
-/* register is set to 1 to indicate that the OPTION was specified. */
-
-/* GL_ARB_fragment_program */
-.regbyte ARB_precision_hint_fastest 0x00
-.regbyte ARB_precision_hint_nicest 0x00
-.regbyte ARB_fog_exp 0x00
-.regbyte ARB_fog_exp2 0x00
-.regbyte ARB_fog_linear 0x00
-
-/* GL_ARB_vertex_program */
-.regbyte ARB_position_invariant 0x00
-
-/* GL_ARB_fragment_program_shadow */
-.regbyte ARB_fragment_program_shadow 0x00
-
-/* program target condition register */
-/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */
-/* to distinguish between them we need a register that will store for us the current target. */
-/* the client will typically set the register to apropriate value before parsing a particular */
-/* program. the mapping between program targets and their values is listed below. */
-/* */
-/* program target register value */
-/* ---------------------------------------------- */
-/* FRAGMENT_PROGRAM 0x10 */
-/* VERTEX_PROGRAM 0x20 */
-/* */
-/* the initial value of the register is 0 to catch potential errors with not setting the register */
-/* with the proper value. */
-.regbyte program_target 0x00
-
-/*
- <program> ::= <optionSequence> <statementSequence> "END"
-*/
-program
- programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;
-programs
- .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or
- .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;
-frag_program_1_0
- '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and
- optional_space .and fp_optionSequence .and fp_statementSequence .and
- "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
- '\0' .error CODE_AFTER_END;
-vert_program_1_0
- '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and
- optional_space .and vp_optionSequence .and vp_statementSequence .and
- "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
- '\0' .error CODE_AFTER_END;
-
-/*
- <optionSequence> ::= <optionSequence> <option>
- | ""
-*/
-fp_optionSequence
- .loop fp_option;
-vp_optionSequence
- .loop vp_option;
-
-/*
- <option> ::= "OPTION" <identifier> ";"
-
-NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of
- these options is encountered, the other one is automatically disabled.
- the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear.
-*/
-fp_option
- "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
- fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
-vp_option
- "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
- vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
-fp_optionString
- .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest"
- .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or
- .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest"
- .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or
- fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or
- fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or
- fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or
- .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow"
- .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;
-vp_optionString
- "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;
-fp_ARB_fog_exp
- .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp";
-fp_ARB_fog_exp2
- .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2";
-fp_ARB_fog_linear
- .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear";
-
-/*
- <statementSequence> ::= <statementSequence> <statement>
- | ""
-*/
-fp_statementSequence
- .loop fp_statement;
-vp_statementSequence
- .loop vp_statement;
-
-/*
- <statement> ::= <instruction> ";"
- | <namingStatement> ";"
-
-NOTE: ".emit $" in the definitions below means that we output instruction position (offset of
- the first character of instruction) for program debugging purposes.
-*/
-fp_statement
- fp_statement_1 .or fp_statement_2;
-vp_statement
- vp_statement_1 .or vp_statement_2;
-fp_statement_1
- fp_instruction .emit INSTRUCTION .emit $ .and semicolon;
-fp_statement_2
- fp_namingStatement .emit DECLARATION .and semicolon;
-vp_statement_1
- vp_instruction .emit INSTRUCTION .emit $ .and semicolon;
-vp_statement_2
- vp_namingStatement .emit DECLARATION .and semicolon;
-
-/*
-fragment program
- <instruction> ::= <ALUInstruction>
- | <TexInstruction>
-
-vertex program
- <instruction> ::= <ARL_instruction>
- | <VECTORop_instruction>
- | <SCALARop_instruction>
- | <BINSCop_instruction>
- | <BINop_instruction>
- | <TRIop_instruction>
- | <SWZ_instruction>
-*/
-fp_instruction
- ALUInstruction .emit OP_ALU_INST .or
- TexInstruction .emit OP_TEX_INST;
-vp_instruction
- ARL_instruction .emit OP_ALU_ARL .or
- vp_VECTORop_instruction .emit OP_ALU_VECTOR .or
- vp_SCALARop_instruction .emit OP_ALU_SCALAR .or
- vp_BINSCop_instruction .emit OP_ALU_BINSC .or
- vp_BINop_instruction .emit OP_ALU_BIN .or
- vp_TRIop_instruction .emit OP_ALU_TRI .or
- vp_SWZ_instruction .emit OP_ALU_SWZ;
-
-/*
-fragment program
- <ALUInstruction> ::= <VECTORop_instruction>
- | <SCALARop_instruction>
- | <BINSCop_instruction>
- | <BINop_instruction>
- | <TRIop_instruction>
- | <SWZ_instruction>
-*/
-ALUInstruction
- fp_VECTORop_instruction .emit OP_ALU_VECTOR .or
- fp_SCALARop_instruction .emit OP_ALU_SCALAR .or
- fp_BINSCop_instruction .emit OP_ALU_BINSC .or
- fp_BINop_instruction .emit OP_ALU_BIN .or
- fp_TRIop_instruction .emit OP_ALU_TRI .or
- fp_SWZ_instruction .emit OP_ALU_SWZ;
-
-/*
-fragment program
- <TexInstruction> ::= <SAMPLE_instruction>
- | <KIL_instruction>
-*/
-TexInstruction
- SAMPLE_instruction .emit OP_TEX_SAMPLE .or
- KIL_instruction .emit OP_TEX_KIL;
-
-/*
-vertex program
- <ARL_instruction> ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>
-*/
-ARL_instruction
- "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;
-
-/*
-fragment program
- <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> ","
- <vectorSrcReg>
-
-vertex program
- <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>
-*/
-fp_VECTORop_instruction
- fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;
-vp_VECTORop_instruction
- vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;
-
-/*
-fragment program
- <VECTORop> ::= "ABS" | "ABS_SAT"
- | "FLR" | "FLR_SAT"
- | "FRC" | "FRC_SAT"
- | "LIT" | "LIT_SAT"
- | "MOV" | "MOV_SAT"
-
-vertex program
- <VECTORop> ::= "ABS"
- | "FLR"
- | "FRC"
- | "LIT"
- | "MOV"
-*/
-fp_VECTORop
- "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or
- "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or
- "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or
- "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or
- "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT;
-vp_VECTORop
- "ABS" .emit OP_ABS .or
- "FLR" .emit OP_FLR .or
- "FRC" .emit OP_FRC .or
- "LIT" .emit OP_LIT .or
- "MOV" .emit OP_MOV;
-
-/*
- <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>
-*/
-fp_SCALARop_instruction
- fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;
-vp_SCALARop_instruction
- vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;
-
-/*
-fragment program
- <SCALARop> ::= "COS" | "COS_SAT"
- | "EX2" | "EX2_SAT"
- | "LG2" | "LG2_SAT"
- | "RCP" | "RCP_SAT"
- | "RSQ" | "RSQ_SAT"
- | "SIN" | "SIN_SAT"
- | "SCS" | "SCS_SAT"
-
-vertex program
- <SCALARop> ::= "EX2"
- | "EXP"
- | "LG2"
- | "LOG"
- | "RCP"
- | "RSQ"
-*/
-fp_SCALARop
- "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or
- "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or
- "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or
- "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or
- "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or
- "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or
- "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT;
-vp_SCALARop
- "EX2" .emit OP_EX2 .or
- "EXP" .emit OP_EXP .or
- "LG2" .emit OP_LG2 .or
- "LOG" .emit OP_LOG .or
- "RCP" .emit OP_RCP .or
- "RSQ" .emit OP_RSQ;
-
-/*
- <BINSCop_instruction> ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","
- <scalarSrcReg>
-*/
-fp_BINSCop_instruction
- fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and
- fp_scalarSrcReg;
-vp_BINSCop_instruction
- vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and
- vp_scalarSrcReg;
-
-/*
-fragment program
- <BINSCop> ::= "POW" | "POW_SAT"
-
-vertex program
- <BINSCop> ::= "POW"
-*/
-fp_BINSCop
- "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT;
-vp_BINSCop
- "POW" .emit OP_POW;
-
-/*
-fragment program
- <BINop_instruction> ::= <BINop> <maskedDstReg> ","
- <vectorSrcReg> "," <vectorSrcReg>
-
-vertex program
- <BINop_instruction> ::= <BINop> <maskedDstReg> ","
- <swizzleSrcReg> "," <swizzleSrcReg>
-*/
-fp_BINop_instruction
- fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
- vectorSrcReg;
-vp_BINop_instruction
- vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
- swizzleSrcReg;
-
-/*
-fragment program
- <BINop> ::= "ADD" | "ADD_SAT"
- | "DP3" | "DP3_SAT"
- | "DP4" | "DP4_SAT"
- | "DPH" | "DPH_SAT"
- | "DST" | "DST_SAT"
- | "MAX" | "MAX_SAT"
- | "MIN" | "MIN_SAT"
- | "MUL" | "MUL_SAT"
- | "SGE" | "SGE_SAT"
- | "SLT" | "SLT_SAT"
- | "SUB" | "SUB_SAT"
- | "XPD" | "XPD_SAT"
-
-vertex program
- <BINop> ::= "ADD"
- | "DP3"
- | "DP4"
- | "DPH"
- | "DST"
- | "MAX"
- | "MIN"
- | "MUL"
- | "SGE"
- | "SLT"
- | "SUB"
- | "XPD"
-*/
-fp_BINop
- "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or
- "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or
- "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or
- "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or
- "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or
- "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or
- "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or
- "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or
- "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or
- "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or
- "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or
- "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT;
-vp_BINop
- "ADD" .emit OP_ADD .or
- "DP3" .emit OP_DP3 .or
- "DP4" .emit OP_DP4 .or
- "DPH" .emit OP_DPH .or
- "DST" .emit OP_DST .or
- "MAX" .emit OP_MAX .or
- "MIN" .emit OP_MIN .or
- "MUL" .emit OP_MUL .or
- "SGE" .emit OP_SGE .or
- "SLT" .emit OP_SLT .or
- "SUB" .emit OP_SUB .or
- "XPD" .emit OP_XPD;
-
-/*
-fragment program
- <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
- <vectorSrcReg> "," <vectorSrcReg> ","
- <vectorSrcReg>
-
-vertex program
- <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
- <swizzleSrcReg> "," <swizzleSrcReg> ","
- <swizzleSrcReg>
-*/
-fp_TRIop_instruction
- fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
- vectorSrcReg .and comma .and vectorSrcReg;
-vp_TRIop_instruction
- vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
- swizzleSrcReg .and comma .and swizzleSrcReg;
-
-/*
-fragment program
- <TRIop> ::= "CMP" | "CMP_SAT"
- | "LRP" | "LRP_SAT"
- | "MAD" | "MAD_SAT"
-
-vertex program
- <TRIop> ::= "MAD"
-*/
-fp_TRIop
- "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or
- "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or
- "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT;
-vp_TRIop
- "MAD" .emit OP_MAD;
-
-/*
-fragment program
- <SWZ_instruction> ::= <SWZop> <maskedDstReg> ","
- <srcReg> "," <extendedSwizzle>
-
-vertex program
- <SWZ_instruction> ::= "SWZ" <maskedDstReg> "," <srcReg> ","
- <extendedSwizzle>
-*/
-fp_SWZ_instruction
- SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and
- fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
-vp_SWZ_instruction
- "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and
- vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <SWZop> ::= "SWZ" | "SWZ_SAT"
-*/
-SWZop
- "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT;
-
-/*
-fragment program
- <SAMPLE_instruction> ::= <SAMPLEop> <maskedDstReg> ","
- <vectorSrcReg> "," <texImageUnit> ","
- <texTarget>
-*/
-SAMPLE_instruction
- SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
- texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;
-
-/*
-fragment program
- <SAMPLEop> ::= "TEX" | "TEX_SAT"
- | "TXP" | "TXP_SAT"
- | "TXB" | "TXB_SAT"
-*/
-SAMPLEop
- "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or
- "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or
- "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT;
-
-/*
-fragment program
- <KIL_instruction> ::= "KIL" <vectorSrcReg>
-*/
-KIL_instruction
- "KIL" .emit OP_KIL .and space_src .and vectorSrcReg;
-
-/*
-fragment program
- <texImageUnit> ::= "texture" <optTexImageUnitNum>
-*/
-texImageUnit
- "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum;
-
-/*
-fragment program
- <texTarget> ::= "1D"
- | "2D"
- | "3D"
- | "CUBE"
- | "RECT"
- | <shadowTarget> (if option ARB_fragment_program_shadow present)
-*/
-texTarget
- "1D" .emit TEXTARGET_1D .or
- "2D" .emit TEXTARGET_2D .or
- "3D" .emit TEXTARGET_3D .or
- .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or
- "CUBE" .emit TEXTARGET_CUBE .or
- .if (ARB_fragment_program_shadow != 0x00) shadowTarget;
-
-/*
-GL_ARB_fragment_program_shadow
- <shadowTarget> ::= "SHADOW1D"
- | "SHADOW2D"
- | "SHADOWRECT"
-*/
-shadowTarget
- "SHADOW1D" .emit TEXTARGET_SHADOW1D .or
- "SHADOW2D" .emit TEXTARGET_SHADOW2D .or
- .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT;
-
-/*
-fragment program
- <optTexImageUnitNum> ::= ""
- | "[" <texImageUnitNum> "]"
-*/
-optTexImageUnitNum
- optTexImageUnitNum_1 .or .true .emit 0x00;
-optTexImageUnitNum_1
- lbracket_ne .and texImageUnitNum .and rbracket;
-
-/*
-fragment program
- <texImageUnitNum> ::= <integer> from 0 to
- MAX_TEXTURE_IMAGE_UNITS_ARB-1
-*/
-texImageUnitNum
- integer;
-
-/*
- <scalarSrcReg> ::= <optionalSign> <srcReg> <scalarSuffix>
-*/
-fp_scalarSrcReg
- optionalSign .and fp_srcReg .and fp_scalarSuffix;
-vp_scalarSrcReg
- optionalSign .and vp_srcReg .and vp_scalarSuffix;
-
-/*
-vertex program
- <swizzleSrcReg> ::= <optionalSign> <srcReg> <swizzleSuffix>
-*/
-swizzleSrcReg
- optionalSign .and vp_srcReg .and swizzleSuffix;
-
-/*
-fragment program
- <vectorSrcReg> ::= <optionalSign> <srcReg> <optionalSuffix>
-*/
-vectorSrcReg
- optionalSign .and fp_srcReg .and optionalSuffix;
-
-/*
- <maskedDstReg> ::= <dstReg> <optionalMask>
-*/
-fp_maskedDstReg
- fp_dstReg .and fp_optionalMask;
-vp_maskedDstReg
- vp_dstReg .and vp_optionalMask;
-
-/*
-vertex program
- <maskedAddrReg> ::= <addrReg> <addrWriteMask>
-*/
-maskedAddrReg
- addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;
-
-/*
-fragment program
- <extendedSwizzle> ::= <xyzwExtendedSwizzle>
- | <rgbaExtendedSwizzle>
-
-vertex program
- <extendedSwizzle> ::= <extSwizComp> "," <extSwizComp> ","
- <extSwizComp> "," <extSwizComp>
-
-NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez
-*/
-fp_extendedSwizzle
- rgbaExtendedSwizzle .or xyzwExtendedSwizzle;
-vp_extendedSwizzle
- extSwizComp .and comma .and
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <xyzwExtendedSwizzle> ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> ","
- <xyzwExtSwizComp> "," <xyzwExtSwizComp>
-*/
-xyzwExtendedSwizzle
- xyzwExtSwizComp .and comma .and
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <rgbaExtendedSwizzle> ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> ","
- <rgbaExtSwizComp> "," <rgbaExtSwizComp>
-*/
-rgbaExtendedSwizzle
- rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or
- rgbaExtendedSwizzle_4;
-rgbaExtendedSwizzle_1
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;
-rgbaExtendedSwizzle_2
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
- rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-rgbaExtendedSwizzle_3
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-rgbaExtendedSwizzle_4
- rgbaExtSwizComp_alpha .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
-
-/*
-fragment program
- <xyzwExtSwizComp> ::= <optionalSign> <xyzwExtSwizSel>
-*/
-xyzwExtSwizComp
- optionalSign .and xyzwExtSwizSel;
-
-/*
-fragment program
- <rgbaExtSwizComp> ::= <optionalSign> <rgbaExtSwizSel>
-*/
-rgbaExtSwizComp
- optionalSign .and rgbaExtSwizSel;
-rgbaExtSwizComp_digit
- optionalSign .and rgbaExtSwizSel_digit;
-rgbaExtSwizComp_alpha
- optionalSign .and rgbaExtSwizSel_alpha;
-
-/*
-vertex program
- <extSwizComp> ::= <optionalSign> <extSwizSel>
-*/
-extSwizComp
- optionalSign .and extSwizSel;
-
-/*
-fragment program
- <xyzwExtSwizSel> ::= "0"
- | "1"
- | <xyzwComponent>
-*/
-xyzwExtSwizSel
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single;
-
-/*
-fragment program
- <rgbaExtSwizSel> ::= "0"
- | "1"
- | <rgbaComponent>
-*/
-rgbaExtSwizSel
- rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;
-rgbaExtSwizSel_digit
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1;
-rgbaExtSwizSel_alpha
- rgbaComponent_single;
-
-/*
-vertex program
- <extSwizSel> ::= "0"
- | "1"
- | <component>
-*/
-extSwizSel
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single;
-
-/*
-fragment program
- <srcReg> ::= <fragmentAttribReg>
- | <temporaryReg>
- | <progParamReg>
-
-vertex program
- <srcReg> ::= <vertexAttribReg>
- | <temporaryReg>
- | <progParamReg>
-*/
-fp_srcReg
- fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
-vp_srcReg
- vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
-fp_srcReg_1
- fragmentAttribReg .emit REGISTER_ATTRIB .or
- fp_progParamReg .emit REGISTER_PARAM .or
- fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-vp_srcReg_1
- vertexAttribReg .emit REGISTER_ATTRIB .or
- vp_progParamReg .emit REGISTER_PARAM .or
- vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-
-/*
-fragment program
- <dstReg> ::= <temporaryReg>
- | <fragmentResultReg>
-
-vertex program
- <dstReg> ::= <temporaryReg>
- | <vertexResultReg>
-*/
-fp_dstReg
- fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
-vp_dstReg
- vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
-fp_dstReg_1
- fragmentResultReg .emit REGISTER_RESULT .or
- fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-vp_dstReg_1
- vertexResultReg .emit REGISTER_RESULT .or
- vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
-
-/*
-fragment program
- <fragmentAttribReg> ::= <establishedName>
- | <fragAttribBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
-*/
-fragmentAttribReg
- /*fp_establishedName .or */fragAttribBinding;
-
-/*
-vertex program
- <vertexAttribReg> ::= <establishedName>
- | <vtxAttribBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
-*/
-vertexAttribReg
- vtxAttribBinding;
-
-/*
- <temporaryReg> ::= <establishedName>
-*/
-fp_temporaryReg
- fp_establishedName_no_error_on_identifier;
-vp_temporaryReg
- vp_establishedName_no_error_on_identifier;
-
-/*
-fragment program
- <progParamReg> ::= <progParamSingle>
- | <progParamArray> "[" <progParamArrayAbs> "]"
- | <paramSingleItemUse>
-
-vertex program
- <progParamReg> ::= <progParamSingle>
- | <progParamArray> "[" <progParamArrayMem> "]"
- | <paramSingleItemUse>
-*/
-fp_progParamReg
- fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;
-vp_progParamReg
- vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;
-fp_progParamReg_1
- fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and
- rbracket;
-vp_progParamReg_1
- vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and
- rbracket;
-
-/*
- <progParamSingle> ::= <establishedName>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
-*/
-fp_progParamSingle
- .false;
-vp_progParamSingle
- .false;
-
-/*
- <progParamArray> ::= <establishedName>
-*/
-fp_progParamArray
- fp_establishedName_no_error_on_identifier;
-vp_progParamArray
- vp_establishedName_no_error_on_identifier;
-
-/*
-vertex program
- <progParamArrayMem> ::= <progParamArrayAbs>
- | <progParamArrayRel>
-*/
-progParamArrayMem
- progParamArrayAbs .or progParamArrayRel;
-
-/*
- <progParamArrayAbs> ::= <integer>
-*/
-progParamArrayAbs
- integer_ne .emit ARRAY_INDEX_ABSOLUTE;
-
-/*
-vertex program
- <progParamArrayRel> ::= <addrReg> <addrComponent> <addrRegRelOffset>
-*/
-progParamArrayRel
- addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and
- addrComponent .and addrRegRelOffset;
-
-/*
-vertex program
- <addrRegRelOffset> ::= ""
- | "+" <addrRegPosOffset>
- | "-" <addrRegNegOffset>
-*/
-addrRegRelOffset
- addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;
-addrRegRelOffset_1
- plus_ne .and addrRegPosOffset;
-addrRegRelOffset_2
- minus_ne .and addrRegNegOffset;
-
-/*
-vertex program
- <addrRegPosOffset> ::= <integer> from 0 to 63
-*/
-addrRegPosOffset
- integer_0_63;
-
-/*
-vertex program
- <addrRegNegOffset> ::= <integer> from 0 to 64
-*/
-addrRegNegOffset
- integer_0_64;
-
-/*
-fragment program
- <fragmentResultReg> ::= <establishedName>
- | <resultBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
-*/
-fragmentResultReg
- fp_resultBinding;
-
-/*
-vertex program
- <vertexResultReg> ::= <establishedName>
- | <resultBinding>
-
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
-*/
-vertexResultReg
- vp_resultBinding;
-
-/*
-vertex program
- <addrReg> ::= <establishedName>
-*/
-addrReg
- vp_establishedName_no_error_on_identifier;
-
-/*
-vertex program
- <addrComponent> ::= "." "x"
-*/
-addrComponent
- dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X
- .emit COMPONENT_X .emit COMPONENT_X;
-
-/*
-vertex program
- <addrWriteMask> ::= "." "x"
-*/
-addrWriteMask
- dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;
-
-/*
- <scalarSuffix> ::= "." <component>
-*/
-fp_scalarSuffix
- dot .and fp_component_single .error INVALID_COMPONENT;
-vp_scalarSuffix
- dot .and vp_component_single .error INVALID_COMPONENT;
-
-/*
-vertex program
- <swizzleSuffix> ::= ""
- | "." <component>
- | "." <component> <component>
- <component> <component>
-*/
-swizzleSuffix
- swizzleSuffix_1 .or
- .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
-swizzleSuffix_1
- dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;
-swizzleSuffix_2
- swizzleSuffix_3 .or swizzleSuffix_4;
-swizzleSuffix_3
- vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and
- vp_component_multi .error INVALID_COMPONENT;
-swizzleSuffix_4
- "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
- "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
- "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
-
-/*
-fragment program
- <optionalSuffix> ::= ""
- | "." <component>
- | "." <xyzwComponent> <xyzwComponent>
- <xyzwComponent> <xyzwComponent>
- | "." <rgbaComponent> <rgbaComponent>
- <rgbaComponent> <rgbaComponent>
-*/
-optionalSuffix
- optionalSuffix_1 .or
- .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
-optionalSuffix_1
- dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;
-optionalSuffix_2
- optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;
-optionalSuffix_3
- xyzwComponent_multi .and xyzwComponent_multi .and
- xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;
-optionalSuffix_4
- rgbaComponent_multi .and rgbaComponent_multi .and
- rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;
-optionalSuffix_5
- "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
- "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
- "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or
- "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
- "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
- "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
- "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
-
-/*
-fragment program
- <component> ::= <xyzwComponent>
- | <rgbaComponent>
-
-vertex program
- <component> ::= "x"
- | "y"
- | "z"
- | "w"
-*/
-fp_component_single
- xyzwComponent_single .or rgbaComponent_single;
-vp_component_multi
- 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
- 'w' .emit COMPONENT_W;
-vp_component_single
- "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W;
-
-/*
-fragment program
- <xyzwComponent> ::= "x" | "y" | "z" | "w"
-*/
-xyzwComponent_multi
- 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
- 'w' .emit COMPONENT_W;
-xyzwComponent_single
- "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
- "w" .emit COMPONENT_W;
-
-/*
-fragment program
- <rgbaComponent> ::= "r" | "g" | "b" | "a"
-*/
-rgbaComponent_multi
- 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or
- 'a' .emit COMPONENT_W;
-rgbaComponent_single
- "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or
- "a" .emit COMPONENT_W;
-
-/*
-fragment program
- <optionalMask> ::= ""
- | <xyzwMask>
- | <rgbaMask>
-
-vertex program
- <optionalMask> ::= ""
- | "." "x"
- | "." "y"
- | "." "xy"
- | "." "z"
- | "." "xz"
- | "." "yz"
- | "." "xyz"
- | "." "w"
- | "." "xw"
- | "." "yw"
- | "." "xyw"
- | "." "zw"
- | "." "xzw"
- | "." "yzw"
- | "." "xyzw"
-
-NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez
-*/
-fp_optionalMask
- rgbaMask .or xyzwMask .or .true .emit 0x0F;
-vp_optionalMask
- xyzwMask .or .true .emit 0x0F;
-
-/*
-fragment program
- <xyzwMask> ::= "." "x"
- | "." "y"
- | "." "xy"
- | "." "z"
- | "." "xz"
- | "." "yz"
- | "." "xyz"
- | "." "w"
- | "." "xw"
- | "." "yw"
- | "." "xyw"
- | "." "zw"
- | "." "xzw"
- | "." "yzw"
- | "." "xyzw"
-
-NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>.
-*/
-xyzwMask
- dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;
-xyzwMask_1
- "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or
- "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or
- "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or
- "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01;
-
-/*
-fragment program
- <rgbaMask> ::= "." "r"
- | "." "g"
- | "." "rg"
- | "." "b"
- | "." "rb"
- | "." "gb"
- | "." "rgb"
- | "." "a"
- | "." "ra"
- | "." "ga"
- | "." "rga"
- | "." "ba"
- | "." "rba"
- | "." "gba"
- | "." "rgba"
-*/
-rgbaMask
- dot_ne .and rgbaMask_1;
-rgbaMask_1
- "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or
- "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or
- "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or
- "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01;
-
-/*
-fragment program
- <namingStatement> ::= <ATTRIB_statement>
- | <PARAM_statement>
- | <TEMP_statement>
- | <OUTPUT_statement>
- | <ALIAS_statement>
-
-vertex program
- <namingStatement> ::= <ATTRIB_statement>
- | <PARAM_statement>
- | <TEMP_statement>
- | <ADDRESS_statement>
- | <OUTPUT_statement>
- | <ALIAS_statement>
-*/
-fp_namingStatement
- fp_ATTRIB_statement .emit ATTRIB .or
- fp_PARAM_statement .emit PARAM .or
- fp_TEMP_statement .emit TEMP .or
- fp_OUTPUT_statement .emit OUTPUT .or
- fp_ALIAS_statement .emit ALIAS;
-vp_namingStatement
- vp_ATTRIB_statement .emit ATTRIB .or
- vp_PARAM_statement .emit PARAM .or
- vp_TEMP_statement .emit TEMP .or
- ADDRESS_statement .emit ADDRESS .or
- vp_OUTPUT_statement .emit OUTPUT .or
- vp_ALIAS_statement .emit ALIAS;
-
-/*
-fragment program
- <ATTRIB_statement> ::= "ATTRIB" <establishName> "="
- <fragAttribBinding>
-
-vertex program
- <ATTRIB_statement> ::= "ATTRIB" <establishName> "="
- <vtxAttribBinding>
-*/
-fp_ATTRIB_statement
- "ATTRIB" .and space .and fp_establishName .and equal .and
- fragAttribBinding .error FRAGMENT_EXPECTED;
-vp_ATTRIB_statement
- "ATTRIB" .and space .and vp_establishName .and equal .and
- vtxAttribBinding .error VERTEX_EXPECTED;
-
-/*
-fragment program
- <fragAttribBinding> ::= "fragment" "." <fragAttribItem>
-*/
-fragAttribBinding
- "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;
-
-/*
-vertex program
- <vtxAttribBinding> ::= "vertex" "." <vtxAttribItem>
-*/
-vtxAttribBinding
- "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;
-
-/*
-fragment program
- <fragAttribItem> ::= "color" <optColorType>
- | "texcoord" <optTexCoordNum>
- | "fogcoord"
- | "position"
-*/
-fragAttribItem
- fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or
- fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or
- .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or
- "position" .emit FRAGMENT_ATTRIB_POSITION;
-fragAttribItem_1
- "color" .and optColorType;
-fragAttribItem_2
- "texcoord" .and optTexCoordNum;
-
-/*
-vertex program
- <vtxAttribItem> ::= "position"
- | "weight" <vtxOptWeightNum>
- | "normal"
- | "color" <optColorType>
- | "fogcoord"
- | "texcoord" <optTexCoordNum>
- | "matrixindex" "[" <vtxWeightNum> "]"
- | "attrib" "[" <vtxAttribNum> "]"
-*/
-vtxAttribItem
- "position" .emit VERTEX_ATTRIB_POSITION .or
- .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or
- "normal" .emit VERTEX_ATTRIB_NORMAL .or
- vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or
- "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or
- vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or
- .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or
- vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;
-vtxAttribItem_1
- "weight" .and vtxOptWeightNum;
-vtxAttribItem_2
- "color" .and optColorType;
-vtxAttribItem_3
- "texcoord" .and optTexCoordNum;
-vtxAttribItem_4
- "matrixindex" .and lbracket .and vtxWeightNum .and rbracket;
-vtxAttribItem_5
- "attrib" .and lbracket .and vtxAttribNum .and rbracket;
-
-/*
-vertex program
- <vtxAttribNum> ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1
-*/
-vtxAttribNum
- integer;
-
-/*
-vertex program
- <vtxOptWeightNum> ::= ""
- | "[" <vtxWeightNum> "]"
-*/
-vtxOptWeightNum
- vtxOptWeightNum_1 .or .true .emit 0x00;
-vtxOptWeightNum_1
- lbracket_ne .and vtxWeightNum .and rbracket;
-
-/*
-vertex program
- <vtxWeightNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,
- must be divisible by four
-*/
-vtxWeightNum
- integer;
-
-/*
- <PARAM_statement> ::= <PARAM_singleStmt>
- | <PARAM_multipleStmt>
-*/
-fp_PARAM_statement
- fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;
-vp_PARAM_statement
- vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;
-
-/*
- <PARAM_singleStmt> ::= "PARAM" <establishName> <paramSingleInit>
-*/
-fp_PARAM_singleStmt
- "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and
- .true .emit PARAM_NULL;
-vp_PARAM_singleStmt
- "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and
- .true .emit PARAM_NULL;
-
-/*
- <PARAM_multipleStmt> ::= "PARAM" <establishName> "[" <optArraySize> "]"
- <paramMultipleInit>
-*/
-fp_PARAM_multipleStmt
- "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
- fp_paramMultipleInit .and .true .emit PARAM_NULL;
-vp_PARAM_multipleStmt
- "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
- vp_paramMultipleInit .and .true .emit PARAM_NULL;
-
-/*
- <optArraySize> ::= ""
- | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB
- (maximum number of allowed program
- parameter bindings)
-*/
-optArraySize
- optional_integer;
-
-/*
- <paramSingleInit> ::= "=" <paramSingleItemDecl>
-*/
-fp_paramSingleInit
- equal .and fp_paramSingleItemDecl;
-vp_paramSingleInit
- equal .and vp_paramSingleItemDecl;
-
-/*
- <paramMultipleInit> ::= "=" "{" <paramMultInitList> "}"
-*/
-fp_paramMultipleInit
- equal .and lbrace .and fp_paramMultInitList .and rbrace;
-vp_paramMultipleInit
- equal .and lbrace .and vp_paramMultInitList .and rbrace;
-
-/*
- <paramMultInitList> ::= <paramMultipleItem>
- | <paramMultipleItem> "," <paramMultiInitList>
-*/
-fp_paramMultInitList
- fp_paramMultInitList_1 .or fp_paramMultipleItem;
-vp_paramMultInitList
- vp_paramMultInitList_1 .or vp_paramMultipleItem;
-fp_paramMultInitList_1
- fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;
-vp_paramMultInitList_1
- vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;
-
-/*
- <paramSingleItemDecl> ::= <stateSingleItem>
- | <programSingleItem>
- | <paramConstDecl>
-*/
-fp_paramSingleItemDecl
- fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-vp_paramSingleItemDecl
- vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-
-/*
- <paramSingleItemUse> ::= <stateSingleItem>
- | <programSingleItem>
- | <paramConstUse>
-*/
-fp_paramSingleItemUse
- fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstUse .emit PARAM_CONSTANT;
-vp_paramSingleItemUse
- vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstUse .emit PARAM_CONSTANT;
-
-/*
- <paramMultipleItem> ::= <stateMultipleItem>
- | <programMultipleItem>
- | <paramConstDecl>
-*/
-fp_paramMultipleItem
- fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
- programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-vp_paramMultipleItem
- vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
- programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
- paramConstDecl .emit PARAM_CONSTANT;
-
-/*
- <stateMultipleItem> ::= <stateSingleItem>
- | "state" "." <stateMatrixRows>
-*/
-fp_stateMultipleItem
- stateMultipleItem_1 .or fp_stateSingleItem;
-vp_stateMultipleItem
- stateMultipleItem_1 .or vp_stateSingleItem;
-stateMultipleItem_1
- "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;
-
-/*
-fragment program
- <stateSingleItem> ::= "state" "." <stateMaterialItem>
- | "state" "." <stateLightItem>
- | "state" "." <stateLightModelItem>
- | "state" "." <stateLightProdItem>
- | "state" "." <stateTexEnvItem>
- | "state" "." <stateFogItem>
- | "state" "." <stateDepthItem>
- | "state" "." <stateMatrixRow>
-
-vertex program
- <stateSingleItem> ::= "state" "." <stateMaterialItem>
- | "state" "." <stateLightItem>
- | "state" "." <stateLightModelItem>
- | "state" "." <stateLightProdItem>
- | "state" "." <stateTexGenItem>
- | "state" "." <stateFogItem>
- | "state" "." <stateClipPlaneItem>
- | "state" "." <statePointItem>
- | "state" "." <stateMatrixRow>
-*/
-fp_stateSingleItem
- "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
-vp_stateSingleItem
- "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
-fp_stateSingleItem_1
- stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
- stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;
-vp_stateSingleItem_1
- stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
- stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or
- stateSingleItem_11;
-stateSingleItem_1
- stateMaterialItem .emit STATE_MATERIAL;
-stateSingleItem_2
- stateLightItem .emit STATE_LIGHT;
-stateSingleItem_3
- stateLightModelItem .emit STATE_LIGHT_MODEL;
-stateSingleItem_4
- stateLightProdItem .emit STATE_LIGHT_PROD;
-stateSingleItem_5
- stateTexEnvItem .emit STATE_TEX_ENV;
-stateSingleItem_6
- stateTexGenItem .emit STATE_TEX_GEN;
-stateSingleItem_7
- stateFogItem .emit STATE_FOG;
-stateSingleItem_8
- stateDepthItem .emit STATE_DEPTH;
-stateSingleItem_9
- stateClipPlaneItem .emit STATE_CLIP_PLANE;
-stateSingleItem_10
- statePointItem .emit STATE_POINT;
-stateSingleItem_11
- stateMatrixRow .emit STATE_MATRIX_ROWS;
-
-/*
- <stateMaterialItem> ::= "material" <optFaceType> "." <stateMatProperty>
-*/
-stateMaterialItem
- "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;
-
-/*
- <stateMatProperty> ::= "ambient"
- | "diffuse"
- | "specular"
- | "emission"
- | "shininess"
-*/
-stateMatProperty
- "ambient" .emit MATERIAL_AMBIENT .or
- "diffuse" .emit MATERIAL_DIFFUSE .or
- "specular" .emit MATERIAL_SPECULAR .or
- "emission" .emit MATERIAL_EMISSION .or
- "shininess" .emit MATERIAL_SHININESS;
-
-/*
- <stateLightItem> ::= "light" "[" <stateLightNumber> "]" "."
- <stateLightProperty>
-*/
-stateLightItem
- "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and
- stateLightProperty .error INVALID_LIGHT_PROPERTY;
-
-/*
- <stateLightProperty> ::= "ambient"
- | "diffuse"
- | "specular"
- | "position"
- | "attenuation"
- | "spot" "." <stateSpotProperty>
- | "half"
-*/
-stateLightProperty
- "ambient" .emit LIGHT_AMBIENT .or
- "diffuse" .emit LIGHT_DIFFUSE .or
- "specular" .emit LIGHT_SPECULAR .or
- "position" .emit LIGHT_POSITION .or
- "attenuation" .emit LIGHT_ATTENUATION .or
- stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or
- "half" .emit LIGHT_HALF;
-stateLightProperty_1
- "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;
-
-/*
- <stateSpotProperty> ::= "direction"
-*/
-stateSpotProperty
- "direction";
-
-/*
- <stateLightModelItem> ::= "lightmodel" <stateLModProperty>
-*/
-stateLightModelItem
- "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;
-
-/*
- <stateLModProperty> ::= "." "ambient"
- | <optFaceType> "." "scenecolor"
-*/
-stateLModProperty
- stateLModProperty_1 .or stateLModProperty_2;
-stateLModProperty_1
- dot .and "ambient" .emit LIGHT_MODEL_AMBIENT;
-stateLModProperty_2
- stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;
-stateLModProperty_3
- optFaceType .and dot .and "scenecolor";
-
-/*
- <stateLightProdItem> ::= "lightprod" "[" <stateLightNumber> "]"
- <optFaceType> "." <stateLProdProperty>
-*/
-stateLightProdItem
- "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and
- stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;
-
-/*
- <stateLProdProperty> ::= "ambient"
- | "diffuse"
- | "specular"
-*/
-stateLProdProperty
- "ambient" .emit LIGHT_PROD_AMBIENT .or
- "diffuse" .emit LIGHT_PROD_DIFFUSE .or
- "specular" .emit LIGHT_PROD_SPECULAR;
-
-/*
- <stateLightNumber> ::= <integer> from 0 to MAX_LIGHTS-1
-*/
-stateLightNumber
- integer;
-
-/*
-fragment program
- <stateTexEnvItem> ::= "texenv" <optLegacyTexUnitNum> "."
- <stateTexEnvProperty>
-*/
-stateTexEnvItem
- "texenv" .and optLegacyTexUnitNum .and dot .and
- stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;
-
-/*
-fragment program
- <stateTexEnvProperty> ::= "color"
-*/
-stateTexEnvProperty
- "color" .emit TEX_ENV_COLOR;
-
-/*
-fragment program
- <optLegacyTexUnitNum> ::= ""
- | "[" <legacyTexUnitNum> "]"
-
-NOTE: <optLegaceTexUnitNum> is not optional.
-*/
-optLegacyTexUnitNum
- lbracket_ne .and legacyTexUnitNum .and rbracket;
-
-/*
-fragment program
- <legacyTexUnitNum> ::= <integer> from 0 to MAX_TEXTURE_UNITS-1
-*/
-legacyTexUnitNum
- integer;
-
-/*
-vertex program
- <stateTexGenItem> ::= "texgen" <optTexCoordNum> "."
- <stateTexGenType> "." <stateTexGenCoord>
-*/
-stateTexGenItem
- "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and
- dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;
-
-/*
-vertex program
- <stateTexGenType> ::= "eye"
- | "object"
-*/
-stateTexGenType
- "eye" .emit TEX_GEN_EYE .or
- "object" .emit TEX_GEN_OBJECT;
-
-/*
-vertex program
- <stateTexGenCoord> ::= "s"
- | "t"
- | "r"
- | "q"
-*/
-stateTexGenCoord
- "s" .emit COMPONENT_X .or
- "t" .emit COMPONENT_Y .or
- "r" .emit COMPONENT_Z .or
- "q" .emit COMPONENT_W;
-
-/*
- <stateFogItem> ::= "fog" "." <stateFogProperty>
-*/
-stateFogItem
- "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;
-
-/*
- <stateFogProperty> ::= "color"
- | "params"
-*/
-stateFogProperty
- "color" .emit FOG_COLOR .or
- "params" .emit FOG_PARAMS;
-
-/*
-fragment program
- <stateDepthItem> ::= "depth" "." <stateDepthProperty>
-*/
-stateDepthItem
- "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;
-
-/*
-fragment program
- <stateDepthProperty> ::= "range"
-*/
-stateDepthProperty
- "range" .emit DEPTH_RANGE;
-
-/*
-vertex program
- <stateClipPlaneItem> ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"
-*/
-stateClipPlaneItem
- "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and
- "plane" .error INVALID_CLIPPLANE_PROPERTY;
-
-/*
-vertex program
- <stateClipPlaneNum> ::= <integer> from 0 to MAX_CLIP_PLANES-1
-*/
-stateClipPlaneNum
- integer;
-
-/*
-vertex program
- <statePointItem> ::= "point" . <statePointProperty>
-*/
-statePointItem
- "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;
-
-/*
-vertex program
- <statePointProperty> ::= "size"
- | "attenuation"
-*/
-statePointProperty
- "size" .emit POINT_SIZE .or
- .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION;
-
-/*
- <stateMatrixRow> ::= <stateMatrixItem> "." "row" "["
- <stateMatrixRowNum> "]"
-*/
-stateMatrixRow
- stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and
- lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;
-
-/*
- <stateMatrixRows> ::= <stateMatrixItem> <optMatrixRows>
-*/
-stateMatrixRows
- stateMatrixItem .and optMatrixRows;
-
-/*
- <optMatrixRows> ::= ""
- | "." "row" "[" <stateMatrixRowNum> ".."
- <stateMatrixRowNum> "]"
-*/
-optMatrixRows
- optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;
-optMatrixRows_1
- dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and
- stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;
-
-/*
- <stateMatrixItem> ::= "matrix" . <stateMatrixName>
- <stateOptMatModifier>
-*/
-stateMatrixItem
- "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;
-
-/*
- <stateOptMatModifier> ::= ""
- | "." <stateMatModifier>
-*/
-stateOptMatModifier
- stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;
-stateOptMatModifier_1
- dot_ne .and stateMatModifier;
-
-/*
- <stateMatModifier> ::= "inverse"
- | "transpose"
- | "invtrans"
-*/
-stateMatModifier
- "inverse" .emit MATRIX_MODIFIER_INVERSE .or
- "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or
- "invtrans" .emit MATRIX_MODIFIER_INVTRANS;
-
-/*
- <stateMatrixRowNum> ::= <integer> from 0 to 3
-*/
-stateMatrixRowNum
- integer_0_3;
-
-/*
- <stateMatrixName> ::= "modelview" <stateOptModMatNum>
- | "projection"
- | "mvp"
- | "texture" <optTexCoordNum>
- | "palette" "[" <statePaletteMatNum> "]"
- | "program" "[" <stateProgramMatNum> "]"
-*/
-stateMatrixName
- stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or
- "projection" .emit MATRIX_PROJECTION .or
- "mvp" .emit MATRIX_MVP .or
- stateMatrixName_1_2 .emit MATRIX_TEXTURE .or
- .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or
- stateMatrixName_1_4 .emit MATRIX_PROGRAM;
-stateMatrixName_1_1
- "modelview" .and stateOptModMatNum;
-stateMatrixName_1_2
- "texture" .and optTexCoordNum;
-stateMatrixName_1_3
- "palette" .and lbracket .and statePaletteMatNum .and rbracket;
-stateMatrixName_1_4
- "program" .and lbracket .and stateProgramMatNum .and rbracket;
-
-/*
- <stateOptModMatNum> ::= ""
- | "[" <stateModMatNum> "]"
-*/
-stateOptModMatNum
- .if (vertex_blend != 0x00) stateOptModMatNum_1 .or
- .true .emit 0x00;
-stateOptModMatNum_1
- lbracket_ne .and stateModMatNum .and rbracket;
-
-/*
- <stateModMatNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1
-*/
-stateModMatNum
- integer;
-
-/*
- <optTexCoordNum> ::= ""
- | "[" <texCoordNum> "]"
-*/
-optTexCoordNum
- optTexCoordNum_1 .or .true .emit 0x00;
-optTexCoordNum_1
- lbracket_ne .and texCoordNum .and rbracket;
-
-/*
- <texCoordNum> ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1
-*/
-texCoordNum
- integer;
-
-/*
- <statePaletteMatNum> ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1
-*/
-statePaletteMatNum
- integer;
-
-/*
- <stateProgramMatNum> ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1
-*/
-stateProgramMatNum
- integer;
-
-/*
- <programSingleItem> ::= <progEnvParam>
- | <progLocalParam>
-
-NOTE: <programSingleItem> has been modified for correct error handling. If program property
- is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
-*/
-programSingleItem
- "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;
-programSingleItem_1
- progEnvParam .or progLocalParam;
-
-/*
- <programMultipleItem> ::= <progEnvParams>
- | <progLocalParams>
-
-NOTE: <programMultipleItem> has been modified for correct error handling. If program property
- is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
-*/
-programMultipleItem
- "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;
-programMultipleItem_1
- progEnvParams .or progLocalParams;
-
-/*
- <progEnvParams> ::= "program" "." "env"
- "[" <progEnvParamNums> "]"
-
-NOTE: "program" "." has been moved to <programMultipleItem>.
-*/
-progEnvParams
- "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;
-
-/*
- <progEnvParamNums> ::= <progEnvParamNum>
- | <progEnvParamNum> ".." <progEnvParamNum>
-*/
-progEnvParamNums
- progEnvParamNums_1 .or progEnvParamNums_2;
-progEnvParamNums_1
- progEnvParamNum .and dotdot_ne .and progEnvParamNum;
-progEnvParamNums_2
- progEnvParamNum .and .true .emit 0x00;
-
-/*
- <progEnvParam> ::= "program" "." "env"
- "[" <progEnvParamNum> "]"
-
-NOTE: "program" "." has been moved to <programSingleItem>.
-*/
-progEnvParam
- "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;
-
-/*
- <progLocalParams> ::= "program" "." "local"
- "[" <progLocalParamNums> "]"
-
-NOTE: "program" "." has been moved to <programMultipleItem>.
-*/
-progLocalParams
- "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;
-
-/*
- <progLocalParamNums> ::= <progLocalParamNum>
- | <progLocalParamNum> ".." <progLocalParamNum>
-*/
-progLocalParamNums
- progLocalParamNums_1 .or progLocalParamNums_2;
-progLocalParamNums_1
- progLocalParamNum .and dotdot_ne .and progLocalParamNum;
-progLocalParamNums_2
- progLocalParamNum .and .true .emit 0x00;
-
-/*
- <progLocalParam> ::= "program" "." "local"
- "[" <progLocalParamNum> "]"
-
-NOTE: "program" "." has been moved to <programSingleItem>.
-*/
-progLocalParam
- "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;
-
-/*
- <progEnvParamNum> ::= <integer> from 0 to
- MAX_PROGRAM_ENV_PARAMETERS_ARB - 1
-*/
-progEnvParamNum
- integer;
-
-/*
- <progLocalParamNum> ::= <integer> from 0 to
- MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1
-*/
-progLocalParamNum
- integer;
-
-/*
- <paramConstDecl> ::= <paramConstScalarDecl>
- | <paramConstVector>
-*/
-paramConstDecl
- paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
-
-/*
- <paramConstUse> ::= <paramConstScalarUse>
- | <paramConstVector>
-*/
-paramConstUse
- paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
-
-/*
- <paramConstScalarDecl> ::= <signedFloatConstant>
-*/
-paramConstScalarDecl
- signedFloatConstant;
-
-/*
- <paramConstScalarUse> ::= <floatConstant>
-*/
-paramConstScalarUse
- floatConstant;
-
-/*
- <paramConstVector> ::= "{" <signedFloatConstant> "}"
- | "{" <signedFloatConstant> ","
- <signedFloatConstant> "}"
- | "{" <signedFloatConstant> ","
- <signedFloatConstant> ","
- <signedFloatConstant> "}"
- | "{" <signedFloatConstant> ","
- <signedFloatConstant> ","
- <signedFloatConstant> ","
- <signedFloatConstant> "}"
-*/
-paramConstVector
- paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or
- paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;
-paramConstVector_1
- lbrace_ne .and signedFloatConstant .and rbrace;
-paramConstVector_2
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
-paramConstVector_3
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
- signedFloatConstant .and rbrace;
-paramConstVector_4
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
- signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
-
-/*
- <signedFloatConstant> ::= <optionalSign> <floatConstant>
-*/
-signedFloatConstant
- optionalSign .and floatConstant;
-
-/*
- <floatConstant> ::= see text
- The <floatConstant> rule matches a floating-point constant consisting
- of an integer part, a decimal point, a fraction part, an "e" or
- "E", and an optionally signed integer exponent. The integer and
- fraction parts both consist of a sequence of one or more digits ("0"
- through "9"). Either the integer part or the fraction parts (not
- both) may be missing; either the decimal point or the "e" (or "E")
- and the exponent (not both) may be missing.
-*/
-floatConstant
- float;
-
-/*
- <optionalSign> ::= ""
- | "-"
- | "+"
-*/
-optionalSign
- optional_sign_ne;
-
-/*
- <TEMP_statement> ::= "TEMP" <varNameList>
-*/
-fp_TEMP_statement
- "TEMP" .and space .and fp_varNameList .and .true .emit 0x00;
-vp_TEMP_statement
- "TEMP" .and space .and vp_varNameList .and .true .emit 0x00;
-
-/*
-vertex program
- <ADDRESS_statement> ::= "ADDRESS" <varNameList>
-*/
-ADDRESS_statement
- "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00;
-
-/*
- <varNameList> ::= <establishName>
- | <establishName> "," <varNameList>
-*/
-fp_varNameList
- fp_varNameList_1 .or fp_establishName;
-vp_varNameList
- vp_varNameList_1 .or vp_establishName;
-fp_varNameList_1
- fp_establishName .and comma_ne .and fp_varNameList;
-vp_varNameList_1
- vp_establishName .and comma_ne .and vp_varNameList;
-
-/*
- <OUTPUT_statement> ::= "OUTPUT" <establishName> "="
- <resultBinding>
-*/
-fp_OUTPUT_statement
- "OUTPUT" .and space .and fp_establishName .and equal .and
- fp_resultBinding .error RESULT_EXPECTED;
-vp_OUTPUT_statement
- "OUTPUT" .and space .and vp_establishName .and equal .and
- vp_resultBinding .error RESULT_EXPECTED;
-
-/*
-fragment program
- <resultBinding> ::= "result" "." "color"
- | "result" "." "depth"
-
-vertex program
- <resultBinding> ::= "result" "." "position"
- | "result" "." <resultColBinding>
- | "result" "." "fogcoord"
- | "result" "." "pointsize"
- | "result" "." "texcoord" <optTexCoordNum>
-*/
-fp_resultBinding
- "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
-vp_resultBinding
- "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
-fp_resultBinding_1
- "color" .emit FRAGMENT_RESULT_COLOR .or
- "depth" .emit FRAGMENT_RESULT_DEPTH;
-vp_resultBinding_1
- .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or
- resultColBinding .emit VERTEX_RESULT_COLOR .or
- "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or
- "pointsize" .emit VERTEX_RESULT_POINTSIZE .or
- vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;
-vp_resultBinding_2
- "texcoord" .and optTexCoordNum;
-
-/*
-vertex program
- <resultColBinding> ::= "color" <optFaceType> <optColorType>
-*/
-resultColBinding
- "color" .and optFaceType .and optColorType;
-
-/*
- <optFaceType> ::= ""
- | "." "front"
- | "." "back"
-*/
-optFaceType
- FaceType .or .true .emit FACE_FRONT;
-FaceType
- dot_ne .and FaceProperty;
-FaceProperty
- "front" .emit FACE_FRONT .or "back" .emit FACE_BACK;
-
-/*
- <optColorType> ::= ""
- | "." "primary"
- | "." "secondary"
-*/
-optColorType
- ColorType .or .true .emit COLOR_PRIMARY;
-ColorType
- dot_ne .and ColorProperty;
-ColorProperty
- "primary" .emit COLOR_PRIMARY .or
- .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY;
-
-/*
- <ALIAS_statement> ::= "ALIAS" <establishName> "="
- <establishedName>
-*/
-fp_ALIAS_statement
- "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;
-vp_ALIAS_statement
- "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;
-fp_ALIAS_statement_1
- space .and fp_establishName;
-vp_ALIAS_statement_1
- space .and vp_establishName;
-
-/*
- <establishName> ::= <identifier>
-*/
-fp_establishName
- fp_identifier;
-vp_establishName
- vp_identifier;
-
-/*
- <establishedName> ::= <identifier>
-*/
-fp_establishedName
- fp_identifier;
-vp_establishedName
- vp_identifier;
-fp_establishedName_no_error_on_identifier
- fp_identifier_ne;
-vp_establishedName_no_error_on_identifier
- vp_identifier_ne;
-
-/*
-fragment program
- <identifier> ::= see text
- The <identifier> rule matches a sequence of one or more letters ("A"
- through "Z", "a" through "z"), digits ("0" through "9), underscores
- ("_"), or dollar signs ("$"); the first character must not be a
- number. Upper and lower case letters are considered different
- (names are case-sensitive). The following strings are reserved
- keywords and may not be used as identifiers:
-
- ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,
- COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT,
- END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2,
- LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT,
- MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM,
- POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS,
- SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT,
- TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT,
- fragment, program, result, state, and texture.
-
-vertex program
- <identifier> ::= see text
- The <identifier> rule matches a sequence of one or more letters ("A"
- through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),
- or dollar signs ("$"); the first character must not be a number. Upper
- and lower case letters are considered different (names are
- case-sensitive). The following strings are reserved keywords and may not
- be used as identifiers:
-
- ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,
- EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,
- PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,
- state, and vertex.
-*/
-fp_identifier
- fp_identifier_ne .error IDENTIFIER_EXPECTED;
-vp_identifier
- vp_identifier_ne .error IDENTIFIER_EXPECTED;
-fp_identifier_ne
- fp_not_reserved_identifier .and identifier_ne;
-vp_identifier_ne
- vp_not_reserved_identifier .and identifier_ne;
-
-fp_not_reserved_identifier
- fp_not_reserved_identifier_1 .or .true;
-fp_not_reserved_identifier_1
- fp_reserved_identifier .and .false .error RESERVED_KEYWORD;
-vp_not_reserved_identifier
- vp_not_reserved_identifier_1 .or .true;
-vp_not_reserved_identifier_1
- vp_reserved_identifier .and .false .error RESERVED_KEYWORD;
-
-fp_reserved_identifier
- "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or
- "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or
- "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or
- "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or
- "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or
- "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or
- "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or
- "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or
- "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or
- "fragment" .or "program" .or "result" .or "state" .or "texture";
-vp_reserved_identifier
- "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or
- "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or
- "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or
- "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or
- "XPD" .or "program" .or "result" .or "state" .or "vertex";
-
-/*
- The <integer> rule matches an integer constant. The integer consists
- of a sequence of one or more digits ("0" through "9").
-*/
-integer
- integer_ne .error INTEGER_EXPECTED;
-
-zero
- '0';
-
-leading_zeroes
- .loop zero;
-
-no_digit
- no_digit_1 .or .true;
-no_digit_1
- digit10 .and .false .error INTEGER_OUT_OF_RANGE;
-
-all_zeroes
- all_zeroes_1 .or no_digit_1;
-all_zeroes_1
- '0' .and .loop zero .and no_digit;
-
-integer_0_3
- integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
-integer_0_3_1
- integer_0_3_2 .or all_zeroes .emit '0';
-integer_0_3_2 /* [1, 3] */
- leading_zeroes .and '1'-'3' .emit * .and no_digit;
-
-integer_0_63
- integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
-integer_0_63_1
- integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or
- all_zeroes .emit '0';
-integer_0_63_2 /* [7, 9] */
- leading_zeroes .and '7'-'9' .emit * .and no_digit;
-integer_0_63_3 /* [10, 59] */
- leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
-integer_0_63_4 /* [60, 63] */
- leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;
-integer_0_63_5 /* [1, 6] */
- leading_zeroes .and '1'-'6' .emit * .and no_digit;
-
-integer_0_64
- integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
-integer_0_64_1
- integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or
- all_zeroes .emit '0';
-integer_0_64_2 /* [7, 9] */
- leading_zeroes .and '7'-'9' .emit * .and no_digit;
-integer_0_64_3 /* [10, 59] */
- leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
-integer_0_64_4 /* [60, 64] */
- leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;
-integer_0_64_5 /* [1, 6] */
- leading_zeroes .and '1'-'6' .emit * .and no_digit;
-
-optional_space
- space .or .true;
-
-space_dst
- space .error OPERATION_NEEDS_DESTINATION_VARIABLE;
-
-space_src
- space .error OPERATION_NEEDS_SOURCE_VARIABLE;
-
-space
- single_space .and .loop single_space;
-
-single_space
- white_char .or comment_block;
-
-white_char
- ' ' .or '\t' .or '\n' .or '\r';
-
-comment_block
- '#' .and .loop comment_char .and new_line;
-
-/* All ASCII characters except '\r', '\n' and '\0' */
-comment_char
- '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
-
-new_line
- '\n' .or crlf .or '\0';
-
-crlf
- '\r' .and '\n';
-
-semicolon
- optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;
-
-comma
- optional_space .and ',' .error MISSING_COMMA .and optional_space;
-
-comma_ne
- optional_space .and ',' .and optional_space;
-
-lbracket
- optional_space .and '[' .error MISSING_LBRACKET .and optional_space;
-
-lbracket_ne
- optional_space .and '[' .and optional_space;
-
-rbracket
- optional_space .and ']' .error MISSING_RBRACKET .and optional_space;
-
-dot
- optional_space .and '.' .error MISSING_DOT .and optional_space;
-
-dot_ne
- optional_space .and '.' .and optional_space;
-
-equal
- optional_space .and '=' .error MISSING_EQUAL .and optional_space;
-
-lbrace
- optional_space .and '{' .error MISSING_LBRACE .and optional_space;
-
-lbrace_ne
- optional_space .and '{' .and optional_space;
-
-rbrace
- optional_space .and '}' .error MISSING_RBRACE .and optional_space;
-
-dotdot
- optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;
-
-dotdot_ne
- optional_space .and '.' .and '.' .and optional_space;
-
-/*
- The definition below accepts the following floating point number formats:
- .99 .99e99 99. 99.99 99.99e99 99.e99 99e99
- Also 99 format was considered and accepted because of a large number of existing program
- strings with such a format.
-*/
-float
- float_1 .or float_2 .or float_legacy;
-float_1
- '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
-float_2
- integer_ne .and float_3;
-float_3
- float_4 .or float_5;
-float_4
- '.' .and optional_integer .and optional_exponent;
-float_5
- exponent .emit 0x00;
-float_legacy
- integer_ne .and .true .emit 0x00 .emit 0x00;
-
-/*
- Below is a correct version of <float> definiton.
-*/
-/*
-float
- float_1 .or float_2;
-float_1
- '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
-float_2
- integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT;
-float_3
- float_4 .or float_5;
-float_4
- '.' .and optional_integer .and optional_exponent;
-float_5
- exponent .emit 0x00;
-*/
-
-integer_ne
- integer_ne_1 .and .true .emit 0x00 .emit $;
-integer_ne_1
- digit10 .emit * .and .loop digit10 .emit *;
-
-optional_integer
- integer_ne .or .true .emit 0x00;
-
-/*
-NOTE: If exponent part is omited we treat it as if it was "E+1".
-*/
-optional_exponent
- exponent .or .true .emit 0x00;
-
-exponent
- exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;
-exponent_1
- 'e' .or 'E';
-
-optional_sign_ne
- minus_ne .or plus_ne .or .true;
-
-plus_ne
- optional_space .and '+' .and optional_space;
-
-minus_ne
- optional_space .and '-' .emit '-' .and optional_space;
-
-identifier_ne
- first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;
-
-follow_idchar
- first_idchar .or digit10;
-
-first_idchar
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$';
-
-digit10
- '0'-'9';
-
-/*
- string filtering - if a string is encountered in grammar ("blabla"), the symbol below is
- executed to create the string. The symbol must not throw any errors and emit bytes - it should
- stop if it encounters invalid character. After this the resulting string (from starting
- position up to the invalid character (but without it) is compared with the grammar string.
-*/
-.string __string_filter;
-
-__string_filter
- .loop __identifier_char;
-
-__identifier_char
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';
-
-/*
- error token filtering
-*/
-e_signature
- e_signature_char .and .loop e_signature_char;
-e_signature_char
- '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';
-
-e_statement
- .loop e_statement_not_term;
-/* All ASCII characters to one of '\r', '\n', '\0' and ';' */
-e_statement_not_term
- '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
-
-e_identifier
- e_identifier_first .and .loop e_identifier_next;
-e_identifier_first
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$';
-e_identifier_next
- e_identifier_first .or '0'-'9';
-
-e_token
- e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or
- '-' .or ',' .or ';';
-e_token_number
- e_token_digit .and .loop e_token_digit;
-e_token_digit
- '0'-'9';
-
-e_charordigit
- 'A'-'Z' .or 'a'-'z' .or '0'-'9';
-
+.syntax program;
+
+/*
+ This value must be incremented every time emit code values or structure of the production
+ array changes. This value is placed at the beginning of the production array. The loader
+ compares the value with its REVISION value. If they do not match, the loader is not up
+ to date.
+*/
+.emtcode REVISION 0x07
+
+/* program type */
+.emtcode FRAGMENT_PROGRAM 0x01
+.emtcode VERTEX_PROGRAM 0x02
+
+/* program section */
+.emtcode OPTION 0x01
+.emtcode INSTRUCTION 0x02
+.emtcode DECLARATION 0x03
+.emtcode END 0x04
+
+/* GL_ARB_fragment_program option flags */
+.emtcode ARB_PRECISION_HINT_FASTEST 0x01
+.emtcode ARB_PRECISION_HINT_NICEST 0x02
+.emtcode ARB_FOG_EXP 0x04
+.emtcode ARB_FOG_EXP2 0x08
+.emtcode ARB_FOG_LINEAR 0x10
+
+/* GL_ARB_vertex_program option flags */
+.emtcode ARB_POSITION_INVARIANT 0x20
+
+/* GL_ARB_fragment_program_shadow option flags */
+.emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40
+
+/* GL_ARB_fragment_program instruction class */
+.emtcode OP_ALU_INST 0x00
+.emtcode OP_TEX_INST 0x01
+
+/* GL_ARB_vertex_program instruction class */
+/* OP_ALU_INST */
+
+/* GL_ARB_fragment_program instruction type */
+.emtcode OP_ALU_VECTOR 0x00
+.emtcode OP_ALU_SCALAR 0x01
+.emtcode OP_ALU_BINSC 0x02
+.emtcode OP_ALU_BIN 0x03
+.emtcode OP_ALU_TRI 0x04
+.emtcode OP_ALU_SWZ 0x05
+.emtcode OP_TEX_SAMPLE 0x06
+.emtcode OP_TEX_KIL 0x07
+
+/* GL_ARB_vertex_program instruction type */
+.emtcode OP_ALU_ARL 0x08
+/* OP_ALU_VECTOR */
+/* OP_ALU_SCALAR */
+/* OP_ALU_BINSC */
+/* OP_ALU_BIN */
+/* OP_ALU_TRI */
+/* OP_ALU_SWZ */
+
+/* GL_ARB_fragment_program instruction code */
+.emtcode OP_ABS 0x00
+.emtcode OP_ABS_SAT 0x1B
+.emtcode OP_FLR 0x09
+.emtcode OP_FLR_SAT 0x26
+.emtcode OP_FRC 0x0A
+.emtcode OP_FRC_SAT 0x27
+.emtcode OP_LIT 0x0C
+.emtcode OP_LIT_SAT 0x2A
+.emtcode OP_MOV 0x11
+.emtcode OP_MOV_SAT 0x30
+.emtcode OP_COS 0x1F
+.emtcode OP_COS_SAT 0x20
+.emtcode OP_EX2 0x07
+.emtcode OP_EX2_SAT 0x25
+.emtcode OP_LG2 0x0B
+.emtcode OP_LG2_SAT 0x29
+.emtcode OP_RCP 0x14
+.emtcode OP_RCP_SAT 0x33
+.emtcode OP_RSQ 0x15
+.emtcode OP_RSQ_SAT 0x34
+.emtcode OP_SIN 0x38
+.emtcode OP_SIN_SAT 0x39
+.emtcode OP_SCS 0x35
+.emtcode OP_SCS_SAT 0x36
+.emtcode OP_POW 0x13
+.emtcode OP_POW_SAT 0x32
+.emtcode OP_ADD 0x01
+.emtcode OP_ADD_SAT 0x1C
+.emtcode OP_DP3 0x03
+.emtcode OP_DP3_SAT 0x21
+.emtcode OP_DP4 0x04
+.emtcode OP_DP4_SAT 0x22
+.emtcode OP_DPH 0x05
+.emtcode OP_DPH_SAT 0x23
+.emtcode OP_DST 0x06
+.emtcode OP_DST_SAT 0x24
+.emtcode OP_MAX 0x0F
+.emtcode OP_MAX_SAT 0x2E
+.emtcode OP_MIN 0x10
+.emtcode OP_MIN_SAT 0x2F
+.emtcode OP_MUL 0x12
+.emtcode OP_MUL_SAT 0x31
+.emtcode OP_SGE 0x16
+.emtcode OP_SGE_SAT 0x37
+.emtcode OP_SLT 0x17
+.emtcode OP_SLT_SAT 0x3A
+.emtcode OP_SUB 0x18
+.emtcode OP_SUB_SAT 0x3B
+.emtcode OP_XPD 0x1A
+.emtcode OP_XPD_SAT 0x43
+.emtcode OP_CMP 0x1D
+.emtcode OP_CMP_SAT 0x1E
+.emtcode OP_LRP 0x2B
+.emtcode OP_LRP_SAT 0x2C
+.emtcode OP_MAD 0x0E
+.emtcode OP_MAD_SAT 0x2D
+.emtcode OP_SWZ 0x19
+.emtcode OP_SWZ_SAT 0x3C
+.emtcode OP_TEX 0x3D
+.emtcode OP_TEX_SAT 0x3E
+.emtcode OP_TXB 0x3F
+.emtcode OP_TXB_SAT 0x40
+.emtcode OP_TXP 0x41
+.emtcode OP_TXP_SAT 0x42
+.emtcode OP_KIL 0x28
+
+/* GL_ARB_vertex_program instruction code */
+.emtcode OP_ARL 0x02
+/* OP_ABS */
+/* OP_FLR */
+/* OP_FRC */
+/* OP_LIT */
+/* OP_MOV */
+/* OP_EX2 */
+.emtcode OP_EXP 0x08
+/* OP_LG2 */
+.emtcode OP_LOG 0x0D
+/* OP_RCP */
+/* OP_RSQ */
+/* OP_POW */
+/* OP_ADD */
+/* OP_DP3 */
+/* OP_DP4 */
+/* OP_DPH */
+/* OP_DST */
+/* OP_MAX */
+/* OP_MIN */
+/* OP_MUL */
+/* OP_SGE */
+/* OP_SLT */
+/* OP_SUB */
+/* OP_XPD */
+/* OP_MAD */
+/* OP_SWZ */
+
+/* fragment attribute binding */
+.emtcode FRAGMENT_ATTRIB_COLOR 0x01
+.emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02
+.emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03
+.emtcode FRAGMENT_ATTRIB_POSITION 0x04
+
+/* vertex attribute binding */
+.emtcode VERTEX_ATTRIB_POSITION 0x01
+.emtcode VERTEX_ATTRIB_WEIGHT 0x02
+.emtcode VERTEX_ATTRIB_NORMAL 0x03
+.emtcode VERTEX_ATTRIB_COLOR 0x04
+.emtcode VERTEX_ATTRIB_FOGCOORD 0x05
+.emtcode VERTEX_ATTRIB_TEXCOORD 0x06
+.emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07
+.emtcode VERTEX_ATTRIB_GENERIC 0x08
+
+/* fragment result binding */
+.emtcode FRAGMENT_RESULT_COLOR 0x01
+.emtcode FRAGMENT_RESULT_DEPTH 0x02
+
+/* vertex result binding */
+.emtcode VERTEX_RESULT_POSITION 0x01
+.emtcode VERTEX_RESULT_COLOR 0x02
+.emtcode VERTEX_RESULT_FOGCOORD 0x03
+.emtcode VERTEX_RESULT_POINTSIZE 0x04
+.emtcode VERTEX_RESULT_TEXCOORD 0x05
+
+/* texture target */
+.emtcode TEXTARGET_1D 0x01
+.emtcode TEXTARGET_2D 0x02
+.emtcode TEXTARGET_3D 0x03
+.emtcode TEXTARGET_RECT 0x04
+.emtcode TEXTARGET_CUBE 0x05
+/* GL_ARB_fragment_program_shadow */
+.emtcode TEXTARGET_SHADOW1D 0x06
+.emtcode TEXTARGET_SHADOW2D 0x07
+.emtcode TEXTARGET_SHADOWRECT 0x08
+
+/* face type */
+.emtcode FACE_FRONT 0x00
+.emtcode FACE_BACK 0x01
+
+/* color type */
+.emtcode COLOR_PRIMARY 0x00
+.emtcode COLOR_SECONDARY 0x01
+
+/* component */
+.emtcode COMPONENT_X 0x00
+.emtcode COMPONENT_Y 0x01
+.emtcode COMPONENT_Z 0x02
+.emtcode COMPONENT_W 0x03
+.emtcode COMPONENT_0 0x04
+.emtcode COMPONENT_1 0x05
+
+/* array index type */
+.emtcode ARRAY_INDEX_ABSOLUTE 0x00
+.emtcode ARRAY_INDEX_RELATIVE 0x01
+
+/* matrix name */
+.emtcode MATRIX_MODELVIEW 0x01
+.emtcode MATRIX_PROJECTION 0x02
+.emtcode MATRIX_MVP 0x03
+.emtcode MATRIX_TEXTURE 0x04
+.emtcode MATRIX_PALETTE 0x05
+.emtcode MATRIX_PROGRAM 0x06
+
+/* matrix modifier */
+.emtcode MATRIX_MODIFIER_IDENTITY 0x00
+.emtcode MATRIX_MODIFIER_INVERSE 0x01
+.emtcode MATRIX_MODIFIER_TRANSPOSE 0x02
+.emtcode MATRIX_MODIFIER_INVTRANS 0x03
+
+/* constant type */
+.emtcode CONSTANT_SCALAR 0x01
+.emtcode CONSTANT_VECTOR 0x02
+
+/* program param type */
+.emtcode PROGRAM_PARAM_ENV 0x01
+.emtcode PROGRAM_PARAM_LOCAL 0x02
+
+/* register type */
+.emtcode REGISTER_ATTRIB 0x01
+.emtcode REGISTER_PARAM 0x02
+.emtcode REGISTER_RESULT 0x03
+.emtcode REGISTER_ESTABLISHED_NAME 0x04
+
+/* param binding */
+.emtcode PARAM_NULL 0x00
+.emtcode PARAM_ARRAY_ELEMENT 0x01
+.emtcode PARAM_STATE_ELEMENT 0x02
+.emtcode PARAM_PROGRAM_ELEMENT 0x03
+.emtcode PARAM_PROGRAM_ELEMENTS 0x04
+.emtcode PARAM_CONSTANT 0x05
+
+/* param state property */
+.emtcode STATE_MATERIAL 0x01
+.emtcode STATE_LIGHT 0x02
+.emtcode STATE_LIGHT_MODEL 0x03
+.emtcode STATE_LIGHT_PROD 0x04
+.emtcode STATE_FOG 0x05
+.emtcode STATE_MATRIX_ROWS 0x06
+/* GL_ARB_fragment_program */
+.emtcode STATE_TEX_ENV 0x07
+.emtcode STATE_DEPTH 0x08
+/* GL_ARB_vertex_program */
+.emtcode STATE_TEX_GEN 0x09
+.emtcode STATE_CLIP_PLANE 0x0A
+.emtcode STATE_POINT 0x0B
+
+/* state material property */
+.emtcode MATERIAL_AMBIENT 0x01
+.emtcode MATERIAL_DIFFUSE 0x02
+.emtcode MATERIAL_SPECULAR 0x03
+.emtcode MATERIAL_EMISSION 0x04
+.emtcode MATERIAL_SHININESS 0x05
+
+/* state light property */
+.emtcode LIGHT_AMBIENT 0x01
+.emtcode LIGHT_DIFFUSE 0x02
+.emtcode LIGHT_SPECULAR 0x03
+.emtcode LIGHT_POSITION 0x04
+.emtcode LIGHT_ATTENUATION 0x05
+.emtcode LIGHT_HALF 0x06
+.emtcode LIGHT_SPOT_DIRECTION 0x07
+
+/* state light model property */
+.emtcode LIGHT_MODEL_AMBIENT 0x01
+.emtcode LIGHT_MODEL_SCENECOLOR 0x02
+
+/* state light product property */
+.emtcode LIGHT_PROD_AMBIENT 0x01
+.emtcode LIGHT_PROD_DIFFUSE 0x02
+.emtcode LIGHT_PROD_SPECULAR 0x03
+
+/* state texture environment property */
+.emtcode TEX_ENV_COLOR 0x01
+
+/* state texture generation coord property */
+.emtcode TEX_GEN_EYE 0x01
+.emtcode TEX_GEN_OBJECT 0x02
+
+/* state fog property */
+.emtcode FOG_COLOR 0x01
+.emtcode FOG_PARAMS 0x02
+
+/* state depth property */
+.emtcode DEPTH_RANGE 0x01
+
+/* state point parameters property */
+.emtcode POINT_SIZE 0x01
+.emtcode POINT_ATTENUATION 0x02
+
+/* declaration */
+.emtcode ATTRIB 0x01
+.emtcode PARAM 0x02
+.emtcode TEMP 0x03
+.emtcode OUTPUT 0x04
+.emtcode ALIAS 0x05
+/* GL_ARB_vertex_program */
+.emtcode ADDRESS 0x06
+
+/* error messages */
+.errtext UNKNOWN_PROGRAM_SIGNATURE "1001: '$e_signature$': unknown program signature"
+.errtext MISSING_END_OR_INVALID_STATEMENT "1002: '$e_statement$': invalid statement"
+.errtext CODE_AFTER_END "1003: '$e_statement$': code after 'END' keyword"
+.errtext INVALID_PROGRAM_OPTION "1004: '$e_identifier$': invalid program option"
+.errtext EXT_SWIZ_COMP_EXPECTED "1005: extended swizzle component expected but '$e_token$' found"
+.errtext TEX_TARGET_EXPECTED "1006: texture target expected but '$e_token$' found"
+.errtext TEXTURE_EXPECTED "1007: 'texture' expected but '$e_identifier$' found"
+.errtext SOURCE_REGISTER_EXPECTED "1008: source register expected but '$e_token$' found"
+.errtext DESTINATION_REGISTER_EXPECTED "1009: destination register expected but '$e_token$' found"
+.errtext INVALID_ADDRESS_COMPONENT "1010: '$e_identifier$': invalid address component"
+.errtext INVALID_ADDRESS_WRITEMASK "1011: '$e_identifier$': invalid address writemask"
+.errtext INVALID_COMPONENT "1012: '$e_charordigit$': invalid component"
+.errtext INVALID_SUFFIX "1013: '$e_identifier$': invalid suffix"
+.errtext INVALID_WRITEMASK "1014: '$e_identifier$': invalid writemask"
+.errtext FRAGMENT_EXPECTED "1015: 'fragment' expected but '$e_identifier$' found"
+.errtext VERTEX_EXPECTED "1016: 'vertex' expected but '$e_identifier$' found"
+.errtext INVALID_FRAGMENT_PROPERTY "1017: '$e_identifier$': invalid fragment property"
+.errtext INVALID_VERTEX_PROPERTY "1018: '$e_identifier$': invalid vertex property"
+.errtext INVALID_STATE_PROPERTY "1019: '$e_identifier$': invalid state property"
+.errtext INVALID_MATERIAL_PROPERTY "1020: '$e_identifier$': invalid material property"
+.errtext INVALID_LIGHT_PROPERTY "1021: '$e_identifier$': invalid light property"
+.errtext INVALID_SPOT_PROPERTY "1022: '$e_identifier$': invalid spot property"
+.errtext INVALID_LIGHTMODEL_PROPERTY "1023: '$e_identifier$': invalid light model property"
+.errtext INVALID_LIGHTPROD_PROPERTY "1024: '$e_identifier$': invalid light product property"
+.errtext INVALID_TEXENV_PROPERTY "1025: '$e_identifier$': invalid texture environment property"
+.errtext INVALID_TEXGEN_PROPERTY "1026: '$e_identifier$': invalid texture generating property"
+.errtext INVALID_TEXGEN_COORD "1027: '$e_identifier$': invalid texture generating coord"
+.errtext INVALID_FOG_PROPERTY "1028: '$e_identifier$': invalid fog property"
+.errtext INVALID_DEPTH_PROPERTY "1029: '$e_identifier$': invalid depth property"
+.errtext INVALID_CLIPPLANE_PROPERTY "1030: '$e_identifier$': invalid clip plane property"
+.errtext INVALID_POINT_PROPERTY "1031: '$e_identifier$': invalid point property"
+.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED "1032: matrix row selector or modifier expected but '$e_token$' found"
+.errtext INVALID_MATRIX_NAME "1033: '$e_identifier$': invalid matrix name"
+.errtext INVALID_PROGRAM_PROPERTY "1034: '$e_identifier$': invalid program property"
+.errtext RESULT_EXPECTED "1035: 'result' expected but '$e_token$' found"
+.errtext INVALID_RESULT_PROPERTY "1036: '$e_identifier$': invalid result property"
+.errtext INVALID_FACE_PROPERTY "1037: '$e_identifier$': invalid face property"
+.errtext INVALID_COLOR_PROPERTY "1038: '$e_identifier$': invalid color property"
+.errtext IDENTIFIER_EXPECTED "1039: identifier expected but '$e_token$' found"
+.errtext RESERVED_KEYWORD "1040: use of reserved keyword as an identifier"
+.errtext INTEGER_EXPECTED "1041: integer value expected but '$e_token$' found"
+.errtext MISSING_SEMICOLON "1042: ';' expected but '$e_token$' found"
+.errtext MISSING_COMMA "1043: ',' expected but '$e_token$' found"
+.errtext MISSING_LBRACKET "1044: '[' expected but '$e_token$' found"
+.errtext MISSING_RBRACKET "1045: ']' expected but '$e_token$' found"
+.errtext MISSING_DOT "1046: '.' expected but '$e_token$' found"
+.errtext MISSING_EQUAL "1047: '=' expected but '$e_token$' found"
+.errtext MISSING_LBRACE "1048: '{' expected but '$e_token$' found"
+.errtext MISSING_RBRACE "1049: '}' expected but '$e_token$' found"
+.errtext MISSING_DOTDOT "1050: '..' expected but '$e_token$' found"
+.errtext MISSING_FRACTION_OR_EXPONENT "1051: missing fraction part or exponent"
+.errtext MISSING_DOT_OR_EXPONENT "1052: missing '.' or exponent"
+.errtext EXPONENT_VALUE_EXPECTED "1053: exponent value expected"
+.errtext INTEGER_OUT_OF_RANGE "1054: integer value out of range"
+.errtext OPERATION_NEEDS_DESTINATION_VARIABLE "1055: operation needs destination variable"
+.errtext OPERATION_NEEDS_SOURCE_VARIABLE "1056: operation needs source variable"
+.errtext ADDRESS_REGISTER_EXPECTED "1057: address register expected but '$e_token$' found"
+.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED "1058: address register or integer literal expected but '$e_token$' found"
+
+/* extension presence condition registers */
+
+/* GL_ARB_vertex_blend */
+/* GL_EXT_vertex_weighting */
+.regbyte vertex_blend 0x00
+
+/* GL_ARB_matrix_palette */
+.regbyte matrix_palette 0x00
+
+/* GL_ARB_point_parameters */
+/* GL_EXT_point_parameters */
+.regbyte point_parameters 0x00
+
+/* GL_EXT_secondary_color */
+.regbyte secondary_color 0x00
+
+/* GL_EXT_fog_coord */
+.regbyte fog_coord 0x00
+
+/* GL_EXT_texture_rectangle */
+/* GL_NV_texture_rectangle */
+.regbyte texture_rectangle 0x00
+
+/* GL_ARB_fragment_program_shadow */
+.regbyte fragment_program_shadow 0x00
+
+/* option presence condition registers */
+/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */
+/* register is set to 1 to indicate that the OPTION was specified. */
+
+/* GL_ARB_fragment_program */
+.regbyte ARB_precision_hint_fastest 0x00
+.regbyte ARB_precision_hint_nicest 0x00
+.regbyte ARB_fog_exp 0x00
+.regbyte ARB_fog_exp2 0x00
+.regbyte ARB_fog_linear 0x00
+
+/* GL_ARB_vertex_program */
+.regbyte ARB_position_invariant 0x00
+
+/* GL_ARB_fragment_program_shadow */
+.regbyte ARB_fragment_program_shadow 0x00
+
+/* program target condition register */
+/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */
+/* to distinguish between them we need a register that will store for us the current target. */
+/* the client will typically set the register to apropriate value before parsing a particular */
+/* program. the mapping between program targets and their values is listed below. */
+/* */
+/* program target register value */
+/* ---------------------------------------------- */
+/* FRAGMENT_PROGRAM 0x10 */
+/* VERTEX_PROGRAM 0x20 */
+/* */
+/* the initial value of the register is 0 to catch potential errors with not setting the register */
+/* with the proper value. */
+.regbyte program_target 0x00
+
+/*
+ <program> ::= <optionSequence> <statementSequence> "END"
+*/
+program
+ programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;
+programs
+ .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or
+ .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;
+frag_program_1_0
+ '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and
+ optional_space .and fp_optionSequence .and fp_statementSequence .and
+ "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
+ '\0' .error CODE_AFTER_END;
+vert_program_1_0
+ '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and
+ optional_space .and vp_optionSequence .and vp_statementSequence .and
+ "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
+ '\0' .error CODE_AFTER_END;
+
+/*
+ <optionSequence> ::= <optionSequence> <option>
+ | ""
+*/
+fp_optionSequence
+ .loop fp_option;
+vp_optionSequence
+ .loop vp_option;
+
+/*
+ <option> ::= "OPTION" <identifier> ";"
+
+NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of
+ these options is encountered, the other one is automatically disabled.
+ the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear.
+*/
+fp_option
+ "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
+ fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
+vp_option
+ "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
+ vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
+fp_optionString
+ .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest"
+ .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or
+ .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest"
+ .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or
+ fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or
+ fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or
+ fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or
+ .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow"
+ .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;
+vp_optionString
+ "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;
+fp_ARB_fog_exp
+ .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp";
+fp_ARB_fog_exp2
+ .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2";
+fp_ARB_fog_linear
+ .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear";
+
+/*
+ <statementSequence> ::= <statementSequence> <statement>
+ | ""
+*/
+fp_statementSequence
+ .loop fp_statement;
+vp_statementSequence
+ .loop vp_statement;
+
+/*
+ <statement> ::= <instruction> ";"
+ | <namingStatement> ";"
+
+NOTE: ".emit $" in the definitions below means that we output instruction position (offset of
+ the first character of instruction) for program debugging purposes.
+*/
+fp_statement
+ fp_statement_1 .or fp_statement_2;
+vp_statement
+ vp_statement_1 .or vp_statement_2;
+fp_statement_1
+ fp_instruction .emit INSTRUCTION .emit $ .and semicolon;
+fp_statement_2
+ fp_namingStatement .emit DECLARATION .and semicolon;
+vp_statement_1
+ vp_instruction .emit INSTRUCTION .emit $ .and semicolon;
+vp_statement_2
+ vp_namingStatement .emit DECLARATION .and semicolon;
+
+/*
+fragment program
+ <instruction> ::= <ALUInstruction>
+ | <TexInstruction>
+
+vertex program
+ <instruction> ::= <ARL_instruction>
+ | <VECTORop_instruction>
+ | <SCALARop_instruction>
+ | <BINSCop_instruction>
+ | <BINop_instruction>
+ | <TRIop_instruction>
+ | <SWZ_instruction>
+*/
+fp_instruction
+ ALUInstruction .emit OP_ALU_INST .or
+ TexInstruction .emit OP_TEX_INST;
+vp_instruction
+ ARL_instruction .emit OP_ALU_ARL .or
+ vp_VECTORop_instruction .emit OP_ALU_VECTOR .or
+ vp_SCALARop_instruction .emit OP_ALU_SCALAR .or
+ vp_BINSCop_instruction .emit OP_ALU_BINSC .or
+ vp_BINop_instruction .emit OP_ALU_BIN .or
+ vp_TRIop_instruction .emit OP_ALU_TRI .or
+ vp_SWZ_instruction .emit OP_ALU_SWZ;
+
+/*
+fragment program
+ <ALUInstruction> ::= <VECTORop_instruction>
+ | <SCALARop_instruction>
+ | <BINSCop_instruction>
+ | <BINop_instruction>
+ | <TRIop_instruction>
+ | <SWZ_instruction>
+*/
+ALUInstruction
+ fp_VECTORop_instruction .emit OP_ALU_VECTOR .or
+ fp_SCALARop_instruction .emit OP_ALU_SCALAR .or
+ fp_BINSCop_instruction .emit OP_ALU_BINSC .or
+ fp_BINop_instruction .emit OP_ALU_BIN .or
+ fp_TRIop_instruction .emit OP_ALU_TRI .or
+ fp_SWZ_instruction .emit OP_ALU_SWZ;
+
+/*
+fragment program
+ <TexInstruction> ::= <SAMPLE_instruction>
+ | <KIL_instruction>
+*/
+TexInstruction
+ SAMPLE_instruction .emit OP_TEX_SAMPLE .or
+ KIL_instruction .emit OP_TEX_KIL;
+
+/*
+vertex program
+ <ARL_instruction> ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>
+*/
+ARL_instruction
+ "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;
+
+/*
+fragment program
+ <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> ","
+ <vectorSrcReg>
+
+vertex program
+ <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>
+*/
+fp_VECTORop_instruction
+ fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;
+vp_VECTORop_instruction
+ vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;
+
+/*
+fragment program
+ <VECTORop> ::= "ABS" | "ABS_SAT"
+ | "FLR" | "FLR_SAT"
+ | "FRC" | "FRC_SAT"
+ | "LIT" | "LIT_SAT"
+ | "MOV" | "MOV_SAT"
+
+vertex program
+ <VECTORop> ::= "ABS"
+ | "FLR"
+ | "FRC"
+ | "LIT"
+ | "MOV"
+*/
+fp_VECTORop
+ "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or
+ "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or
+ "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or
+ "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or
+ "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT;
+vp_VECTORop
+ "ABS" .emit OP_ABS .or
+ "FLR" .emit OP_FLR .or
+ "FRC" .emit OP_FRC .or
+ "LIT" .emit OP_LIT .or
+ "MOV" .emit OP_MOV;
+
+/*
+ <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>
+*/
+fp_SCALARop_instruction
+ fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;
+vp_SCALARop_instruction
+ vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;
+
+/*
+fragment program
+ <SCALARop> ::= "COS" | "COS_SAT"
+ | "EX2" | "EX2_SAT"
+ | "LG2" | "LG2_SAT"
+ | "RCP" | "RCP_SAT"
+ | "RSQ" | "RSQ_SAT"
+ | "SIN" | "SIN_SAT"
+ | "SCS" | "SCS_SAT"
+
+vertex program
+ <SCALARop> ::= "EX2"
+ | "EXP"
+ | "LG2"
+ | "LOG"
+ | "RCP"
+ | "RSQ"
+*/
+fp_SCALARop
+ "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or
+ "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or
+ "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or
+ "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or
+ "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or
+ "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or
+ "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT;
+vp_SCALARop
+ "EX2" .emit OP_EX2 .or
+ "EXP" .emit OP_EXP .or
+ "LG2" .emit OP_LG2 .or
+ "LOG" .emit OP_LOG .or
+ "RCP" .emit OP_RCP .or
+ "RSQ" .emit OP_RSQ;
+
+/*
+ <BINSCop_instruction> ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","
+ <scalarSrcReg>
+*/
+fp_BINSCop_instruction
+ fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and
+ fp_scalarSrcReg;
+vp_BINSCop_instruction
+ vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and
+ vp_scalarSrcReg;
+
+/*
+fragment program
+ <BINSCop> ::= "POW" | "POW_SAT"
+
+vertex program
+ <BINSCop> ::= "POW"
+*/
+fp_BINSCop
+ "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT;
+vp_BINSCop
+ "POW" .emit OP_POW;
+
+/*
+fragment program
+ <BINop_instruction> ::= <BINop> <maskedDstReg> ","
+ <vectorSrcReg> "," <vectorSrcReg>
+
+vertex program
+ <BINop_instruction> ::= <BINop> <maskedDstReg> ","
+ <swizzleSrcReg> "," <swizzleSrcReg>
+*/
+fp_BINop_instruction
+ fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
+ vectorSrcReg;
+vp_BINop_instruction
+ vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
+ swizzleSrcReg;
+
+/*
+fragment program
+ <BINop> ::= "ADD" | "ADD_SAT"
+ | "DP3" | "DP3_SAT"
+ | "DP4" | "DP4_SAT"
+ | "DPH" | "DPH_SAT"
+ | "DST" | "DST_SAT"
+ | "MAX" | "MAX_SAT"
+ | "MIN" | "MIN_SAT"
+ | "MUL" | "MUL_SAT"
+ | "SGE" | "SGE_SAT"
+ | "SLT" | "SLT_SAT"
+ | "SUB" | "SUB_SAT"
+ | "XPD" | "XPD_SAT"
+
+vertex program
+ <BINop> ::= "ADD"
+ | "DP3"
+ | "DP4"
+ | "DPH"
+ | "DST"
+ | "MAX"
+ | "MIN"
+ | "MUL"
+ | "SGE"
+ | "SLT"
+ | "SUB"
+ | "XPD"
+*/
+fp_BINop
+ "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or
+ "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or
+ "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or
+ "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or
+ "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or
+ "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or
+ "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or
+ "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or
+ "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or
+ "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or
+ "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or
+ "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT;
+vp_BINop
+ "ADD" .emit OP_ADD .or
+ "DP3" .emit OP_DP3 .or
+ "DP4" .emit OP_DP4 .or
+ "DPH" .emit OP_DPH .or
+ "DST" .emit OP_DST .or
+ "MAX" .emit OP_MAX .or
+ "MIN" .emit OP_MIN .or
+ "MUL" .emit OP_MUL .or
+ "SGE" .emit OP_SGE .or
+ "SLT" .emit OP_SLT .or
+ "SUB" .emit OP_SUB .or
+ "XPD" .emit OP_XPD;
+
+/*
+fragment program
+ <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
+ <vectorSrcReg> "," <vectorSrcReg> ","
+ <vectorSrcReg>
+
+vertex program
+ <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
+ <swizzleSrcReg> "," <swizzleSrcReg> ","
+ <swizzleSrcReg>
+*/
+fp_TRIop_instruction
+ fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
+ vectorSrcReg .and comma .and vectorSrcReg;
+vp_TRIop_instruction
+ vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
+ swizzleSrcReg .and comma .and swizzleSrcReg;
+
+/*
+fragment program
+ <TRIop> ::= "CMP" | "CMP_SAT"
+ | "LRP" | "LRP_SAT"
+ | "MAD" | "MAD_SAT"
+
+vertex program
+ <TRIop> ::= "MAD"
+*/
+fp_TRIop
+ "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or
+ "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or
+ "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT;
+vp_TRIop
+ "MAD" .emit OP_MAD;
+
+/*
+fragment program
+ <SWZ_instruction> ::= <SWZop> <maskedDstReg> ","
+ <srcReg> "," <extendedSwizzle>
+
+vertex program
+ <SWZ_instruction> ::= "SWZ" <maskedDstReg> "," <srcReg> ","
+ <extendedSwizzle>
+*/
+fp_SWZ_instruction
+ SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and
+ fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
+vp_SWZ_instruction
+ "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and
+ vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+ <SWZop> ::= "SWZ" | "SWZ_SAT"
+*/
+SWZop
+ "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT;
+
+/*
+fragment program
+ <SAMPLE_instruction> ::= <SAMPLEop> <maskedDstReg> ","
+ <vectorSrcReg> "," <texImageUnit> ","
+ <texTarget>
+*/
+SAMPLE_instruction
+ SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
+ texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;
+
+/*
+fragment program
+ <SAMPLEop> ::= "TEX" | "TEX_SAT"
+ | "TXP" | "TXP_SAT"
+ | "TXB" | "TXB_SAT"
+*/
+SAMPLEop
+ "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or
+ "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or
+ "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT;
+
+/*
+fragment program
+ <KIL_instruction> ::= "KIL" <vectorSrcReg>
+*/
+KIL_instruction
+ "KIL" .emit OP_KIL .and space_src .and vectorSrcReg;
+
+/*
+fragment program
+ <texImageUnit> ::= "texture" <optTexImageUnitNum>
+*/
+texImageUnit
+ "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum;
+
+/*
+fragment program
+ <texTarget> ::= "1D"
+ | "2D"
+ | "3D"
+ | "CUBE"
+ | "RECT"
+ | <shadowTarget> (if option ARB_fragment_program_shadow present)
+*/
+texTarget
+ "1D" .emit TEXTARGET_1D .or
+ "2D" .emit TEXTARGET_2D .or
+ "3D" .emit TEXTARGET_3D .or
+ .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or
+ "CUBE" .emit TEXTARGET_CUBE .or
+ .if (ARB_fragment_program_shadow != 0x00) shadowTarget;
+
+/*
+GL_ARB_fragment_program_shadow
+ <shadowTarget> ::= "SHADOW1D"
+ | "SHADOW2D"
+ | "SHADOWRECT"
+*/
+shadowTarget
+ "SHADOW1D" .emit TEXTARGET_SHADOW1D .or
+ "SHADOW2D" .emit TEXTARGET_SHADOW2D .or
+ .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT;
+
+/*
+fragment program
+ <optTexImageUnitNum> ::= ""
+ | "[" <texImageUnitNum> "]"
+*/
+optTexImageUnitNum
+ optTexImageUnitNum_1 .or .true .emit 0x00;
+optTexImageUnitNum_1
+ lbracket_ne .and texImageUnitNum .and rbracket;
+
+/*
+fragment program
+ <texImageUnitNum> ::= <integer> from 0 to
+ MAX_TEXTURE_IMAGE_UNITS_ARB-1
+*/
+texImageUnitNum
+ integer;
+
+/*
+ <scalarSrcReg> ::= <optionalSign> <srcReg> <scalarSuffix>
+*/
+fp_scalarSrcReg
+ optionalSign .and fp_srcReg .and fp_scalarSuffix;
+vp_scalarSrcReg
+ optionalSign .and vp_srcReg .and vp_scalarSuffix;
+
+/*
+vertex program
+ <swizzleSrcReg> ::= <optionalSign> <srcReg> <swizzleSuffix>
+*/
+swizzleSrcReg
+ optionalSign .and vp_srcReg .and swizzleSuffix;
+
+/*
+fragment program
+ <vectorSrcReg> ::= <optionalSign> <srcReg> <optionalSuffix>
+*/
+vectorSrcReg
+ optionalSign .and fp_srcReg .and optionalSuffix;
+
+/*
+ <maskedDstReg> ::= <dstReg> <optionalMask>
+*/
+fp_maskedDstReg
+ fp_dstReg .and fp_optionalMask;
+vp_maskedDstReg
+ vp_dstReg .and vp_optionalMask;
+
+/*
+vertex program
+ <maskedAddrReg> ::= <addrReg> <addrWriteMask>
+*/
+maskedAddrReg
+ addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;
+
+/*
+fragment program
+ <extendedSwizzle> ::= <xyzwExtendedSwizzle>
+ | <rgbaExtendedSwizzle>
+
+vertex program
+ <extendedSwizzle> ::= <extSwizComp> "," <extSwizComp> ","
+ <extSwizComp> "," <extSwizComp>
+
+NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez
+*/
+fp_extendedSwizzle
+ rgbaExtendedSwizzle .or xyzwExtendedSwizzle;
+vp_extendedSwizzle
+ extSwizComp .and comma .and
+ extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ extSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+ <xyzwExtendedSwizzle> ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> ","
+ <xyzwExtSwizComp> "," <xyzwExtSwizComp>
+*/
+xyzwExtendedSwizzle
+ xyzwExtSwizComp .and comma .and
+ xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+ <rgbaExtendedSwizzle> ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> ","
+ <rgbaExtSwizComp> "," <rgbaExtSwizComp>
+*/
+rgbaExtendedSwizzle
+ rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or
+ rgbaExtendedSwizzle_4;
+rgbaExtendedSwizzle_1
+ rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
+ rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;
+rgbaExtendedSwizzle_2
+ rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
+ rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+rgbaExtendedSwizzle_3
+ rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and
+ rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+rgbaExtendedSwizzle_4
+ rgbaExtSwizComp_alpha .and comma .and
+ rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+ rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+ <xyzwExtSwizComp> ::= <optionalSign> <xyzwExtSwizSel>
+*/
+xyzwExtSwizComp
+ optionalSign .and xyzwExtSwizSel;
+
+/*
+fragment program
+ <rgbaExtSwizComp> ::= <optionalSign> <rgbaExtSwizSel>
+*/
+rgbaExtSwizComp
+ optionalSign .and rgbaExtSwizSel;
+rgbaExtSwizComp_digit
+ optionalSign .and rgbaExtSwizSel_digit;
+rgbaExtSwizComp_alpha
+ optionalSign .and rgbaExtSwizSel_alpha;
+
+/*
+vertex program
+ <extSwizComp> ::= <optionalSign> <extSwizSel>
+*/
+extSwizComp
+ optionalSign .and extSwizSel;
+
+/*
+fragment program
+ <xyzwExtSwizSel> ::= "0"
+ | "1"
+ | <xyzwComponent>
+*/
+xyzwExtSwizSel
+ "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single;
+
+/*
+fragment program
+ <rgbaExtSwizSel> ::= "0"
+ | "1"
+ | <rgbaComponent>
+*/
+rgbaExtSwizSel
+ rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;
+rgbaExtSwizSel_digit
+ "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1;
+rgbaExtSwizSel_alpha
+ rgbaComponent_single;
+
+/*
+vertex program
+ <extSwizSel> ::= "0"
+ | "1"
+ | <component>
+*/
+extSwizSel
+ "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single;
+
+/*
+fragment program
+ <srcReg> ::= <fragmentAttribReg>
+ | <temporaryReg>
+ | <progParamReg>
+
+vertex program
+ <srcReg> ::= <vertexAttribReg>
+ | <temporaryReg>
+ | <progParamReg>
+*/
+fp_srcReg
+ fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
+vp_srcReg
+ vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
+fp_srcReg_1
+ fragmentAttribReg .emit REGISTER_ATTRIB .or
+ fp_progParamReg .emit REGISTER_PARAM .or
+ fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+vp_srcReg_1
+ vertexAttribReg .emit REGISTER_ATTRIB .or
+ vp_progParamReg .emit REGISTER_PARAM .or
+ vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+
+/*
+fragment program
+ <dstReg> ::= <temporaryReg>
+ | <fragmentResultReg>
+
+vertex program
+ <dstReg> ::= <temporaryReg>
+ | <vertexResultReg>
+*/
+fp_dstReg
+ fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
+vp_dstReg
+ vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
+fp_dstReg_1
+ fragmentResultReg .emit REGISTER_RESULT .or
+ fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+vp_dstReg_1
+ vertexResultReg .emit REGISTER_RESULT .or
+ vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+
+/*
+fragment program
+ <fragmentAttribReg> ::= <establishedName>
+ | <fragAttribBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
+*/
+fragmentAttribReg
+ /*fp_establishedName .or */fragAttribBinding;
+
+/*
+vertex program
+ <vertexAttribReg> ::= <establishedName>
+ | <vtxAttribBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
+*/
+vertexAttribReg
+ vtxAttribBinding;
+
+/*
+ <temporaryReg> ::= <establishedName>
+*/
+fp_temporaryReg
+ fp_establishedName_no_error_on_identifier;
+vp_temporaryReg
+ vp_establishedName_no_error_on_identifier;
+
+/*
+fragment program
+ <progParamReg> ::= <progParamSingle>
+ | <progParamArray> "[" <progParamArrayAbs> "]"
+ | <paramSingleItemUse>
+
+vertex program
+ <progParamReg> ::= <progParamSingle>
+ | <progParamArray> "[" <progParamArrayMem> "]"
+ | <paramSingleItemUse>
+*/
+fp_progParamReg
+ fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;
+vp_progParamReg
+ vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;
+fp_progParamReg_1
+ fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and
+ rbracket;
+vp_progParamReg_1
+ vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and
+ rbracket;
+
+/*
+ <progParamSingle> ::= <establishedName>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
+*/
+fp_progParamSingle
+ .false;
+vp_progParamSingle
+ .false;
+
+/*
+ <progParamArray> ::= <establishedName>
+*/
+fp_progParamArray
+ fp_establishedName_no_error_on_identifier;
+vp_progParamArray
+ vp_establishedName_no_error_on_identifier;
+
+/*
+vertex program
+ <progParamArrayMem> ::= <progParamArrayAbs>
+ | <progParamArrayRel>
+*/
+progParamArrayMem
+ progParamArrayAbs .or progParamArrayRel;
+
+/*
+ <progParamArrayAbs> ::= <integer>
+*/
+progParamArrayAbs
+ integer_ne .emit ARRAY_INDEX_ABSOLUTE;
+
+/*
+vertex program
+ <progParamArrayRel> ::= <addrReg> <addrComponent> <addrRegRelOffset>
+*/
+progParamArrayRel
+ addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and
+ addrComponent .and addrRegRelOffset;
+
+/*
+vertex program
+ <addrRegRelOffset> ::= ""
+ | "+" <addrRegPosOffset>
+ | "-" <addrRegNegOffset>
+*/
+addrRegRelOffset
+ addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;
+addrRegRelOffset_1
+ plus_ne .and addrRegPosOffset;
+addrRegRelOffset_2
+ minus_ne .and addrRegNegOffset;
+
+/*
+vertex program
+ <addrRegPosOffset> ::= <integer> from 0 to 63
+*/
+addrRegPosOffset
+ integer_0_63;
+
+/*
+vertex program
+ <addrRegNegOffset> ::= <integer> from 0 to 64
+*/
+addrRegNegOffset
+ integer_0_64;
+
+/*
+fragment program
+ <fragmentResultReg> ::= <establishedName>
+ | <resultBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
+*/
+fragmentResultReg
+ fp_resultBinding;
+
+/*
+vertex program
+ <vertexResultReg> ::= <establishedName>
+ | <resultBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
+*/
+vertexResultReg
+ vp_resultBinding;
+
+/*
+vertex program
+ <addrReg> ::= <establishedName>
+*/
+addrReg
+ vp_establishedName_no_error_on_identifier;
+
+/*
+vertex program
+ <addrComponent> ::= "." "x"
+*/
+addrComponent
+ dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X
+ .emit COMPONENT_X .emit COMPONENT_X;
+
+/*
+vertex program
+ <addrWriteMask> ::= "." "x"
+*/
+addrWriteMask
+ dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;
+
+/*
+ <scalarSuffix> ::= "." <component>
+*/
+fp_scalarSuffix
+ dot .and fp_component_single .error INVALID_COMPONENT;
+vp_scalarSuffix
+ dot .and vp_component_single .error INVALID_COMPONENT;
+
+/*
+vertex program
+ <swizzleSuffix> ::= ""
+ | "." <component>
+ | "." <component> <component>
+ <component> <component>
+*/
+swizzleSuffix
+ swizzleSuffix_1 .or
+ .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
+swizzleSuffix_1
+ dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;
+swizzleSuffix_2
+ swizzleSuffix_3 .or swizzleSuffix_4;
+swizzleSuffix_3
+ vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and
+ vp_component_multi .error INVALID_COMPONENT;
+swizzleSuffix_4
+ "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
+ "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
+ "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
+ "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
+
+/*
+fragment program
+ <optionalSuffix> ::= ""
+ | "." <component>
+ | "." <xyzwComponent> <xyzwComponent>
+ <xyzwComponent> <xyzwComponent>
+ | "." <rgbaComponent> <rgbaComponent>
+ <rgbaComponent> <rgbaComponent>
+*/
+optionalSuffix
+ optionalSuffix_1 .or
+ .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
+optionalSuffix_1
+ dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;
+optionalSuffix_2
+ optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;
+optionalSuffix_3
+ xyzwComponent_multi .and xyzwComponent_multi .and
+ xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;
+optionalSuffix_4
+ rgbaComponent_multi .and rgbaComponent_multi .and
+ rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;
+optionalSuffix_5
+ "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
+ "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
+ "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
+ "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or
+ "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
+ "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
+ "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
+ "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
+
+/*
+fragment program
+ <component> ::= <xyzwComponent>
+ | <rgbaComponent>
+
+vertex program
+ <component> ::= "x"
+ | "y"
+ | "z"
+ | "w"
+*/
+fp_component_single
+ xyzwComponent_single .or rgbaComponent_single;
+vp_component_multi
+ 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
+ 'w' .emit COMPONENT_W;
+vp_component_single
+ "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
+ "w" .emit COMPONENT_W;
+
+/*
+fragment program
+ <xyzwComponent> ::= "x" | "y" | "z" | "w"
+*/
+xyzwComponent_multi
+ 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
+ 'w' .emit COMPONENT_W;
+xyzwComponent_single
+ "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
+ "w" .emit COMPONENT_W;
+
+/*
+fragment program
+ <rgbaComponent> ::= "r" | "g" | "b" | "a"
+*/
+rgbaComponent_multi
+ 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or
+ 'a' .emit COMPONENT_W;
+rgbaComponent_single
+ "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or
+ "a" .emit COMPONENT_W;
+
+/*
+fragment program
+ <optionalMask> ::= ""
+ | <xyzwMask>
+ | <rgbaMask>
+
+vertex program
+ <optionalMask> ::= ""
+ | "." "x"
+ | "." "y"
+ | "." "xy"
+ | "." "z"
+ | "." "xz"
+ | "." "yz"
+ | "." "xyz"
+ | "." "w"
+ | "." "xw"
+ | "." "yw"
+ | "." "xyw"
+ | "." "zw"
+ | "." "xzw"
+ | "." "yzw"
+ | "." "xyzw"
+
+NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez
+*/
+fp_optionalMask
+ rgbaMask .or xyzwMask .or .true .emit 0x0F;
+vp_optionalMask
+ xyzwMask .or .true .emit 0x0F;
+
+/*
+fragment program
+ <xyzwMask> ::= "." "x"
+ | "." "y"
+ | "." "xy"
+ | "." "z"
+ | "." "xz"
+ | "." "yz"
+ | "." "xyz"
+ | "." "w"
+ | "." "xw"
+ | "." "yw"
+ | "." "xyw"
+ | "." "zw"
+ | "." "xzw"
+ | "." "yzw"
+ | "." "xyzw"
+
+NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>.
+*/
+xyzwMask
+ dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;
+xyzwMask_1
+ "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or
+ "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or
+ "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or
+ "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01;
+
+/*
+fragment program
+ <rgbaMask> ::= "." "r"
+ | "." "g"
+ | "." "rg"
+ | "." "b"
+ | "." "rb"
+ | "." "gb"
+ | "." "rgb"
+ | "." "a"
+ | "." "ra"
+ | "." "ga"
+ | "." "rga"
+ | "." "ba"
+ | "." "rba"
+ | "." "gba"
+ | "." "rgba"
+*/
+rgbaMask
+ dot_ne .and rgbaMask_1;
+rgbaMask_1
+ "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or
+ "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or
+ "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or
+ "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01;
+
+/*
+fragment program
+ <namingStatement> ::= <ATTRIB_statement>
+ | <PARAM_statement>
+ | <TEMP_statement>
+ | <OUTPUT_statement>
+ | <ALIAS_statement>
+
+vertex program
+ <namingStatement> ::= <ATTRIB_statement>
+ | <PARAM_statement>
+ | <TEMP_statement>
+ | <ADDRESS_statement>
+ | <OUTPUT_statement>
+ | <ALIAS_statement>
+*/
+fp_namingStatement
+ fp_ATTRIB_statement .emit ATTRIB .or
+ fp_PARAM_statement .emit PARAM .or
+ fp_TEMP_statement .emit TEMP .or
+ fp_OUTPUT_statement .emit OUTPUT .or
+ fp_ALIAS_statement .emit ALIAS;
+vp_namingStatement
+ vp_ATTRIB_statement .emit ATTRIB .or
+ vp_PARAM_statement .emit PARAM .or
+ vp_TEMP_statement .emit TEMP .or
+ ADDRESS_statement .emit ADDRESS .or
+ vp_OUTPUT_statement .emit OUTPUT .or
+ vp_ALIAS_statement .emit ALIAS;
+
+/*
+fragment program
+ <ATTRIB_statement> ::= "ATTRIB" <establishName> "="
+ <fragAttribBinding>
+
+vertex program
+ <ATTRIB_statement> ::= "ATTRIB" <establishName> "="
+ <vtxAttribBinding>
+*/
+fp_ATTRIB_statement
+ "ATTRIB" .and space .and fp_establishName .and equal .and
+ fragAttribBinding .error FRAGMENT_EXPECTED;
+vp_ATTRIB_statement
+ "ATTRIB" .and space .and vp_establishName .and equal .and
+ vtxAttribBinding .error VERTEX_EXPECTED;
+
+/*
+fragment program
+ <fragAttribBinding> ::= "fragment" "." <fragAttribItem>
+*/
+fragAttribBinding
+ "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;
+
+/*
+vertex program
+ <vtxAttribBinding> ::= "vertex" "." <vtxAttribItem>
+*/
+vtxAttribBinding
+ "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;
+
+/*
+fragment program
+ <fragAttribItem> ::= "color" <optColorType>
+ | "texcoord" <optTexCoordNum>
+ | "fogcoord"
+ | "position"
+*/
+fragAttribItem
+ fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or
+ fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or
+ .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or
+ "position" .emit FRAGMENT_ATTRIB_POSITION;
+fragAttribItem_1
+ "color" .and optColorType;
+fragAttribItem_2
+ "texcoord" .and optTexCoordNum;
+
+/*
+vertex program
+ <vtxAttribItem> ::= "position"
+ | "weight" <vtxOptWeightNum>
+ | "normal"
+ | "color" <optColorType>
+ | "fogcoord"
+ | "texcoord" <optTexCoordNum>
+ | "matrixindex" "[" <vtxWeightNum> "]"
+ | "attrib" "[" <vtxAttribNum> "]"
+*/
+vtxAttribItem
+ "position" .emit VERTEX_ATTRIB_POSITION .or
+ .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or
+ "normal" .emit VERTEX_ATTRIB_NORMAL .or
+ vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or
+ "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or
+ vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or
+ .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or
+ vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;
+vtxAttribItem_1
+ "weight" .and vtxOptWeightNum;
+vtxAttribItem_2
+ "color" .and optColorType;
+vtxAttribItem_3
+ "texcoord" .and optTexCoordNum;
+vtxAttribItem_4
+ "matrixindex" .and lbracket .and vtxWeightNum .and rbracket;
+vtxAttribItem_5
+ "attrib" .and lbracket .and vtxAttribNum .and rbracket;
+
+/*
+vertex program
+ <vtxAttribNum> ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1
+*/
+vtxAttribNum
+ integer;
+
+/*
+vertex program
+ <vtxOptWeightNum> ::= ""
+ | "[" <vtxWeightNum> "]"
+*/
+vtxOptWeightNum
+ vtxOptWeightNum_1 .or .true .emit 0x00;
+vtxOptWeightNum_1
+ lbracket_ne .and vtxWeightNum .and rbracket;
+
+/*
+vertex program
+ <vtxWeightNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,
+ must be divisible by four
+*/
+vtxWeightNum
+ integer;
+
+/*
+ <PARAM_statement> ::= <PARAM_singleStmt>
+ | <PARAM_multipleStmt>
+*/
+fp_PARAM_statement
+ fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;
+vp_PARAM_statement
+ vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;
+
+/*
+ <PARAM_singleStmt> ::= "PARAM" <establishName> <paramSingleInit>
+*/
+fp_PARAM_singleStmt
+ "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and
+ .true .emit PARAM_NULL;
+vp_PARAM_singleStmt
+ "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and
+ .true .emit PARAM_NULL;
+
+/*
+ <PARAM_multipleStmt> ::= "PARAM" <establishName> "[" <optArraySize> "]"
+ <paramMultipleInit>
+*/
+fp_PARAM_multipleStmt
+ "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
+ fp_paramMultipleInit .and .true .emit PARAM_NULL;
+vp_PARAM_multipleStmt
+ "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
+ vp_paramMultipleInit .and .true .emit PARAM_NULL;
+
+/*
+ <optArraySize> ::= ""
+ | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB
+ (maximum number of allowed program
+ parameter bindings)
+*/
+optArraySize
+ optional_integer;
+
+/*
+ <paramSingleInit> ::= "=" <paramSingleItemDecl>
+*/
+fp_paramSingleInit
+ equal .and fp_paramSingleItemDecl;
+vp_paramSingleInit
+ equal .and vp_paramSingleItemDecl;
+
+/*
+ <paramMultipleInit> ::= "=" "{" <paramMultInitList> "}"
+*/
+fp_paramMultipleInit
+ equal .and lbrace .and fp_paramMultInitList .and rbrace;
+vp_paramMultipleInit
+ equal .and lbrace .and vp_paramMultInitList .and rbrace;
+
+/*
+ <paramMultInitList> ::= <paramMultipleItem>
+ | <paramMultipleItem> "," <paramMultiInitList>
+*/
+fp_paramMultInitList
+ fp_paramMultInitList_1 .or fp_paramMultipleItem;
+vp_paramMultInitList
+ vp_paramMultInitList_1 .or vp_paramMultipleItem;
+fp_paramMultInitList_1
+ fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;
+vp_paramMultInitList_1
+ vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;
+
+/*
+ <paramSingleItemDecl> ::= <stateSingleItem>
+ | <programSingleItem>
+ | <paramConstDecl>
+*/
+fp_paramSingleItemDecl
+ fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+ programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+ paramConstDecl .emit PARAM_CONSTANT;
+vp_paramSingleItemDecl
+ vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+ programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+ paramConstDecl .emit PARAM_CONSTANT;
+
+/*
+ <paramSingleItemUse> ::= <stateSingleItem>
+ | <programSingleItem>
+ | <paramConstUse>
+*/
+fp_paramSingleItemUse
+ fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+ programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+ paramConstUse .emit PARAM_CONSTANT;
+vp_paramSingleItemUse
+ vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+ programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+ paramConstUse .emit PARAM_CONSTANT;
+
+/*
+ <paramMultipleItem> ::= <stateMultipleItem>
+ | <programMultipleItem>
+ | <paramConstDecl>
+*/
+fp_paramMultipleItem
+ fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
+ programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
+ paramConstDecl .emit PARAM_CONSTANT;
+vp_paramMultipleItem
+ vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
+ programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
+ paramConstDecl .emit PARAM_CONSTANT;
+
+/*
+ <stateMultipleItem> ::= <stateSingleItem>
+ | "state" "." <stateMatrixRows>
+*/
+fp_stateMultipleItem
+ stateMultipleItem_1 .or fp_stateSingleItem;
+vp_stateMultipleItem
+ stateMultipleItem_1 .or vp_stateSingleItem;
+stateMultipleItem_1
+ "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;
+
+/*
+fragment program
+ <stateSingleItem> ::= "state" "." <stateMaterialItem>
+ | "state" "." <stateLightItem>
+ | "state" "." <stateLightModelItem>
+ | "state" "." <stateLightProdItem>
+ | "state" "." <stateTexEnvItem>
+ | "state" "." <stateFogItem>
+ | "state" "." <stateDepthItem>
+ | "state" "." <stateMatrixRow>
+
+vertex program
+ <stateSingleItem> ::= "state" "." <stateMaterialItem>
+ | "state" "." <stateLightItem>
+ | "state" "." <stateLightModelItem>
+ | "state" "." <stateLightProdItem>
+ | "state" "." <stateTexGenItem>
+ | "state" "." <stateFogItem>
+ | "state" "." <stateClipPlaneItem>
+ | "state" "." <statePointItem>
+ | "state" "." <stateMatrixRow>
+*/
+fp_stateSingleItem
+ "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
+vp_stateSingleItem
+ "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
+fp_stateSingleItem_1
+ stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
+ stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;
+vp_stateSingleItem_1
+ stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
+ stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or
+ stateSingleItem_11;
+stateSingleItem_1
+ stateMaterialItem .emit STATE_MATERIAL;
+stateSingleItem_2
+ stateLightItem .emit STATE_LIGHT;
+stateSingleItem_3
+ stateLightModelItem .emit STATE_LIGHT_MODEL;
+stateSingleItem_4
+ stateLightProdItem .emit STATE_LIGHT_PROD;
+stateSingleItem_5
+ stateTexEnvItem .emit STATE_TEX_ENV;
+stateSingleItem_6
+ stateTexGenItem .emit STATE_TEX_GEN;
+stateSingleItem_7
+ stateFogItem .emit STATE_FOG;
+stateSingleItem_8
+ stateDepthItem .emit STATE_DEPTH;
+stateSingleItem_9
+ stateClipPlaneItem .emit STATE_CLIP_PLANE;
+stateSingleItem_10
+ statePointItem .emit STATE_POINT;
+stateSingleItem_11
+ stateMatrixRow .emit STATE_MATRIX_ROWS;
+
+/*
+ <stateMaterialItem> ::= "material" <optFaceType> "." <stateMatProperty>
+*/
+stateMaterialItem
+ "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;
+
+/*
+ <stateMatProperty> ::= "ambient"
+ | "diffuse"
+ | "specular"
+ | "emission"
+ | "shininess"
+*/
+stateMatProperty
+ "ambient" .emit MATERIAL_AMBIENT .or
+ "diffuse" .emit MATERIAL_DIFFUSE .or
+ "specular" .emit MATERIAL_SPECULAR .or
+ "emission" .emit MATERIAL_EMISSION .or
+ "shininess" .emit MATERIAL_SHININESS;
+
+/*
+ <stateLightItem> ::= "light" "[" <stateLightNumber> "]" "."
+ <stateLightProperty>
+*/
+stateLightItem
+ "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and
+ stateLightProperty .error INVALID_LIGHT_PROPERTY;
+
+/*
+ <stateLightProperty> ::= "ambient"
+ | "diffuse"
+ | "specular"
+ | "position"
+ | "attenuation"
+ | "spot" "." <stateSpotProperty>
+ | "half"
+*/
+stateLightProperty
+ "ambient" .emit LIGHT_AMBIENT .or
+ "diffuse" .emit LIGHT_DIFFUSE .or
+ "specular" .emit LIGHT_SPECULAR .or
+ "position" .emit LIGHT_POSITION .or
+ "attenuation" .emit LIGHT_ATTENUATION .or
+ stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or
+ "half" .emit LIGHT_HALF;
+stateLightProperty_1
+ "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;
+
+/*
+ <stateSpotProperty> ::= "direction"
+*/
+stateSpotProperty
+ "direction";
+
+/*
+ <stateLightModelItem> ::= "lightmodel" <stateLModProperty>
+*/
+stateLightModelItem
+ "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;
+
+/*
+ <stateLModProperty> ::= "." "ambient"
+ | <optFaceType> "." "scenecolor"
+*/
+stateLModProperty
+ stateLModProperty_1 .or stateLModProperty_2;
+stateLModProperty_1
+ dot .and "ambient" .emit LIGHT_MODEL_AMBIENT;
+stateLModProperty_2
+ stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;
+stateLModProperty_3
+ optFaceType .and dot .and "scenecolor";
+
+/*
+ <stateLightProdItem> ::= "lightprod" "[" <stateLightNumber> "]"
+ <optFaceType> "." <stateLProdProperty>
+*/
+stateLightProdItem
+ "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and
+ stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;
+
+/*
+ <stateLProdProperty> ::= "ambient"
+ | "diffuse"
+ | "specular"
+*/
+stateLProdProperty
+ "ambient" .emit LIGHT_PROD_AMBIENT .or
+ "diffuse" .emit LIGHT_PROD_DIFFUSE .or
+ "specular" .emit LIGHT_PROD_SPECULAR;
+
+/*
+ <stateLightNumber> ::= <integer> from 0 to MAX_LIGHTS-1
+*/
+stateLightNumber
+ integer;
+
+/*
+fragment program
+ <stateTexEnvItem> ::= "texenv" <optLegacyTexUnitNum> "."
+ <stateTexEnvProperty>
+*/
+stateTexEnvItem
+ "texenv" .and optLegacyTexUnitNum .and dot .and
+ stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;
+
+/*
+fragment program
+ <stateTexEnvProperty> ::= "color"
+*/
+stateTexEnvProperty
+ "color" .emit TEX_ENV_COLOR;
+
+/*
+fragment program
+ <optLegacyTexUnitNum> ::= ""
+ | "[" <legacyTexUnitNum> "]"
+
+NOTE: <optLegaceTexUnitNum> is not optional.
+*/
+optLegacyTexUnitNum
+ lbracket_ne .and legacyTexUnitNum .and rbracket;
+
+/*
+fragment program
+ <legacyTexUnitNum> ::= <integer> from 0 to MAX_TEXTURE_UNITS-1
+*/
+legacyTexUnitNum
+ integer;
+
+/*
+vertex program
+ <stateTexGenItem> ::= "texgen" <optTexCoordNum> "."
+ <stateTexGenType> "." <stateTexGenCoord>
+*/
+stateTexGenItem
+ "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and
+ dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;
+
+/*
+vertex program
+ <stateTexGenType> ::= "eye"
+ | "object"
+*/
+stateTexGenType
+ "eye" .emit TEX_GEN_EYE .or
+ "object" .emit TEX_GEN_OBJECT;
+
+/*
+vertex program
+ <stateTexGenCoord> ::= "s"
+ | "t"
+ | "r"
+ | "q"
+*/
+stateTexGenCoord
+ "s" .emit COMPONENT_X .or
+ "t" .emit COMPONENT_Y .or
+ "r" .emit COMPONENT_Z .or
+ "q" .emit COMPONENT_W;
+
+/*
+ <stateFogItem> ::= "fog" "." <stateFogProperty>
+*/
+stateFogItem
+ "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;
+
+/*
+ <stateFogProperty> ::= "color"
+ | "params"
+*/
+stateFogProperty
+ "color" .emit FOG_COLOR .or
+ "params" .emit FOG_PARAMS;
+
+/*
+fragment program
+ <stateDepthItem> ::= "depth" "." <stateDepthProperty>
+*/
+stateDepthItem
+ "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;
+
+/*
+fragment program
+ <stateDepthProperty> ::= "range"
+*/
+stateDepthProperty
+ "range" .emit DEPTH_RANGE;
+
+/*
+vertex program
+ <stateClipPlaneItem> ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"
+*/
+stateClipPlaneItem
+ "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and
+ "plane" .error INVALID_CLIPPLANE_PROPERTY;
+
+/*
+vertex program
+ <stateClipPlaneNum> ::= <integer> from 0 to MAX_CLIP_PLANES-1
+*/
+stateClipPlaneNum
+ integer;
+
+/*
+vertex program
+ <statePointItem> ::= "point" . <statePointProperty>
+*/
+statePointItem
+ "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;
+
+/*
+vertex program
+ <statePointProperty> ::= "size"
+ | "attenuation"
+*/
+statePointProperty
+ "size" .emit POINT_SIZE .or
+ .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION;
+
+/*
+ <stateMatrixRow> ::= <stateMatrixItem> "." "row" "["
+ <stateMatrixRowNum> "]"
+*/
+stateMatrixRow
+ stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and
+ lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;
+
+/*
+ <stateMatrixRows> ::= <stateMatrixItem> <optMatrixRows>
+*/
+stateMatrixRows
+ stateMatrixItem .and optMatrixRows;
+
+/*
+ <optMatrixRows> ::= ""
+ | "." "row" "[" <stateMatrixRowNum> ".."
+ <stateMatrixRowNum> "]"
+*/
+optMatrixRows
+ optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;
+optMatrixRows_1
+ dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and
+ stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;
+
+/*
+ <stateMatrixItem> ::= "matrix" . <stateMatrixName>
+ <stateOptMatModifier>
+*/
+stateMatrixItem
+ "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;
+
+/*
+ <stateOptMatModifier> ::= ""
+ | "." <stateMatModifier>
+*/
+stateOptMatModifier
+ stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;
+stateOptMatModifier_1
+ dot_ne .and stateMatModifier;
+
+/*
+ <stateMatModifier> ::= "inverse"
+ | "transpose"
+ | "invtrans"
+*/
+stateMatModifier
+ "inverse" .emit MATRIX_MODIFIER_INVERSE .or
+ "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or
+ "invtrans" .emit MATRIX_MODIFIER_INVTRANS;
+
+/*
+ <stateMatrixRowNum> ::= <integer> from 0 to 3
+*/
+stateMatrixRowNum
+ integer_0_3;
+
+/*
+ <stateMatrixName> ::= "modelview" <stateOptModMatNum>
+ | "projection"
+ | "mvp"
+ | "texture" <optTexCoordNum>
+ | "palette" "[" <statePaletteMatNum> "]"
+ | "program" "[" <stateProgramMatNum> "]"
+*/
+stateMatrixName
+ stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or
+ "projection" .emit MATRIX_PROJECTION .or
+ "mvp" .emit MATRIX_MVP .or
+ stateMatrixName_1_2 .emit MATRIX_TEXTURE .or
+ .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or
+ stateMatrixName_1_4 .emit MATRIX_PROGRAM;
+stateMatrixName_1_1
+ "modelview" .and stateOptModMatNum;
+stateMatrixName_1_2
+ "texture" .and optTexCoordNum;
+stateMatrixName_1_3
+ "palette" .and lbracket .and statePaletteMatNum .and rbracket;
+stateMatrixName_1_4
+ "program" .and lbracket .and stateProgramMatNum .and rbracket;
+
+/*
+ <stateOptModMatNum> ::= ""
+ | "[" <stateModMatNum> "]"
+*/
+stateOptModMatNum
+ .if (vertex_blend != 0x00) stateOptModMatNum_1 .or
+ .true .emit 0x00;
+stateOptModMatNum_1
+ lbracket_ne .and stateModMatNum .and rbracket;
+
+/*
+ <stateModMatNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1
+*/
+stateModMatNum
+ integer;
+
+/*
+ <optTexCoordNum> ::= ""
+ | "[" <texCoordNum> "]"
+*/
+optTexCoordNum
+ optTexCoordNum_1 .or .true .emit 0x00;
+optTexCoordNum_1
+ lbracket_ne .and texCoordNum .and rbracket;
+
+/*
+ <texCoordNum> ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1
+*/
+texCoordNum
+ integer;
+
+/*
+ <statePaletteMatNum> ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1
+*/
+statePaletteMatNum
+ integer;
+
+/*
+ <stateProgramMatNum> ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1
+*/
+stateProgramMatNum
+ integer;
+
+/*
+ <programSingleItem> ::= <progEnvParam>
+ | <progLocalParam>
+
+NOTE: <programSingleItem> has been modified for correct error handling. If program property
+ is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
+*/
+programSingleItem
+ "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;
+programSingleItem_1
+ progEnvParam .or progLocalParam;
+
+/*
+ <programMultipleItem> ::= <progEnvParams>
+ | <progLocalParams>
+
+NOTE: <programMultipleItem> has been modified for correct error handling. If program property
+ is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
+*/
+programMultipleItem
+ "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;
+programMultipleItem_1
+ progEnvParams .or progLocalParams;
+
+/*
+ <progEnvParams> ::= "program" "." "env"
+ "[" <progEnvParamNums> "]"
+
+NOTE: "program" "." has been moved to <programMultipleItem>.
+*/
+progEnvParams
+ "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;
+
+/*
+ <progEnvParamNums> ::= <progEnvParamNum>
+ | <progEnvParamNum> ".." <progEnvParamNum>
+*/
+progEnvParamNums
+ progEnvParamNums_1 .or progEnvParamNums_2;
+progEnvParamNums_1
+ progEnvParamNum .and dotdot_ne .and progEnvParamNum;
+progEnvParamNums_2
+ progEnvParamNum .and .true .emit 0x00;
+
+/*
+ <progEnvParam> ::= "program" "." "env"
+ "[" <progEnvParamNum> "]"
+
+NOTE: "program" "." has been moved to <programSingleItem>.
+*/
+progEnvParam
+ "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;
+
+/*
+ <progLocalParams> ::= "program" "." "local"
+ "[" <progLocalParamNums> "]"
+
+NOTE: "program" "." has been moved to <programMultipleItem>.
+*/
+progLocalParams
+ "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;
+
+/*
+ <progLocalParamNums> ::= <progLocalParamNum>
+ | <progLocalParamNum> ".." <progLocalParamNum>
+*/
+progLocalParamNums
+ progLocalParamNums_1 .or progLocalParamNums_2;
+progLocalParamNums_1
+ progLocalParamNum .and dotdot_ne .and progLocalParamNum;
+progLocalParamNums_2
+ progLocalParamNum .and .true .emit 0x00;
+
+/*
+ <progLocalParam> ::= "program" "." "local"
+ "[" <progLocalParamNum> "]"
+
+NOTE: "program" "." has been moved to <programSingleItem>.
+*/
+progLocalParam
+ "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;
+
+/*
+ <progEnvParamNum> ::= <integer> from 0 to
+ MAX_PROGRAM_ENV_PARAMETERS_ARB - 1
+*/
+progEnvParamNum
+ integer;
+
+/*
+ <progLocalParamNum> ::= <integer> from 0 to
+ MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1
+*/
+progLocalParamNum
+ integer;
+
+/*
+ <paramConstDecl> ::= <paramConstScalarDecl>
+ | <paramConstVector>
+*/
+paramConstDecl
+ paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
+
+/*
+ <paramConstUse> ::= <paramConstScalarUse>
+ | <paramConstVector>
+*/
+paramConstUse
+ paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
+
+/*
+ <paramConstScalarDecl> ::= <signedFloatConstant>
+*/
+paramConstScalarDecl
+ signedFloatConstant;
+
+/*
+ <paramConstScalarUse> ::= <floatConstant>
+*/
+paramConstScalarUse
+ floatConstant;
+
+/*
+ <paramConstVector> ::= "{" <signedFloatConstant> "}"
+ | "{" <signedFloatConstant> ","
+ <signedFloatConstant> "}"
+ | "{" <signedFloatConstant> ","
+ <signedFloatConstant> ","
+ <signedFloatConstant> "}"
+ | "{" <signedFloatConstant> ","
+ <signedFloatConstant> ","
+ <signedFloatConstant> ","
+ <signedFloatConstant> "}"
+*/
+paramConstVector
+ paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or
+ paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;
+paramConstVector_1
+ lbrace_ne .and signedFloatConstant .and rbrace;
+paramConstVector_2
+ lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
+paramConstVector_3
+ lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
+ signedFloatConstant .and rbrace;
+paramConstVector_4
+ lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
+ signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
+
+/*
+ <signedFloatConstant> ::= <optionalSign> <floatConstant>
+*/
+signedFloatConstant
+ optionalSign .and floatConstant;
+
+/*
+ <floatConstant> ::= see text
+ The <floatConstant> rule matches a floating-point constant consisting
+ of an integer part, a decimal point, a fraction part, an "e" or
+ "E", and an optionally signed integer exponent. The integer and
+ fraction parts both consist of a sequence of one or more digits ("0"
+ through "9"). Either the integer part or the fraction parts (not
+ both) may be missing; either the decimal point or the "e" (or "E")
+ and the exponent (not both) may be missing.
+*/
+floatConstant
+ float;
+
+/*
+ <optionalSign> ::= ""
+ | "-"
+ | "+"
+*/
+optionalSign
+ optional_sign_ne;
+
+/*
+ <TEMP_statement> ::= "TEMP" <varNameList>
+*/
+fp_TEMP_statement
+ "TEMP" .and space .and fp_varNameList .and .true .emit 0x00;
+vp_TEMP_statement
+ "TEMP" .and space .and vp_varNameList .and .true .emit 0x00;
+
+/*
+vertex program
+ <ADDRESS_statement> ::= "ADDRESS" <varNameList>
+*/
+ADDRESS_statement
+ "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00;
+
+/*
+ <varNameList> ::= <establishName>
+ | <establishName> "," <varNameList>
+*/
+fp_varNameList
+ fp_varNameList_1 .or fp_establishName;
+vp_varNameList
+ vp_varNameList_1 .or vp_establishName;
+fp_varNameList_1
+ fp_establishName .and comma_ne .and fp_varNameList;
+vp_varNameList_1
+ vp_establishName .and comma_ne .and vp_varNameList;
+
+/*
+ <OUTPUT_statement> ::= "OUTPUT" <establishName> "="
+ <resultBinding>
+*/
+fp_OUTPUT_statement
+ "OUTPUT" .and space .and fp_establishName .and equal .and
+ fp_resultBinding .error RESULT_EXPECTED;
+vp_OUTPUT_statement
+ "OUTPUT" .and space .and vp_establishName .and equal .and
+ vp_resultBinding .error RESULT_EXPECTED;
+
+/*
+fragment program
+ <resultBinding> ::= "result" "." "color"
+ | "result" "." "depth"
+
+vertex program
+ <resultBinding> ::= "result" "." "position"
+ | "result" "." <resultColBinding>
+ | "result" "." "fogcoord"
+ | "result" "." "pointsize"
+ | "result" "." "texcoord" <optTexCoordNum>
+*/
+fp_resultBinding
+ "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
+vp_resultBinding
+ "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
+fp_resultBinding_1
+ "color" .emit FRAGMENT_RESULT_COLOR .or
+ "depth" .emit FRAGMENT_RESULT_DEPTH;
+vp_resultBinding_1
+ .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or
+ resultColBinding .emit VERTEX_RESULT_COLOR .or
+ "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or
+ "pointsize" .emit VERTEX_RESULT_POINTSIZE .or
+ vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;
+vp_resultBinding_2
+ "texcoord" .and optTexCoordNum;
+
+/*
+vertex program
+ <resultColBinding> ::= "color" <optFaceType> <optColorType>
+*/
+resultColBinding
+ "color" .and optFaceType .and optColorType;
+
+/*
+ <optFaceType> ::= ""
+ | "." "front"
+ | "." "back"
+*/
+optFaceType
+ FaceType .or .true .emit FACE_FRONT;
+FaceType
+ dot_ne .and FaceProperty;
+FaceProperty
+ "front" .emit FACE_FRONT .or "back" .emit FACE_BACK;
+
+/*
+ <optColorType> ::= ""
+ | "." "primary"
+ | "." "secondary"
+*/
+optColorType
+ ColorType .or .true .emit COLOR_PRIMARY;
+ColorType
+ dot_ne .and ColorProperty;
+ColorProperty
+ "primary" .emit COLOR_PRIMARY .or
+ .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY;
+
+/*
+ <ALIAS_statement> ::= "ALIAS" <establishName> "="
+ <establishedName>
+*/
+fp_ALIAS_statement
+ "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;
+vp_ALIAS_statement
+ "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;
+fp_ALIAS_statement_1
+ space .and fp_establishName;
+vp_ALIAS_statement_1
+ space .and vp_establishName;
+
+/*
+ <establishName> ::= <identifier>
+*/
+fp_establishName
+ fp_identifier;
+vp_establishName
+ vp_identifier;
+
+/*
+ <establishedName> ::= <identifier>
+*/
+fp_establishedName
+ fp_identifier;
+vp_establishedName
+ vp_identifier;
+fp_establishedName_no_error_on_identifier
+ fp_identifier_ne;
+vp_establishedName_no_error_on_identifier
+ vp_identifier_ne;
+
+/*
+fragment program
+ <identifier> ::= see text
+ The <identifier> rule matches a sequence of one or more letters ("A"
+ through "Z", "a" through "z"), digits ("0" through "9), underscores
+ ("_"), or dollar signs ("$"); the first character must not be a
+ number. Upper and lower case letters are considered different
+ (names are case-sensitive). The following strings are reserved
+ keywords and may not be used as identifiers:
+
+ ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,
+ COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT,
+ END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2,
+ LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT,
+ MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM,
+ POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS,
+ SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT,
+ TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT,
+ fragment, program, result, state, and texture.
+
+vertex program
+ <identifier> ::= see text
+ The <identifier> rule matches a sequence of one or more letters ("A"
+ through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),
+ or dollar signs ("$"); the first character must not be a number. Upper
+ and lower case letters are considered different (names are
+ case-sensitive). The following strings are reserved keywords and may not
+ be used as identifiers:
+
+ ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,
+ EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,
+ PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,
+ state, and vertex.
+*/
+fp_identifier
+ fp_identifier_ne .error IDENTIFIER_EXPECTED;
+vp_identifier
+ vp_identifier_ne .error IDENTIFIER_EXPECTED;
+fp_identifier_ne
+ fp_not_reserved_identifier .and identifier_ne;
+vp_identifier_ne
+ vp_not_reserved_identifier .and identifier_ne;
+
+fp_not_reserved_identifier
+ fp_not_reserved_identifier_1 .or .true;
+fp_not_reserved_identifier_1
+ fp_reserved_identifier .and .false .error RESERVED_KEYWORD;
+vp_not_reserved_identifier
+ vp_not_reserved_identifier_1 .or .true;
+vp_not_reserved_identifier_1
+ vp_reserved_identifier .and .false .error RESERVED_KEYWORD;
+
+fp_reserved_identifier
+ "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or
+ "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or
+ "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or
+ "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or
+ "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or
+ "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or
+ "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or
+ "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or
+ "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or
+ "fragment" .or "program" .or "result" .or "state" .or "texture";
+vp_reserved_identifier
+ "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or
+ "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or
+ "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or
+ "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or
+ "XPD" .or "program" .or "result" .or "state" .or "vertex";
+
+/*
+ The <integer> rule matches an integer constant. The integer consists
+ of a sequence of one or more digits ("0" through "9").
+*/
+integer
+ integer_ne .error INTEGER_EXPECTED;
+
+zero
+ '0';
+
+leading_zeroes
+ .loop zero;
+
+no_digit
+ no_digit_1 .or .true;
+no_digit_1
+ digit10 .and .false .error INTEGER_OUT_OF_RANGE;
+
+all_zeroes
+ all_zeroes_1 .or no_digit_1;
+all_zeroes_1
+ '0' .and .loop zero .and no_digit;
+
+integer_0_3
+ integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
+integer_0_3_1
+ integer_0_3_2 .or all_zeroes .emit '0';
+integer_0_3_2 /* [1, 3] */
+ leading_zeroes .and '1'-'3' .emit * .and no_digit;
+
+integer_0_63
+ integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
+integer_0_63_1
+ integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or
+ all_zeroes .emit '0';
+integer_0_63_2 /* [7, 9] */
+ leading_zeroes .and '7'-'9' .emit * .and no_digit;
+integer_0_63_3 /* [10, 59] */
+ leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
+integer_0_63_4 /* [60, 63] */
+ leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;
+integer_0_63_5 /* [1, 6] */
+ leading_zeroes .and '1'-'6' .emit * .and no_digit;
+
+integer_0_64
+ integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
+integer_0_64_1
+ integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or
+ all_zeroes .emit '0';
+integer_0_64_2 /* [7, 9] */
+ leading_zeroes .and '7'-'9' .emit * .and no_digit;
+integer_0_64_3 /* [10, 59] */
+ leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
+integer_0_64_4 /* [60, 64] */
+ leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;
+integer_0_64_5 /* [1, 6] */
+ leading_zeroes .and '1'-'6' .emit * .and no_digit;
+
+optional_space
+ space .or .true;
+
+space_dst
+ space .error OPERATION_NEEDS_DESTINATION_VARIABLE;
+
+space_src
+ space .error OPERATION_NEEDS_SOURCE_VARIABLE;
+
+space
+ single_space .and .loop single_space;
+
+single_space
+ white_char .or comment_block;
+
+white_char
+ ' ' .or '\t' .or '\n' .or '\r';
+
+comment_block
+ '#' .and .loop comment_char .and new_line;
+
+/* All ASCII characters except '\r', '\n' and '\0' */
+comment_char
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+new_line
+ '\n' .or crlf .or '\0';
+
+crlf
+ '\r' .and '\n';
+
+semicolon
+ optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;
+
+comma
+ optional_space .and ',' .error MISSING_COMMA .and optional_space;
+
+comma_ne
+ optional_space .and ',' .and optional_space;
+
+lbracket
+ optional_space .and '[' .error MISSING_LBRACKET .and optional_space;
+
+lbracket_ne
+ optional_space .and '[' .and optional_space;
+
+rbracket
+ optional_space .and ']' .error MISSING_RBRACKET .and optional_space;
+
+dot
+ optional_space .and '.' .error MISSING_DOT .and optional_space;
+
+dot_ne
+ optional_space .and '.' .and optional_space;
+
+equal
+ optional_space .and '=' .error MISSING_EQUAL .and optional_space;
+
+lbrace
+ optional_space .and '{' .error MISSING_LBRACE .and optional_space;
+
+lbrace_ne
+ optional_space .and '{' .and optional_space;
+
+rbrace
+ optional_space .and '}' .error MISSING_RBRACE .and optional_space;
+
+dotdot
+ optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;
+
+dotdot_ne
+ optional_space .and '.' .and '.' .and optional_space;
+
+/*
+ The definition below accepts the following floating point number formats:
+ .99 .99e99 99. 99.99 99.99e99 99.e99 99e99
+ Also 99 format was considered and accepted because of a large number of existing program
+ strings with such a format.
+*/
+float
+ float_1 .or float_2 .or float_legacy;
+float_1
+ '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
+float_2
+ integer_ne .and float_3;
+float_3
+ float_4 .or float_5;
+float_4
+ '.' .and optional_integer .and optional_exponent;
+float_5
+ exponent .emit 0x00;
+float_legacy
+ integer_ne .and .true .emit 0x00 .emit 0x00;
+
+/*
+ Below is a correct version of <float> definiton.
+*/
+/*
+float
+ float_1 .or float_2;
+float_1
+ '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
+float_2
+ integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT;
+float_3
+ float_4 .or float_5;
+float_4
+ '.' .and optional_integer .and optional_exponent;
+float_5
+ exponent .emit 0x00;
+*/
+
+integer_ne
+ integer_ne_1 .and .true .emit 0x00 .emit $;
+integer_ne_1
+ digit10 .emit * .and .loop digit10 .emit *;
+
+optional_integer
+ integer_ne .or .true .emit 0x00;
+
+/*
+NOTE: If exponent part is omited we treat it as if it was "E+1".
+*/
+optional_exponent
+ exponent .or .true .emit 0x00;
+
+exponent
+ exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;
+exponent_1
+ 'e' .or 'E';
+
+optional_sign_ne
+ minus_ne .or plus_ne .or .true;
+
+plus_ne
+ optional_space .and '+' .and optional_space;
+
+minus_ne
+ optional_space .and '-' .emit '-' .and optional_space;
+
+identifier_ne
+ first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;
+
+follow_idchar
+ first_idchar .or digit10;
+
+first_idchar
+ 'a'-'z' .or 'A'-'Z' .or '_' .or '$';
+
+digit10
+ '0'-'9';
+
+/*
+ string filtering - if a string is encountered in grammar ("blabla"), the symbol below is
+ executed to create the string. The symbol must not throw any errors and emit bytes - it should
+ stop if it encounters invalid character. After this the resulting string (from starting
+ position up to the invalid character (but without it) is compared with the grammar string.
+*/
+.string __string_filter;
+
+__string_filter
+ .loop __identifier_char;
+
+__identifier_char
+ 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';
+
+/*
+ error token filtering
+*/
+e_signature
+ e_signature_char .and .loop e_signature_char;
+e_signature_char
+ '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';
+
+e_statement
+ .loop e_statement_not_term;
+/* All ASCII characters to one of '\r', '\n', '\0' and ';' */
+e_statement_not_term
+ '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+e_identifier
+ e_identifier_first .and .loop e_identifier_next;
+e_identifier_first
+ 'a'-'z' .or 'A'-'Z' .or '_' .or '$';
+e_identifier_next
+ e_identifier_first .or '0'-'9';
+
+e_token
+ e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or
+ '-' .or ',' .or ';';
+e_token_number
+ e_token_digit .and .loop e_token_digit;
+e_token_digit
+ '0'-'9';
+
+e_charordigit
+ 'A'-'Z' .or 'a'-'z' .or '0'-'9';
+
diff --git a/src/mesa/shader/arbprogram_syn.h b/src/mesa/shader/arbprogram_syn.h
index fe89b5ff3b5..71ccd204d12 100644
--- a/src/mesa/shader/arbprogram_syn.h
+++ b/src/mesa/shader/arbprogram_syn.h
@@ -1,1314 +1,1344 @@
-".syntax program;\n"
-".emtcode REVISION 0x07\n"
-".emtcode FRAGMENT_PROGRAM 0x01\n"
-".emtcode VERTEX_PROGRAM 0x02\n"
-".emtcode OPTION 0x01\n"
-".emtcode INSTRUCTION 0x02\n"
-".emtcode DECLARATION 0x03\n"
-".emtcode END 0x04\n"
-".emtcode ARB_PRECISION_HINT_FASTEST 0x01\n"
-".emtcode ARB_PRECISION_HINT_NICEST 0x02\n"
-".emtcode ARB_FOG_EXP 0x04\n"
-".emtcode ARB_FOG_EXP2 0x08\n"
-".emtcode ARB_FOG_LINEAR 0x10\n"
-".emtcode ARB_POSITION_INVARIANT 0x20\n"
-".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40\n"
-".emtcode OP_ALU_INST 0x00\n"
-".emtcode OP_TEX_INST 0x01\n"
-".emtcode OP_ALU_VECTOR 0x00\n"
-".emtcode OP_ALU_SCALAR 0x01\n"
-".emtcode OP_ALU_BINSC 0x02\n"
-".emtcode OP_ALU_BIN 0x03\n"
-".emtcode OP_ALU_TRI 0x04\n"
-".emtcode OP_ALU_SWZ 0x05\n"
-".emtcode OP_TEX_SAMPLE 0x06\n"
-".emtcode OP_TEX_KIL 0x07\n"
-".emtcode OP_ALU_ARL 0x08\n"
-".emtcode OP_ABS 0x00\n"
-".emtcode OP_ABS_SAT 0x1B\n"
-".emtcode OP_FLR 0x09\n"
-".emtcode OP_FLR_SAT 0x26\n"
-".emtcode OP_FRC 0x0A\n"
-".emtcode OP_FRC_SAT 0x27\n"
-".emtcode OP_LIT 0x0C\n"
-".emtcode OP_LIT_SAT 0x2A\n"
-".emtcode OP_MOV 0x11\n"
-".emtcode OP_MOV_SAT 0x30\n"
-".emtcode OP_COS 0x1F\n"
-".emtcode OP_COS_SAT 0x20\n"
-".emtcode OP_EX2 0x07\n"
-".emtcode OP_EX2_SAT 0x25\n"
-".emtcode OP_LG2 0x0B\n"
-".emtcode OP_LG2_SAT 0x29\n"
-".emtcode OP_RCP 0x14\n"
-".emtcode OP_RCP_SAT 0x33\n"
-".emtcode OP_RSQ 0x15\n"
-".emtcode OP_RSQ_SAT 0x34\n"
-".emtcode OP_SIN 0x38\n"
-".emtcode OP_SIN_SAT 0x39\n"
-".emtcode OP_SCS 0x35\n"
-".emtcode OP_SCS_SAT 0x36\n"
-".emtcode OP_POW 0x13\n"
-".emtcode OP_POW_SAT 0x32\n"
-".emtcode OP_ADD 0x01\n"
-".emtcode OP_ADD_SAT 0x1C\n"
-".emtcode OP_DP3 0x03\n"
-".emtcode OP_DP3_SAT 0x21\n"
-".emtcode OP_DP4 0x04\n"
-".emtcode OP_DP4_SAT 0x22\n"
-".emtcode OP_DPH 0x05\n"
-".emtcode OP_DPH_SAT 0x23\n"
-".emtcode OP_DST 0x06\n"
-".emtcode OP_DST_SAT 0x24\n"
-".emtcode OP_MAX 0x0F\n"
-".emtcode OP_MAX_SAT 0x2E\n"
-".emtcode OP_MIN 0x10\n"
-".emtcode OP_MIN_SAT 0x2F\n"
-".emtcode OP_MUL 0x12\n"
-".emtcode OP_MUL_SAT 0x31\n"
-".emtcode OP_SGE 0x16\n"
-".emtcode OP_SGE_SAT 0x37\n"
-".emtcode OP_SLT 0x17\n"
-".emtcode OP_SLT_SAT 0x3A\n"
-".emtcode OP_SUB 0x18\n"
-".emtcode OP_SUB_SAT 0x3B\n"
-".emtcode OP_XPD 0x1A\n"
-".emtcode OP_XPD_SAT 0x43\n"
-".emtcode OP_CMP 0x1D\n"
-".emtcode OP_CMP_SAT 0x1E\n"
-".emtcode OP_LRP 0x2B\n"
-".emtcode OP_LRP_SAT 0x2C\n"
-".emtcode OP_MAD 0x0E\n"
-".emtcode OP_MAD_SAT 0x2D\n"
-".emtcode OP_SWZ 0x19\n"
-".emtcode OP_SWZ_SAT 0x3C\n"
-".emtcode OP_TEX 0x3D\n"
-".emtcode OP_TEX_SAT 0x3E\n"
-".emtcode OP_TXB 0x3F\n"
-".emtcode OP_TXB_SAT 0x40\n"
-".emtcode OP_TXP 0x41\n"
-".emtcode OP_TXP_SAT 0x42\n"
-".emtcode OP_KIL 0x28\n"
-".emtcode OP_ARL 0x02\n"
-".emtcode OP_EXP 0x08\n"
-".emtcode OP_LOG 0x0D\n"
-".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n"
-".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n"
-".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n"
-".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n"
-".emtcode VERTEX_ATTRIB_POSITION 0x01\n"
-".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n"
-".emtcode VERTEX_ATTRIB_NORMAL 0x03\n"
-".emtcode VERTEX_ATTRIB_COLOR 0x04\n"
-".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n"
-".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n"
-".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n"
-".emtcode VERTEX_ATTRIB_GENERIC 0x08\n"
-".emtcode FRAGMENT_RESULT_COLOR 0x01\n"
-".emtcode FRAGMENT_RESULT_DEPTH 0x02\n"
-".emtcode VERTEX_RESULT_POSITION 0x01\n"
-".emtcode VERTEX_RESULT_COLOR 0x02\n"
-".emtcode VERTEX_RESULT_FOGCOORD 0x03\n"
-".emtcode VERTEX_RESULT_POINTSIZE 0x04\n"
-".emtcode VERTEX_RESULT_TEXCOORD 0x05\n"
-".emtcode TEXTARGET_1D 0x01\n"
-".emtcode TEXTARGET_2D 0x02\n"
-".emtcode TEXTARGET_3D 0x03\n"
-".emtcode TEXTARGET_RECT 0x04\n"
-".emtcode TEXTARGET_CUBE 0x05\n"
-".emtcode TEXTARGET_SHADOW1D 0x06\n"
-".emtcode TEXTARGET_SHADOW2D 0x07\n"
-".emtcode TEXTARGET_SHADOWRECT 0x08\n"
-".emtcode FACE_FRONT 0x00\n"
-".emtcode FACE_BACK 0x01\n"
-".emtcode COLOR_PRIMARY 0x00\n"
-".emtcode COLOR_SECONDARY 0x01\n"
-".emtcode COMPONENT_X 0x00\n"
-".emtcode COMPONENT_Y 0x01\n"
-".emtcode COMPONENT_Z 0x02\n"
-".emtcode COMPONENT_W 0x03\n"
-".emtcode COMPONENT_0 0x04\n"
-".emtcode COMPONENT_1 0x05\n"
-".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n"
-".emtcode ARRAY_INDEX_RELATIVE 0x01\n"
-".emtcode MATRIX_MODELVIEW 0x01\n"
-".emtcode MATRIX_PROJECTION 0x02\n"
-".emtcode MATRIX_MVP 0x03\n"
-".emtcode MATRIX_TEXTURE 0x04\n"
-".emtcode MATRIX_PALETTE 0x05\n"
-".emtcode MATRIX_PROGRAM 0x06\n"
-".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n"
-".emtcode MATRIX_MODIFIER_INVERSE 0x01\n"
-".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n"
-".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n"
-".emtcode CONSTANT_SCALAR 0x01\n"
-".emtcode CONSTANT_VECTOR 0x02\n"
-".emtcode PROGRAM_PARAM_ENV 0x01\n"
-".emtcode PROGRAM_PARAM_LOCAL 0x02\n"
-".emtcode REGISTER_ATTRIB 0x01\n"
-".emtcode REGISTER_PARAM 0x02\n"
-".emtcode REGISTER_RESULT 0x03\n"
-".emtcode REGISTER_ESTABLISHED_NAME 0x04\n"
-".emtcode PARAM_NULL 0x00\n"
-".emtcode PARAM_ARRAY_ELEMENT 0x01\n"
-".emtcode PARAM_STATE_ELEMENT 0x02\n"
-".emtcode PARAM_PROGRAM_ELEMENT 0x03\n"
-".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n"
-".emtcode PARAM_CONSTANT 0x05\n"
-".emtcode STATE_MATERIAL 0x01\n"
-".emtcode STATE_LIGHT 0x02\n"
-".emtcode STATE_LIGHT_MODEL 0x03\n"
-".emtcode STATE_LIGHT_PROD 0x04\n"
-".emtcode STATE_FOG 0x05\n"
-".emtcode STATE_MATRIX_ROWS 0x06\n"
-".emtcode STATE_TEX_ENV 0x07\n"
-".emtcode STATE_DEPTH 0x08\n"
-".emtcode STATE_TEX_GEN 0x09\n"
-".emtcode STATE_CLIP_PLANE 0x0A\n"
-".emtcode STATE_POINT 0x0B\n"
-".emtcode MATERIAL_AMBIENT 0x01\n"
-".emtcode MATERIAL_DIFFUSE 0x02\n"
-".emtcode MATERIAL_SPECULAR 0x03\n"
-".emtcode MATERIAL_EMISSION 0x04\n"
-".emtcode MATERIAL_SHININESS 0x05\n"
-".emtcode LIGHT_AMBIENT 0x01\n"
-".emtcode LIGHT_DIFFUSE 0x02\n"
-".emtcode LIGHT_SPECULAR 0x03\n"
-".emtcode LIGHT_POSITION 0x04\n"
-".emtcode LIGHT_ATTENUATION 0x05\n"
-".emtcode LIGHT_HALF 0x06\n"
-".emtcode LIGHT_SPOT_DIRECTION 0x07\n"
-".emtcode LIGHT_MODEL_AMBIENT 0x01\n"
-".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n"
-".emtcode LIGHT_PROD_AMBIENT 0x01\n"
-".emtcode LIGHT_PROD_DIFFUSE 0x02\n"
-".emtcode LIGHT_PROD_SPECULAR 0x03\n"
-".emtcode TEX_ENV_COLOR 0x01\n"
-".emtcode TEX_GEN_EYE 0x01\n"
-".emtcode TEX_GEN_OBJECT 0x02\n"
-".emtcode FOG_COLOR 0x01\n"
-".emtcode FOG_PARAMS 0x02\n"
-".emtcode DEPTH_RANGE 0x01\n"
-".emtcode POINT_SIZE 0x01\n"
-".emtcode POINT_ATTENUATION 0x02\n"
-".emtcode ATTRIB 0x01\n"
-".emtcode PARAM 0x02\n"
-".emtcode TEMP 0x03\n"
-".emtcode OUTPUT 0x04\n"
-".emtcode ALIAS 0x05\n"
-".emtcode ADDRESS 0x06\n"
-".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n"
-".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n"
-".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n"
-".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n"
-".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n"
-".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n"
-".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n"
-".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n"
-".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n"
-".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n"
-".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n"
-".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n"
-".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n"
-".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n"
-".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n"
-".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n"
-".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n"
-".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n"
-".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n"
-".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n"
-".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n"
-".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n"
-".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n"
-".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n"
-".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n"
-".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n"
-".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n"
-".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n"
-".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n"
-".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n"
-".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n"
-".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n"
-".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n"
-".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n"
-".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n"
-".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n"
-".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n"
-".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n"
-".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n"
-".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n"
-".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n"
-".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n"
-".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n"
-".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n"
-".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n"
-".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n"
-".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n"
-".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n"
-".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n"
-".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n"
-".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n"
-".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n"
-".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n"
-".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n"
-".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n"
-".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n"
-".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n"
-".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n"
-".regbyte vertex_blend 0x00\n"
-".regbyte matrix_palette 0x00\n"
-".regbyte point_parameters 0x01\n"
-".regbyte secondary_color 0x01\n"
-".regbyte fog_coord 0x01\n"
-".regbyte texture_rectangle 0x01\n"
-".regbyte fragment_program_shadow 0x00\n"
-".regbyte ARB_precision_hint_fastest 0x00\n"
-".regbyte ARB_precision_hint_nicest 0x00\n"
-".regbyte ARB_fog_exp 0x00\n"
-".regbyte ARB_fog_exp2 0x00\n"
-".regbyte ARB_fog_linear 0x00\n"
-".regbyte ARB_position_invariant 0x00\n"
-".regbyte ARB_fragment_program_shadow 0x00\n"
-".regbyte program_target 0x00\n"
-"program\n"
-" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n"
-"programs\n"
-" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n"
-" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n"
-"frag_program_1_0\n"
-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n"
-" optional_space .and fp_optionSequence .and fp_statementSequence .and\n"
-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
-" '\\0' .error CODE_AFTER_END;\n"
-"vert_program_1_0\n"
-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n"
-" optional_space .and vp_optionSequence .and vp_statementSequence .and\n"
-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
-" '\\0' .error CODE_AFTER_END;\n"
-"fp_optionSequence\n"
-" .loop fp_option;\n"
-"vp_optionSequence\n"
-" .loop vp_option;\n"
-"fp_option\n"
-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
-" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
-"vp_option\n"
-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
-" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
-"fp_optionString\n"
-" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n"
-" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n"
-" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n"
-" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n"
-" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n"
-" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n"
-" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n"
-" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n"
-" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;\n"
-"vp_optionString\n"
-" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n"
-"fp_ARB_fog_exp\n"
-" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n"
-"fp_ARB_fog_exp2\n"
-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n"
-"fp_ARB_fog_linear\n"
-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n"
-"fp_statementSequence\n"
-" .loop fp_statement;\n"
-"vp_statementSequence\n"
-" .loop vp_statement;\n"
-"fp_statement\n"
-" fp_statement_1 .or fp_statement_2;\n"
-"vp_statement\n"
-" vp_statement_1 .or vp_statement_2;\n"
-"fp_statement_1\n"
-" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
-"fp_statement_2\n"
-" fp_namingStatement .emit DECLARATION .and semicolon;\n"
-"vp_statement_1\n"
-" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
-"vp_statement_2\n"
-" vp_namingStatement .emit DECLARATION .and semicolon;\n"
-"fp_instruction\n"
-" ALUInstruction .emit OP_ALU_INST .or\n"
-" TexInstruction .emit OP_TEX_INST;\n"
-"vp_instruction\n"
-" ARL_instruction .emit OP_ALU_ARL .or\n"
-" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
-" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
-" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
-" vp_BINop_instruction .emit OP_ALU_BIN .or\n"
-" vp_TRIop_instruction .emit OP_ALU_TRI .or\n"
-" vp_SWZ_instruction .emit OP_ALU_SWZ;\n"
-"ALUInstruction\n"
-" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
-" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
-" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
-" fp_BINop_instruction .emit OP_ALU_BIN .or\n"
-" fp_TRIop_instruction .emit OP_ALU_TRI .or\n"
-" fp_SWZ_instruction .emit OP_ALU_SWZ;\n"
-"TexInstruction\n"
-" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n"
-" KIL_instruction .emit OP_TEX_KIL;\n"
-"ARL_instruction\n"
-" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n"
-"fp_VECTORop_instruction\n"
-" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n"
-"vp_VECTORop_instruction\n"
-" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n"
-"fp_VECTORop\n"
-" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n"
-" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n"
-" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n"
-" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n"
-" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n"
-"vp_VECTORop\n"
-" \"ABS\" .emit OP_ABS .or\n"
-" \"FLR\" .emit OP_FLR .or\n"
-" \"FRC\" .emit OP_FRC .or\n"
-" \"LIT\" .emit OP_LIT .or\n"
-" \"MOV\" .emit OP_MOV;\n"
-"fp_SCALARop_instruction\n"
-" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n"
-"vp_SCALARop_instruction\n"
-" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n"
-"fp_SCALARop\n"
-" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n"
-" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n"
-" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n"
-" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n"
-" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n"
-" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n"
-" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n"
-"vp_SCALARop\n"
-" \"EX2\" .emit OP_EX2 .or\n"
-" \"EXP\" .emit OP_EXP .or\n"
-" \"LG2\" .emit OP_LG2 .or\n"
-" \"LOG\" .emit OP_LOG .or\n"
-" \"RCP\" .emit OP_RCP .or\n"
-" \"RSQ\" .emit OP_RSQ;\n"
-"fp_BINSCop_instruction\n"
-" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n"
-" fp_scalarSrcReg;\n"
-"vp_BINSCop_instruction\n"
-" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n"
-" vp_scalarSrcReg;\n"
-"fp_BINSCop\n"
-" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n"
-"vp_BINSCop\n"
-" \"POW\" .emit OP_POW;\n"
-"fp_BINop_instruction\n"
-" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
-" vectorSrcReg;\n"
-"vp_BINop_instruction\n"
-" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
-" swizzleSrcReg;\n"
-"fp_BINop\n"
-" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n"
-" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n"
-" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n"
-" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n"
-" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n"
-" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n"
-" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n"
-" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n"
-" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n"
-" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n"
-" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n"
-" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n"
-"vp_BINop\n"
-" \"ADD\" .emit OP_ADD .or\n"
-" \"DP3\" .emit OP_DP3 .or\n"
-" \"DP4\" .emit OP_DP4 .or\n"
-" \"DPH\" .emit OP_DPH .or\n"
-" \"DST\" .emit OP_DST .or\n"
-" \"MAX\" .emit OP_MAX .or\n"
-" \"MIN\" .emit OP_MIN .or\n"
-" \"MUL\" .emit OP_MUL .or\n"
-" \"SGE\" .emit OP_SGE .or\n"
-" \"SLT\" .emit OP_SLT .or\n"
-" \"SUB\" .emit OP_SUB .or\n"
-" \"XPD\" .emit OP_XPD;\n"
-"fp_TRIop_instruction\n"
-" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
-" vectorSrcReg .and comma .and vectorSrcReg;\n"
-"vp_TRIop_instruction\n"
-" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
-" swizzleSrcReg .and comma .and swizzleSrcReg;\n"
-"fp_TRIop\n"
-" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n"
-" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n"
-" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n"
-"vp_TRIop\n"
-" \"MAD\" .emit OP_MAD;\n"
-"fp_SWZ_instruction\n"
-" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n"
-" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
-"vp_SWZ_instruction\n"
-" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n"
-" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
-"SWZop\n"
-" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n"
-"SAMPLE_instruction\n"
-" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
-" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n"
-"SAMPLEop\n"
-" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n"
-" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n"
-" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n"
-"KIL_instruction\n"
-" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n"
-"texImageUnit\n"
-" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n"
-"texTarget\n"
-" \"1D\" .emit TEXTARGET_1D .or\n"
-" \"2D\" .emit TEXTARGET_2D .or\n"
-" \"3D\" .emit TEXTARGET_3D .or\n"
-" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n"
-" \"CUBE\" .emit TEXTARGET_CUBE .or\n"
-" .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\n"
-"shadowTarget\n"
-" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n"
-" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n"
-" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT;\n"
-"optTexImageUnitNum\n"
-" optTexImageUnitNum_1 .or .true .emit 0x00;\n"
-"optTexImageUnitNum_1\n"
-" lbracket_ne .and texImageUnitNum .and rbracket;\n"
-"texImageUnitNum\n"
-" integer;\n"
-"fp_scalarSrcReg\n"
-" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n"
-"vp_scalarSrcReg\n"
-" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n"
-"swizzleSrcReg\n"
-" optionalSign .and vp_srcReg .and swizzleSuffix;\n"
-"vectorSrcReg\n"
-" optionalSign .and fp_srcReg .and optionalSuffix;\n"
-"fp_maskedDstReg\n"
-" fp_dstReg .and fp_optionalMask;\n"
-"vp_maskedDstReg\n"
-" vp_dstReg .and vp_optionalMask;\n"
-"maskedAddrReg\n"
-" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n"
-"fp_extendedSwizzle\n"
-" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n"
-"vp_extendedSwizzle\n"
-" extSwizComp .and comma .and\n"
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"xyzwExtendedSwizzle\n"
-" xyzwExtSwizComp .and comma .and\n"
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"rgbaExtendedSwizzle\n"
-" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n"
-" rgbaExtendedSwizzle_4;\n"
-"rgbaExtendedSwizzle_1\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n"
-"rgbaExtendedSwizzle_2\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
-" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"rgbaExtendedSwizzle_3\n"
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"rgbaExtendedSwizzle_4\n"
-" rgbaExtSwizComp_alpha .and comma .and \n"
-"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
-"xyzwExtSwizComp\n"
-" optionalSign .and xyzwExtSwizSel;\n"
-"rgbaExtSwizComp\n"
-" optionalSign .and rgbaExtSwizSel;\n"
-"rgbaExtSwizComp_digit\n"
-" optionalSign .and rgbaExtSwizSel_digit;\n"
-"rgbaExtSwizComp_alpha\n"
-" optionalSign .and rgbaExtSwizSel_alpha;\n"
-"extSwizComp\n"
-" optionalSign .and extSwizSel;\n"
-"xyzwExtSwizSel\n"
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n"
-"rgbaExtSwizSel\n"
-" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n"
-"rgbaExtSwizSel_digit\n"
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n"
-"rgbaExtSwizSel_alpha\n"
-" rgbaComponent_single;\n"
-"extSwizSel\n"
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n"
-"fp_srcReg\n"
-" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
-"vp_srcReg\n"
-" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
-"fp_srcReg_1\n"
-" fragmentAttribReg .emit REGISTER_ATTRIB .or\n"
-" fp_progParamReg .emit REGISTER_PARAM .or\n"
-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"vp_srcReg_1\n"
-" vertexAttribReg .emit REGISTER_ATTRIB .or\n"
-" vp_progParamReg .emit REGISTER_PARAM .or\n"
-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"fp_dstReg\n"
-" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
-"vp_dstReg\n"
-" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
-"fp_dstReg_1\n"
-" fragmentResultReg .emit REGISTER_RESULT .or\n"
-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"vp_dstReg_1\n"
-" vertexResultReg .emit REGISTER_RESULT .or\n"
-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
-"fragmentAttribReg\n"
-" fragAttribBinding;\n"
-"vertexAttribReg\n"
-" vtxAttribBinding;\n"
-"fp_temporaryReg\n"
-" fp_establishedName_no_error_on_identifier;\n"
-"vp_temporaryReg\n"
-" vp_establishedName_no_error_on_identifier;\n"
-"fp_progParamReg\n"
-" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n"
-"vp_progParamReg\n"
-" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n"
-"fp_progParamReg_1\n"
-" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n"
-" rbracket;\n"
-"vp_progParamReg_1\n"
-" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n"
-" rbracket;\n"
-"fp_progParamSingle\n"
-" .false;\n"
-"vp_progParamSingle\n"
-" .false;\n"
-"fp_progParamArray\n"
-" fp_establishedName_no_error_on_identifier;\n"
-"vp_progParamArray\n"
-" vp_establishedName_no_error_on_identifier;\n"
-"progParamArrayMem\n"
-" progParamArrayAbs .or progParamArrayRel;\n"
-"progParamArrayAbs\n"
-" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n"
-"progParamArrayRel\n"
-" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n"
-" addrComponent .and addrRegRelOffset;\n"
-"addrRegRelOffset\n"
-" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n"
-"addrRegRelOffset_1\n"
-" plus_ne .and addrRegPosOffset;\n"
-"addrRegRelOffset_2\n"
-" minus_ne .and addrRegNegOffset;\n"
-"addrRegPosOffset\n"
-" integer_0_63;\n"
-"addrRegNegOffset\n"
-" integer_0_64;\n"
-"fragmentResultReg\n"
-" fp_resultBinding;\n"
-"vertexResultReg\n"
-" vp_resultBinding;\n"
-"addrReg\n"
-" vp_establishedName_no_error_on_identifier;\n"
-"addrComponent\n"
-" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n"
-" .emit COMPONENT_X .emit COMPONENT_X;\n"
-"addrWriteMask\n"
-" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n"
-"fp_scalarSuffix\n"
-" dot .and fp_component_single .error INVALID_COMPONENT;\n"
-"vp_scalarSuffix\n"
-" dot .and vp_component_single .error INVALID_COMPONENT;\n"
-"swizzleSuffix\n"
-" swizzleSuffix_1 .or\n"
-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
-"swizzleSuffix_1\n"
-" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n"
-"swizzleSuffix_2\n"
-" swizzleSuffix_3 .or swizzleSuffix_4;\n"
-"swizzleSuffix_3\n"
-" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n"
-" vp_component_multi .error INVALID_COMPONENT;\n"
-"swizzleSuffix_4\n"
-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
-"optionalSuffix\n"
-" optionalSuffix_1 .or\n"
-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
-"optionalSuffix_1\n"
-" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n"
-"optionalSuffix_2\n"
-" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n"
-"optionalSuffix_3\n"
-" xyzwComponent_multi .and xyzwComponent_multi .and\n"
-" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n"
-"optionalSuffix_4\n"
-" rgbaComponent_multi .and rgbaComponent_multi .and\n"
-" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n"
-"optionalSuffix_5\n"
-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n"
-" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
-" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
-" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
-" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
-"fp_component_single\n"
-" xyzwComponent_single .or rgbaComponent_single;\n"
-"vp_component_multi\n"
-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
-" 'w' .emit COMPONENT_W;\n"
-"vp_component_single\n"
-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W;\n"
-"xyzwComponent_multi\n"
-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
-" 'w' .emit COMPONENT_W;\n"
-"xyzwComponent_single\n"
-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
-" \"w\" .emit COMPONENT_W;\n"
-"rgbaComponent_multi\n"
-" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n"
-" 'a' .emit COMPONENT_W;\n"
-"rgbaComponent_single\n"
-" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n"
-" \"a\" .emit COMPONENT_W;\n"
-"fp_optionalMask\n"
-" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n"
-"vp_optionalMask\n"
-" xyzwMask .or .true .emit 0x0F;\n"
-"xyzwMask\n"
-" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n"
-"xyzwMask_1\n"
-" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n"
-" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n"
-" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n"
-" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n"
-"rgbaMask\n"
-" dot_ne .and rgbaMask_1;\n"
-"rgbaMask_1\n"
-" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n"
-" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n"
-" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n"
-" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n"
-"fp_namingStatement\n"
-" fp_ATTRIB_statement .emit ATTRIB .or\n"
-" fp_PARAM_statement .emit PARAM .or\n"
-" fp_TEMP_statement .emit TEMP .or\n"
-" fp_OUTPUT_statement .emit OUTPUT .or\n"
-" fp_ALIAS_statement .emit ALIAS;\n"
-"vp_namingStatement\n"
-" vp_ATTRIB_statement .emit ATTRIB .or\n"
-" vp_PARAM_statement .emit PARAM .or\n"
-" vp_TEMP_statement .emit TEMP .or\n"
-" ADDRESS_statement .emit ADDRESS .or\n"
-" vp_OUTPUT_statement .emit OUTPUT .or\n"
-" vp_ALIAS_statement .emit ALIAS;\n"
-"fp_ATTRIB_statement\n"
-" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n"
-" fragAttribBinding .error FRAGMENT_EXPECTED;\n"
-"vp_ATTRIB_statement\n"
-" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n"
-" vtxAttribBinding .error VERTEX_EXPECTED;\n"
-"fragAttribBinding\n"
-" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n"
-"vtxAttribBinding\n"
-" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n"
-"fragAttribItem\n"
-" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n"
-" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n"
-" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n"
-" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n"
-"fragAttribItem_1\n"
-" \"color\" .and optColorType;\n"
-"fragAttribItem_2\n"
-" \"texcoord\" .and optTexCoordNum;\n"
-"vtxAttribItem\n"
-" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n"
-" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n"
-" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n"
-" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n"
-" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n"
-" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n"
-" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n"
-" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n"
-"vtxAttribItem_1\n"
-" \"weight\" .and vtxOptWeightNum;\n"
-"vtxAttribItem_2\n"
-" \"color\" .and optColorType;\n"
-"vtxAttribItem_3\n"
-" \"texcoord\" .and optTexCoordNum;\n"
-"vtxAttribItem_4\n"
-" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n"
-"vtxAttribItem_5\n"
-" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n"
-"vtxAttribNum\n"
-" integer;\n"
-"vtxOptWeightNum\n"
-" vtxOptWeightNum_1 .or .true .emit 0x00;\n"
-"vtxOptWeightNum_1\n"
-" lbracket_ne .and vtxWeightNum .and rbracket;\n"
-"vtxWeightNum\n"
-" integer;\n"
-"fp_PARAM_statement\n"
-" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n"
-"vp_PARAM_statement\n"
-" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n"
-"fp_PARAM_singleStmt\n"
-" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n"
-" .true .emit PARAM_NULL;\n"
-"vp_PARAM_singleStmt\n"
-" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n"
-" .true .emit PARAM_NULL;\n"
-"fp_PARAM_multipleStmt\n"
-" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
-" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
-"vp_PARAM_multipleStmt\n"
-" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
-" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
-"optArraySize\n"
-" optional_integer;\n"
-"fp_paramSingleInit\n"
-" equal .and fp_paramSingleItemDecl;\n"
-"vp_paramSingleInit\n"
-" equal .and vp_paramSingleItemDecl;\n"
-"fp_paramMultipleInit\n"
-" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n"
-"vp_paramMultipleInit\n"
-" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n"
-"fp_paramMultInitList\n"
-" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n"
-"vp_paramMultInitList\n"
-" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n"
-"fp_paramMultInitList_1\n"
-" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n"
-"vp_paramMultInitList_1\n"
-" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n"
-"fp_paramSingleItemDecl\n"
-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"vp_paramSingleItemDecl\n"
-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"fp_paramSingleItemUse\n"
-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstUse .emit PARAM_CONSTANT;\n"
-"vp_paramSingleItemUse\n"
-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstUse .emit PARAM_CONSTANT;\n"
-"fp_paramMultipleItem\n"
-" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"vp_paramMultipleItem\n"
-" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
-" paramConstDecl .emit PARAM_CONSTANT;\n"
-"fp_stateMultipleItem\n"
-" stateMultipleItem_1 .or fp_stateSingleItem;\n"
-"vp_stateMultipleItem\n"
-" stateMultipleItem_1 .or vp_stateSingleItem;\n"
-"stateMultipleItem_1\n"
-" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n"
-"fp_stateSingleItem\n"
-" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
-"vp_stateSingleItem\n"
-" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
-"fp_stateSingleItem_1\n"
-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
-" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n"
-"vp_stateSingleItem_1\n"
-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
-" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n"
-" stateSingleItem_11;\n"
-"stateSingleItem_1\n"
-" stateMaterialItem .emit STATE_MATERIAL;\n"
-"stateSingleItem_2\n"
-" stateLightItem .emit STATE_LIGHT;\n"
-"stateSingleItem_3\n"
-" stateLightModelItem .emit STATE_LIGHT_MODEL;\n"
-"stateSingleItem_4\n"
-" stateLightProdItem .emit STATE_LIGHT_PROD;\n"
-"stateSingleItem_5\n"
-" stateTexEnvItem .emit STATE_TEX_ENV;\n"
-"stateSingleItem_6\n"
-" stateTexGenItem .emit STATE_TEX_GEN;\n"
-"stateSingleItem_7\n"
-" stateFogItem .emit STATE_FOG;\n"
-"stateSingleItem_8\n"
-" stateDepthItem .emit STATE_DEPTH;\n"
-"stateSingleItem_9\n"
-" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n"
-"stateSingleItem_10\n"
-" statePointItem .emit STATE_POINT;\n"
-"stateSingleItem_11\n"
-" stateMatrixRow .emit STATE_MATRIX_ROWS;\n"
-"stateMaterialItem\n"
-" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n"
-"stateMatProperty\n"
-" \"ambient\" .emit MATERIAL_AMBIENT .or\n"
-" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n"
-" \"specular\" .emit MATERIAL_SPECULAR .or\n"
-" \"emission\" .emit MATERIAL_EMISSION .or\n"
-" \"shininess\" .emit MATERIAL_SHININESS;\n"
-"stateLightItem\n"
-" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n"
-" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n"
-"stateLightProperty\n"
-" \"ambient\" .emit LIGHT_AMBIENT .or\n"
-" \"diffuse\" .emit LIGHT_DIFFUSE .or\n"
-" \"specular\" .emit LIGHT_SPECULAR .or\n"
-" \"position\" .emit LIGHT_POSITION .or\n"
-" \"attenuation\" .emit LIGHT_ATTENUATION .or\n"
-" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n"
-" \"half\" .emit LIGHT_HALF;\n"
-"stateLightProperty_1\n"
-" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n"
-"stateSpotProperty\n"
-" \"direction\";\n"
-"stateLightModelItem\n"
-" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n"
-"stateLModProperty\n"
-" stateLModProperty_1 .or stateLModProperty_2;\n"
-"stateLModProperty_1\n"
-" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n"
-"stateLModProperty_2\n"
-" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n"
-"stateLModProperty_3\n"
-" optFaceType .and dot .and \"scenecolor\";\n"
-"stateLightProdItem\n"
-" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n"
-" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n"
-"stateLProdProperty\n"
-" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n"
-" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n"
-" \"specular\" .emit LIGHT_PROD_SPECULAR;\n"
-"stateLightNumber\n"
-" integer;\n"
-"stateTexEnvItem\n"
-" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n"
-" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n"
-"stateTexEnvProperty\n"
-" \"color\" .emit TEX_ENV_COLOR;\n"
-"optLegacyTexUnitNum\n"
-" lbracket_ne .and legacyTexUnitNum .and rbracket;\n"
-"legacyTexUnitNum\n"
-" integer;\n"
-"stateTexGenItem\n"
-" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n"
-" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n"
-"stateTexGenType\n"
-" \"eye\" .emit TEX_GEN_EYE .or\n"
-" \"object\" .emit TEX_GEN_OBJECT;\n"
-"stateTexGenCoord\n"
-" \"s\" .emit COMPONENT_X .or\n"
-" \"t\" .emit COMPONENT_Y .or\n"
-" \"r\" .emit COMPONENT_Z .or\n"
-" \"q\" .emit COMPONENT_W;\n"
-"stateFogItem\n"
-" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n"
-"stateFogProperty\n"
-" \"color\" .emit FOG_COLOR .or\n"
-" \"params\" .emit FOG_PARAMS;\n"
-"stateDepthItem\n"
-" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n"
-"stateDepthProperty\n"
-" \"range\" .emit DEPTH_RANGE;\n"
-"stateClipPlaneItem\n"
-" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n"
-" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n"
-"stateClipPlaneNum\n"
-" integer;\n"
-"statePointItem\n"
-" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n"
-"statePointProperty\n"
-" \"size\" .emit POINT_SIZE .or\n"
-" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n"
-"stateMatrixRow\n"
-" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n"
-" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n"
-"stateMatrixRows\n"
-" stateMatrixItem .and optMatrixRows;\n"
-"optMatrixRows\n"
-" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n"
-"optMatrixRows_1\n"
-" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n"
-" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n"
-"stateMatrixItem\n"
-" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n"
-"stateOptMatModifier\n"
-" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n"
-"stateOptMatModifier_1\n"
-" dot_ne .and stateMatModifier;\n"
-"stateMatModifier\n"
-" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n"
-" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n"
-" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n"
-"stateMatrixRowNum\n"
-" integer_0_3;\n"
-"stateMatrixName\n"
-" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n"
-" \"projection\" .emit MATRIX_PROJECTION .or\n"
-" \"mvp\" .emit MATRIX_MVP .or\n"
-" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n"
-" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n"
-" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n"
-"stateMatrixName_1_1\n"
-" \"modelview\" .and stateOptModMatNum;\n"
-"stateMatrixName_1_2\n"
-" \"texture\" .and optTexCoordNum;\n"
-"stateMatrixName_1_3\n"
-" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n"
-"stateMatrixName_1_4\n"
-" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n"
-"stateOptModMatNum\n"
-" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n"
-" .true .emit 0x00;\n"
-"stateOptModMatNum_1\n"
-" lbracket_ne .and stateModMatNum .and rbracket;\n"
-"stateModMatNum\n"
-" integer;\n"
-"optTexCoordNum\n"
-" optTexCoordNum_1 .or .true .emit 0x00;\n"
-"optTexCoordNum_1\n"
-" lbracket_ne .and texCoordNum .and rbracket;\n"
-"texCoordNum\n"
-" integer;\n"
-"statePaletteMatNum\n"
-" integer;\n"
-"stateProgramMatNum\n"
-" integer;\n"
-"programSingleItem\n"
-" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
-"programSingleItem_1\n"
-" progEnvParam .or progLocalParam;\n"
-"programMultipleItem\n"
-" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
-"programMultipleItem_1\n"
-" progEnvParams .or progLocalParams;\n"
-"progEnvParams\n"
-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n"
-"progEnvParamNums\n"
-" progEnvParamNums_1 .or progEnvParamNums_2;\n"
-"progEnvParamNums_1\n"
-" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n"
-"progEnvParamNums_2\n"
-" progEnvParamNum .and .true .emit 0x00;\n"
-"progEnvParam\n"
-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n"
-"progLocalParams\n"
-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n"
-"progLocalParamNums\n"
-" progLocalParamNums_1 .or progLocalParamNums_2;\n"
-"progLocalParamNums_1\n"
-" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n"
-"progLocalParamNums_2\n"
-" progLocalParamNum .and .true .emit 0x00;\n"
-"progLocalParam\n"
-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n"
-"progEnvParamNum\n"
-" integer;\n"
-"progLocalParamNum\n"
-" integer;\n"
-"paramConstDecl\n"
-" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
-"paramConstUse\n"
-" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
-"paramConstScalarDecl\n"
-" signedFloatConstant;\n"
-"paramConstScalarUse\n"
-" floatConstant;\n"
-"paramConstVector\n"
-" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n"
-" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n"
-"paramConstVector_1\n"
-" lbrace_ne .and signedFloatConstant .and rbrace;\n"
-"paramConstVector_2\n"
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
-"paramConstVector_3\n"
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
-" signedFloatConstant .and rbrace;\n"
-"paramConstVector_4\n"
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
-" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
-"signedFloatConstant\n"
-" optionalSign .and floatConstant;\n"
-"floatConstant\n"
-" float;\n"
-"optionalSign\n"
-" optional_sign_ne;\n"
-"fp_TEMP_statement\n"
-" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n"
-"vp_TEMP_statement\n"
-" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
-"ADDRESS_statement\n"
-" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
-"fp_varNameList\n"
-" fp_varNameList_1 .or fp_establishName;\n"
-"vp_varNameList\n"
-" vp_varNameList_1 .or vp_establishName;\n"
-"fp_varNameList_1\n"
-" fp_establishName .and comma_ne .and fp_varNameList;\n"
-"vp_varNameList_1\n"
-" vp_establishName .and comma_ne .and vp_varNameList;\n"
-"fp_OUTPUT_statement\n"
-" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n"
-" fp_resultBinding .error RESULT_EXPECTED;\n"
-"vp_OUTPUT_statement\n"
-" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n"
-" vp_resultBinding .error RESULT_EXPECTED;\n"
-"fp_resultBinding\n"
-" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
-"vp_resultBinding\n"
-" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
-"fp_resultBinding_1\n"
-" \"color\" .emit FRAGMENT_RESULT_COLOR .or\n"
-" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n"
-"vp_resultBinding_1\n"
-" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n"
-" resultColBinding .emit VERTEX_RESULT_COLOR .or\n"
-" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n"
-" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n"
-" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n"
-"vp_resultBinding_2\n"
-" \"texcoord\" .and optTexCoordNum;\n"
-"resultColBinding\n"
-" \"color\" .and optFaceType .and optColorType;\n"
-"optFaceType\n"
-" FaceType .or .true .emit FACE_FRONT;\n"
-"FaceType\n"
-" dot_ne .and FaceProperty;\n"
-"FaceProperty\n"
-" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n"
-"optColorType\n"
-" ColorType .or .true .emit COLOR_PRIMARY;\n"
-"ColorType\n"
-" dot_ne .and ColorProperty;\n"
-"ColorProperty\n"
-" \"primary\" .emit COLOR_PRIMARY .or\n"
-" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n"
-"fp_ALIAS_statement\n"
-" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n"
-"vp_ALIAS_statement\n"
-" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n"
-"fp_ALIAS_statement_1\n"
-" space .and fp_establishName;\n"
-"vp_ALIAS_statement_1\n"
-" space .and vp_establishName;\n"
-"fp_establishName\n"
-" fp_identifier;\n"
-"vp_establishName\n"
-" vp_identifier;\n"
-"fp_establishedName\n"
-" fp_identifier;\n"
-"vp_establishedName\n"
-" vp_identifier;\n"
-"fp_establishedName_no_error_on_identifier\n"
-" fp_identifier_ne;\n"
-"vp_establishedName_no_error_on_identifier\n"
-" vp_identifier_ne;\n"
-"fp_identifier\n"
-" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
-"vp_identifier\n"
-" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
-"fp_identifier_ne\n"
-" fp_not_reserved_identifier .and identifier_ne;\n"
-"vp_identifier_ne\n"
-" vp_not_reserved_identifier .and identifier_ne;\n"
-"fp_not_reserved_identifier\n"
-" fp_not_reserved_identifier_1 .or .true;\n"
-"fp_not_reserved_identifier_1\n"
-" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
-"vp_not_reserved_identifier\n"
-" vp_not_reserved_identifier_1 .or .true;\n"
-"vp_not_reserved_identifier_1\n"
-" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
-"fp_reserved_identifier\n"
-" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n"
-" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n"
-" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n"
-" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n"
-" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n"
-" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n"
-" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n"
-" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n"
-" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n"
-" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n"
-"vp_reserved_identifier\n"
-" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n"
-" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n"
-" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n"
-" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n"
-" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n"
-"integer\n"
-" integer_ne .error INTEGER_EXPECTED;\n"
-"zero\n"
-" '0';\n"
-"leading_zeroes\n"
-" .loop zero;\n"
-"no_digit\n"
-" no_digit_1 .or .true;\n"
-"no_digit_1\n"
-" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n"
-"all_zeroes\n"
-" all_zeroes_1 .or no_digit_1;\n"
-"all_zeroes_1\n"
-" '0' .and .loop zero .and no_digit;\n"
-"integer_0_3\n"
-" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
-"integer_0_3_1\n"
-" integer_0_3_2 .or all_zeroes .emit '0';\n"
-"integer_0_3_2 \n"
-" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n"
-"integer_0_63\n"
-" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
-"integer_0_63_1\n"
-" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n"
-" all_zeroes .emit '0';\n"
-"integer_0_63_2 \n"
-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
-"integer_0_63_3 \n"
-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
-"integer_0_63_4 \n"
-" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n"
-"integer_0_63_5 \n"
-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
-"integer_0_64\n"
-" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
-"integer_0_64_1\n"
-" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n"
-" all_zeroes .emit '0';\n"
-"integer_0_64_2 \n"
-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
-"integer_0_64_3 \n"
-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
-"integer_0_64_4 \n"
-" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n"
-"integer_0_64_5 \n"
-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
-"optional_space\n"
-" space .or .true;\n"
-"space_dst\n"
-" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n"
-"space_src\n"
-" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n"
-"space\n"
-" single_space .and .loop single_space;\n"
-"single_space\n"
-" white_char .or comment_block;\n"
-"white_char\n"
-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
-"comment_block\n"
-" '#' .and .loop comment_char .and new_line;\n"
-"comment_char\n"
-" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
-"new_line\n"
-" '\\n' .or crlf .or '\\0';\n"
-"crlf\n"
-" '\\r' .and '\\n';\n"
-"semicolon\n"
-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
-"comma\n"
-" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n"
-"comma_ne\n"
-" optional_space .and ',' .and optional_space;\n"
-"lbracket\n"
-" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n"
-"lbracket_ne\n"
-" optional_space .and '[' .and optional_space;\n"
-"rbracket\n"
-" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n"
-"dot\n"
-" optional_space .and '.' .error MISSING_DOT .and optional_space;\n"
-"dot_ne\n"
-" optional_space .and '.' .and optional_space;\n"
-"equal\n"
-" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n"
-"lbrace\n"
-" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n"
-"lbrace_ne\n"
-" optional_space .and '{' .and optional_space;\n"
-"rbrace\n"
-" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n"
-"dotdot\n"
-" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n"
-"dotdot_ne\n"
-" optional_space .and '.' .and '.' .and optional_space;\n"
-"float\n"
-" float_1 .or float_2 .or float_legacy;\n"
-"float_1\n"
-" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n"
-"float_2\n"
-" integer_ne .and float_3;\n"
-"float_3\n"
-" float_4 .or float_5;\n"
-"float_4\n"
-" '.' .and optional_integer .and optional_exponent;\n"
-"float_5\n"
-" exponent .emit 0x00;\n"
-"float_legacy\n"
-" integer_ne .and .true .emit 0x00 .emit 0x00;\n"
-"integer_ne\n"
-" integer_ne_1 .and .true .emit 0x00 .emit $;\n"
-"integer_ne_1\n"
-" digit10 .emit * .and .loop digit10 .emit *;\n"
-"optional_integer\n"
-" integer_ne .or .true .emit 0x00;\n"
-"optional_exponent\n"
-" exponent .or .true .emit 0x00;\n"
-"exponent\n"
-" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n"
-"exponent_1\n"
-" 'e' .or 'E';\n"
-"optional_sign_ne\n"
-" minus_ne .or plus_ne .or .true;\n"
-"plus_ne\n"
-" optional_space .and '+' .and optional_space;\n"
-"minus_ne\n"
-" optional_space .and '-' .emit '-' .and optional_space;\n"
-"identifier_ne\n"
-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n"
-"follow_idchar\n"
-" first_idchar .or digit10;\n"
-"first_idchar\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
-"digit10\n"
-" '0'-'9';\n"
-".string __string_filter;\n"
-"__string_filter\n"
-" .loop __identifier_char;\n"
-"__identifier_char\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n"
-"e_signature\n"
-" e_signature_char .and .loop e_signature_char;\n"
-"e_signature_char\n"
-" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
-"e_statement\n"
-" .loop e_statement_not_term;\n"
-"e_statement_not_term\n"
-" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
-"e_identifier\n"
-" e_identifier_first .and .loop e_identifier_next;\n"
-"e_identifier_first\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
-"e_identifier_next\n"
-" e_identifier_first .or '0'-'9';\n"
-"e_token\n"
-" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n"
-" '-' .or ',' .or ';';\n"
-"e_token_number\n"
-" e_token_digit .and .loop e_token_digit;\n"
-"e_token_digit\n"
-" '0'-'9';\n"
-"e_charordigit\n"
-" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
-"" \ No newline at end of file
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * \file arbprogram_syn.h
+ * ARB_fragment_program/ARB_vertex_program syntax
+ * \author Michal Krol
+ */
+
+".syntax program;\n"
+".emtcode REVISION 0x07\n"
+".emtcode FRAGMENT_PROGRAM 0x01\n"
+".emtcode VERTEX_PROGRAM 0x02\n"
+".emtcode OPTION 0x01\n"
+".emtcode INSTRUCTION 0x02\n"
+".emtcode DECLARATION 0x03\n"
+".emtcode END 0x04\n"
+".emtcode ARB_PRECISION_HINT_FASTEST 0x01\n"
+".emtcode ARB_PRECISION_HINT_NICEST 0x02\n"
+".emtcode ARB_FOG_EXP 0x04\n"
+".emtcode ARB_FOG_EXP2 0x08\n"
+".emtcode ARB_FOG_LINEAR 0x10\n"
+".emtcode ARB_POSITION_INVARIANT 0x20\n"
+".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40\n"
+".emtcode OP_ALU_INST 0x00\n"
+".emtcode OP_TEX_INST 0x01\n"
+".emtcode OP_ALU_VECTOR 0x00\n"
+".emtcode OP_ALU_SCALAR 0x01\n"
+".emtcode OP_ALU_BINSC 0x02\n"
+".emtcode OP_ALU_BIN 0x03\n"
+".emtcode OP_ALU_TRI 0x04\n"
+".emtcode OP_ALU_SWZ 0x05\n"
+".emtcode OP_TEX_SAMPLE 0x06\n"
+".emtcode OP_TEX_KIL 0x07\n"
+".emtcode OP_ALU_ARL 0x08\n"
+".emtcode OP_ABS 0x00\n"
+".emtcode OP_ABS_SAT 0x1B\n"
+".emtcode OP_FLR 0x09\n"
+".emtcode OP_FLR_SAT 0x26\n"
+".emtcode OP_FRC 0x0A\n"
+".emtcode OP_FRC_SAT 0x27\n"
+".emtcode OP_LIT 0x0C\n"
+".emtcode OP_LIT_SAT 0x2A\n"
+".emtcode OP_MOV 0x11\n"
+".emtcode OP_MOV_SAT 0x30\n"
+".emtcode OP_COS 0x1F\n"
+".emtcode OP_COS_SAT 0x20\n"
+".emtcode OP_EX2 0x07\n"
+".emtcode OP_EX2_SAT 0x25\n"
+".emtcode OP_LG2 0x0B\n"
+".emtcode OP_LG2_SAT 0x29\n"
+".emtcode OP_RCP 0x14\n"
+".emtcode OP_RCP_SAT 0x33\n"
+".emtcode OP_RSQ 0x15\n"
+".emtcode OP_RSQ_SAT 0x34\n"
+".emtcode OP_SIN 0x38\n"
+".emtcode OP_SIN_SAT 0x39\n"
+".emtcode OP_SCS 0x35\n"
+".emtcode OP_SCS_SAT 0x36\n"
+".emtcode OP_POW 0x13\n"
+".emtcode OP_POW_SAT 0x32\n"
+".emtcode OP_ADD 0x01\n"
+".emtcode OP_ADD_SAT 0x1C\n"
+".emtcode OP_DP3 0x03\n"
+".emtcode OP_DP3_SAT 0x21\n"
+".emtcode OP_DP4 0x04\n"
+".emtcode OP_DP4_SAT 0x22\n"
+".emtcode OP_DPH 0x05\n"
+".emtcode OP_DPH_SAT 0x23\n"
+".emtcode OP_DST 0x06\n"
+".emtcode OP_DST_SAT 0x24\n"
+".emtcode OP_MAX 0x0F\n"
+".emtcode OP_MAX_SAT 0x2E\n"
+".emtcode OP_MIN 0x10\n"
+".emtcode OP_MIN_SAT 0x2F\n"
+".emtcode OP_MUL 0x12\n"
+".emtcode OP_MUL_SAT 0x31\n"
+".emtcode OP_SGE 0x16\n"
+".emtcode OP_SGE_SAT 0x37\n"
+".emtcode OP_SLT 0x17\n"
+".emtcode OP_SLT_SAT 0x3A\n"
+".emtcode OP_SUB 0x18\n"
+".emtcode OP_SUB_SAT 0x3B\n"
+".emtcode OP_XPD 0x1A\n"
+".emtcode OP_XPD_SAT 0x43\n"
+".emtcode OP_CMP 0x1D\n"
+".emtcode OP_CMP_SAT 0x1E\n"
+".emtcode OP_LRP 0x2B\n"
+".emtcode OP_LRP_SAT 0x2C\n"
+".emtcode OP_MAD 0x0E\n"
+".emtcode OP_MAD_SAT 0x2D\n"
+".emtcode OP_SWZ 0x19\n"
+".emtcode OP_SWZ_SAT 0x3C\n"
+".emtcode OP_TEX 0x3D\n"
+".emtcode OP_TEX_SAT 0x3E\n"
+".emtcode OP_TXB 0x3F\n"
+".emtcode OP_TXB_SAT 0x40\n"
+".emtcode OP_TXP 0x41\n"
+".emtcode OP_TXP_SAT 0x42\n"
+".emtcode OP_KIL 0x28\n"
+".emtcode OP_ARL 0x02\n"
+".emtcode OP_EXP 0x08\n"
+".emtcode OP_LOG 0x0D\n"
+".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n"
+".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n"
+".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n"
+".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n"
+".emtcode VERTEX_ATTRIB_POSITION 0x01\n"
+".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n"
+".emtcode VERTEX_ATTRIB_NORMAL 0x03\n"
+".emtcode VERTEX_ATTRIB_COLOR 0x04\n"
+".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n"
+".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n"
+".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n"
+".emtcode VERTEX_ATTRIB_GENERIC 0x08\n"
+".emtcode FRAGMENT_RESULT_COLOR 0x01\n"
+".emtcode FRAGMENT_RESULT_DEPTH 0x02\n"
+".emtcode VERTEX_RESULT_POSITION 0x01\n"
+".emtcode VERTEX_RESULT_COLOR 0x02\n"
+".emtcode VERTEX_RESULT_FOGCOORD 0x03\n"
+".emtcode VERTEX_RESULT_POINTSIZE 0x04\n"
+".emtcode VERTEX_RESULT_TEXCOORD 0x05\n"
+".emtcode TEXTARGET_1D 0x01\n"
+".emtcode TEXTARGET_2D 0x02\n"
+".emtcode TEXTARGET_3D 0x03\n"
+".emtcode TEXTARGET_RECT 0x04\n"
+".emtcode TEXTARGET_CUBE 0x05\n"
+".emtcode TEXTARGET_SHADOW1D 0x06\n"
+".emtcode TEXTARGET_SHADOW2D 0x07\n"
+".emtcode TEXTARGET_SHADOWRECT 0x08\n"
+".emtcode FACE_FRONT 0x00\n"
+".emtcode FACE_BACK 0x01\n"
+".emtcode COLOR_PRIMARY 0x00\n"
+".emtcode COLOR_SECONDARY 0x01\n"
+".emtcode COMPONENT_X 0x00\n"
+".emtcode COMPONENT_Y 0x01\n"
+".emtcode COMPONENT_Z 0x02\n"
+".emtcode COMPONENT_W 0x03\n"
+".emtcode COMPONENT_0 0x04\n"
+".emtcode COMPONENT_1 0x05\n"
+".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n"
+".emtcode ARRAY_INDEX_RELATIVE 0x01\n"
+".emtcode MATRIX_MODELVIEW 0x01\n"
+".emtcode MATRIX_PROJECTION 0x02\n"
+".emtcode MATRIX_MVP 0x03\n"
+".emtcode MATRIX_TEXTURE 0x04\n"
+".emtcode MATRIX_PALETTE 0x05\n"
+".emtcode MATRIX_PROGRAM 0x06\n"
+".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n"
+".emtcode MATRIX_MODIFIER_INVERSE 0x01\n"
+".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n"
+".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n"
+".emtcode CONSTANT_SCALAR 0x01\n"
+".emtcode CONSTANT_VECTOR 0x02\n"
+".emtcode PROGRAM_PARAM_ENV 0x01\n"
+".emtcode PROGRAM_PARAM_LOCAL 0x02\n"
+".emtcode REGISTER_ATTRIB 0x01\n"
+".emtcode REGISTER_PARAM 0x02\n"
+".emtcode REGISTER_RESULT 0x03\n"
+".emtcode REGISTER_ESTABLISHED_NAME 0x04\n"
+".emtcode PARAM_NULL 0x00\n"
+".emtcode PARAM_ARRAY_ELEMENT 0x01\n"
+".emtcode PARAM_STATE_ELEMENT 0x02\n"
+".emtcode PARAM_PROGRAM_ELEMENT 0x03\n"
+".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n"
+".emtcode PARAM_CONSTANT 0x05\n"
+".emtcode STATE_MATERIAL 0x01\n"
+".emtcode STATE_LIGHT 0x02\n"
+".emtcode STATE_LIGHT_MODEL 0x03\n"
+".emtcode STATE_LIGHT_PROD 0x04\n"
+".emtcode STATE_FOG 0x05\n"
+".emtcode STATE_MATRIX_ROWS 0x06\n"
+".emtcode STATE_TEX_ENV 0x07\n"
+".emtcode STATE_DEPTH 0x08\n"
+".emtcode STATE_TEX_GEN 0x09\n"
+".emtcode STATE_CLIP_PLANE 0x0A\n"
+".emtcode STATE_POINT 0x0B\n"
+".emtcode MATERIAL_AMBIENT 0x01\n"
+".emtcode MATERIAL_DIFFUSE 0x02\n"
+".emtcode MATERIAL_SPECULAR 0x03\n"
+".emtcode MATERIAL_EMISSION 0x04\n"
+".emtcode MATERIAL_SHININESS 0x05\n"
+".emtcode LIGHT_AMBIENT 0x01\n"
+".emtcode LIGHT_DIFFUSE 0x02\n"
+".emtcode LIGHT_SPECULAR 0x03\n"
+".emtcode LIGHT_POSITION 0x04\n"
+".emtcode LIGHT_ATTENUATION 0x05\n"
+".emtcode LIGHT_HALF 0x06\n"
+".emtcode LIGHT_SPOT_DIRECTION 0x07\n"
+".emtcode LIGHT_MODEL_AMBIENT 0x01\n"
+".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n"
+".emtcode LIGHT_PROD_AMBIENT 0x01\n"
+".emtcode LIGHT_PROD_DIFFUSE 0x02\n"
+".emtcode LIGHT_PROD_SPECULAR 0x03\n"
+".emtcode TEX_ENV_COLOR 0x01\n"
+".emtcode TEX_GEN_EYE 0x01\n"
+".emtcode TEX_GEN_OBJECT 0x02\n"
+".emtcode FOG_COLOR 0x01\n"
+".emtcode FOG_PARAMS 0x02\n"
+".emtcode DEPTH_RANGE 0x01\n"
+".emtcode POINT_SIZE 0x01\n"
+".emtcode POINT_ATTENUATION 0x02\n"
+".emtcode ATTRIB 0x01\n"
+".emtcode PARAM 0x02\n"
+".emtcode TEMP 0x03\n"
+".emtcode OUTPUT 0x04\n"
+".emtcode ALIAS 0x05\n"
+".emtcode ADDRESS 0x06\n"
+".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n"
+".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n"
+".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n"
+".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n"
+".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n"
+".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n"
+".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n"
+".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n"
+".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n"
+".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n"
+".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n"
+".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n"
+".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n"
+".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n"
+".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n"
+".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n"
+".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n"
+".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n"
+".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n"
+".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n"
+".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n"
+".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n"
+".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n"
+".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n"
+".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n"
+".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n"
+".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n"
+".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n"
+".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n"
+".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n"
+".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n"
+".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n"
+".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n"
+".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n"
+".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n"
+".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n"
+".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n"
+".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n"
+".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n"
+".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n"
+".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n"
+".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n"
+".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n"
+".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n"
+".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n"
+".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n"
+".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n"
+".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n"
+".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n"
+".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n"
+".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n"
+".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n"
+".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n"
+".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n"
+".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n"
+".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n"
+".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n"
+".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n"
+".regbyte vertex_blend 0x00\n"
+".regbyte matrix_palette 0x00\n"
+".regbyte point_parameters 0x00\n"
+".regbyte secondary_color 0x00\n"
+".regbyte fog_coord 0x00\n"
+".regbyte texture_rectangle 0x00\n"
+".regbyte fragment_program_shadow 0x00\n"
+".regbyte ARB_precision_hint_fastest 0x00\n"
+".regbyte ARB_precision_hint_nicest 0x00\n"
+".regbyte ARB_fog_exp 0x00\n"
+".regbyte ARB_fog_exp2 0x00\n"
+".regbyte ARB_fog_linear 0x00\n"
+".regbyte ARB_position_invariant 0x00\n"
+".regbyte ARB_fragment_program_shadow 0x00\n"
+".regbyte program_target 0x00\n"
+"program\n"
+" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n"
+"programs\n"
+" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n"
+" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n"
+"frag_program_1_0\n"
+" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n"
+" optional_space .and fp_optionSequence .and fp_statementSequence .and\n"
+" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
+" '\\0' .error CODE_AFTER_END;\n"
+"vert_program_1_0\n"
+" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n"
+" optional_space .and vp_optionSequence .and vp_statementSequence .and\n"
+" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
+" '\\0' .error CODE_AFTER_END;\n"
+"fp_optionSequence\n"
+" .loop fp_option;\n"
+"vp_optionSequence\n"
+" .loop vp_option;\n"
+"fp_option\n"
+" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
+" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
+"vp_option\n"
+" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
+" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
+"fp_optionString\n"
+" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n"
+" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n"
+" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n"
+" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n"
+" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n"
+" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n"
+" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n"
+" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n"
+" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;\n"
+"vp_optionString\n"
+" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n"
+"fp_ARB_fog_exp\n"
+" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n"
+"fp_ARB_fog_exp2\n"
+" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n"
+"fp_ARB_fog_linear\n"
+" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n"
+"fp_statementSequence\n"
+" .loop fp_statement;\n"
+"vp_statementSequence\n"
+" .loop vp_statement;\n"
+"fp_statement\n"
+" fp_statement_1 .or fp_statement_2;\n"
+"vp_statement\n"
+" vp_statement_1 .or vp_statement_2;\n"
+"fp_statement_1\n"
+" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
+"fp_statement_2\n"
+" fp_namingStatement .emit DECLARATION .and semicolon;\n"
+"vp_statement_1\n"
+" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
+"vp_statement_2\n"
+" vp_namingStatement .emit DECLARATION .and semicolon;\n"
+"fp_instruction\n"
+" ALUInstruction .emit OP_ALU_INST .or\n"
+" TexInstruction .emit OP_TEX_INST;\n"
+"vp_instruction\n"
+" ARL_instruction .emit OP_ALU_ARL .or\n"
+" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
+" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
+" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
+" vp_BINop_instruction .emit OP_ALU_BIN .or\n"
+" vp_TRIop_instruction .emit OP_ALU_TRI .or\n"
+" vp_SWZ_instruction .emit OP_ALU_SWZ;\n"
+"ALUInstruction\n"
+" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
+" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
+" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
+" fp_BINop_instruction .emit OP_ALU_BIN .or\n"
+" fp_TRIop_instruction .emit OP_ALU_TRI .or\n"
+" fp_SWZ_instruction .emit OP_ALU_SWZ;\n"
+"TexInstruction\n"
+" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n"
+" KIL_instruction .emit OP_TEX_KIL;\n"
+"ARL_instruction\n"
+" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n"
+"fp_VECTORop_instruction\n"
+" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n"
+"vp_VECTORop_instruction\n"
+" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n"
+"fp_VECTORop\n"
+" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n"
+" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n"
+" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n"
+" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n"
+" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n"
+"vp_VECTORop\n"
+" \"ABS\" .emit OP_ABS .or\n"
+" \"FLR\" .emit OP_FLR .or\n"
+" \"FRC\" .emit OP_FRC .or\n"
+" \"LIT\" .emit OP_LIT .or\n"
+" \"MOV\" .emit OP_MOV;\n"
+"fp_SCALARop_instruction\n"
+" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n"
+"vp_SCALARop_instruction\n"
+" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n"
+"fp_SCALARop\n"
+" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n"
+" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n"
+" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n"
+" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n"
+" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n"
+" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n"
+" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n"
+"vp_SCALARop\n"
+" \"EX2\" .emit OP_EX2 .or\n"
+" \"EXP\" .emit OP_EXP .or\n"
+" \"LG2\" .emit OP_LG2 .or\n"
+" \"LOG\" .emit OP_LOG .or\n"
+" \"RCP\" .emit OP_RCP .or\n"
+" \"RSQ\" .emit OP_RSQ;\n"
+"fp_BINSCop_instruction\n"
+" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n"
+" fp_scalarSrcReg;\n"
+"vp_BINSCop_instruction\n"
+" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n"
+" vp_scalarSrcReg;\n"
+"fp_BINSCop\n"
+" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n"
+"vp_BINSCop\n"
+" \"POW\" .emit OP_POW;\n"
+"fp_BINop_instruction\n"
+" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
+" vectorSrcReg;\n"
+"vp_BINop_instruction\n"
+" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
+" swizzleSrcReg;\n"
+"fp_BINop\n"
+" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n"
+" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n"
+" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n"
+" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n"
+" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n"
+" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n"
+" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n"
+" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n"
+" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n"
+" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n"
+" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n"
+" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n"
+"vp_BINop\n"
+" \"ADD\" .emit OP_ADD .or\n"
+" \"DP3\" .emit OP_DP3 .or\n"
+" \"DP4\" .emit OP_DP4 .or\n"
+" \"DPH\" .emit OP_DPH .or\n"
+" \"DST\" .emit OP_DST .or\n"
+" \"MAX\" .emit OP_MAX .or\n"
+" \"MIN\" .emit OP_MIN .or\n"
+" \"MUL\" .emit OP_MUL .or\n"
+" \"SGE\" .emit OP_SGE .or\n"
+" \"SLT\" .emit OP_SLT .or\n"
+" \"SUB\" .emit OP_SUB .or\n"
+" \"XPD\" .emit OP_XPD;\n"
+"fp_TRIop_instruction\n"
+" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
+" vectorSrcReg .and comma .and vectorSrcReg;\n"
+"vp_TRIop_instruction\n"
+" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
+" swizzleSrcReg .and comma .and swizzleSrcReg;\n"
+"fp_TRIop\n"
+" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n"
+" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n"
+" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n"
+"vp_TRIop\n"
+" \"MAD\" .emit OP_MAD;\n"
+"fp_SWZ_instruction\n"
+" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n"
+" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
+"vp_SWZ_instruction\n"
+" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n"
+" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
+"SWZop\n"
+" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n"
+"SAMPLE_instruction\n"
+" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
+" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n"
+"SAMPLEop\n"
+" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n"
+" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n"
+" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n"
+"KIL_instruction\n"
+" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n"
+"texImageUnit\n"
+" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n"
+"texTarget\n"
+" \"1D\" .emit TEXTARGET_1D .or\n"
+" \"2D\" .emit TEXTARGET_2D .or\n"
+" \"3D\" .emit TEXTARGET_3D .or\n"
+" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n"
+" \"CUBE\" .emit TEXTARGET_CUBE .or\n"
+" .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\n"
+"shadowTarget\n"
+" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n"
+" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n"
+" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT;\n"
+"optTexImageUnitNum\n"
+" optTexImageUnitNum_1 .or .true .emit 0x00;\n"
+"optTexImageUnitNum_1\n"
+" lbracket_ne .and texImageUnitNum .and rbracket;\n"
+"texImageUnitNum\n"
+" integer;\n"
+"fp_scalarSrcReg\n"
+" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n"
+"vp_scalarSrcReg\n"
+" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n"
+"swizzleSrcReg\n"
+" optionalSign .and vp_srcReg .and swizzleSuffix;\n"
+"vectorSrcReg\n"
+" optionalSign .and fp_srcReg .and optionalSuffix;\n"
+"fp_maskedDstReg\n"
+" fp_dstReg .and fp_optionalMask;\n"
+"vp_maskedDstReg\n"
+" vp_dstReg .and vp_optionalMask;\n"
+"maskedAddrReg\n"
+" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n"
+"fp_extendedSwizzle\n"
+" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n"
+"vp_extendedSwizzle\n"
+" extSwizComp .and comma .and\n"
+" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"xyzwExtendedSwizzle\n"
+" xyzwExtSwizComp .and comma .and\n"
+" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"rgbaExtendedSwizzle\n"
+" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n"
+" rgbaExtendedSwizzle_4;\n"
+"rgbaExtendedSwizzle_1\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n"
+"rgbaExtendedSwizzle_2\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
+" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"rgbaExtendedSwizzle_3\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"rgbaExtendedSwizzle_4\n"
+" rgbaExtSwizComp_alpha .and comma .and \n"
+"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"xyzwExtSwizComp\n"
+" optionalSign .and xyzwExtSwizSel;\n"
+"rgbaExtSwizComp\n"
+" optionalSign .and rgbaExtSwizSel;\n"
+"rgbaExtSwizComp_digit\n"
+" optionalSign .and rgbaExtSwizSel_digit;\n"
+"rgbaExtSwizComp_alpha\n"
+" optionalSign .and rgbaExtSwizSel_alpha;\n"
+"extSwizComp\n"
+" optionalSign .and extSwizSel;\n"
+"xyzwExtSwizSel\n"
+" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n"
+"rgbaExtSwizSel\n"
+" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n"
+"rgbaExtSwizSel_digit\n"
+" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n"
+"rgbaExtSwizSel_alpha\n"
+" rgbaComponent_single;\n"
+"extSwizSel\n"
+" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n"
+"fp_srcReg\n"
+" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
+"vp_srcReg\n"
+" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
+"fp_srcReg_1\n"
+" fragmentAttribReg .emit REGISTER_ATTRIB .or\n"
+" fp_progParamReg .emit REGISTER_PARAM .or\n"
+" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"vp_srcReg_1\n"
+" vertexAttribReg .emit REGISTER_ATTRIB .or\n"
+" vp_progParamReg .emit REGISTER_PARAM .or\n"
+" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"fp_dstReg\n"
+" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
+"vp_dstReg\n"
+" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
+"fp_dstReg_1\n"
+" fragmentResultReg .emit REGISTER_RESULT .or\n"
+" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"vp_dstReg_1\n"
+" vertexResultReg .emit REGISTER_RESULT .or\n"
+" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"fragmentAttribReg\n"
+" fragAttribBinding;\n"
+"vertexAttribReg\n"
+" vtxAttribBinding;\n"
+"fp_temporaryReg\n"
+" fp_establishedName_no_error_on_identifier;\n"
+"vp_temporaryReg\n"
+" vp_establishedName_no_error_on_identifier;\n"
+"fp_progParamReg\n"
+" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n"
+"vp_progParamReg\n"
+" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n"
+"fp_progParamReg_1\n"
+" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n"
+" rbracket;\n"
+"vp_progParamReg_1\n"
+" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n"
+" rbracket;\n"
+"fp_progParamSingle\n"
+" .false;\n"
+"vp_progParamSingle\n"
+" .false;\n"
+"fp_progParamArray\n"
+" fp_establishedName_no_error_on_identifier;\n"
+"vp_progParamArray\n"
+" vp_establishedName_no_error_on_identifier;\n"
+"progParamArrayMem\n"
+" progParamArrayAbs .or progParamArrayRel;\n"
+"progParamArrayAbs\n"
+" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n"
+"progParamArrayRel\n"
+" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n"
+" addrComponent .and addrRegRelOffset;\n"
+"addrRegRelOffset\n"
+" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n"
+"addrRegRelOffset_1\n"
+" plus_ne .and addrRegPosOffset;\n"
+"addrRegRelOffset_2\n"
+" minus_ne .and addrRegNegOffset;\n"
+"addrRegPosOffset\n"
+" integer_0_63;\n"
+"addrRegNegOffset\n"
+" integer_0_64;\n"
+"fragmentResultReg\n"
+" fp_resultBinding;\n"
+"vertexResultReg\n"
+" vp_resultBinding;\n"
+"addrReg\n"
+" vp_establishedName_no_error_on_identifier;\n"
+"addrComponent\n"
+" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n"
+" .emit COMPONENT_X .emit COMPONENT_X;\n"
+"addrWriteMask\n"
+" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n"
+"fp_scalarSuffix\n"
+" dot .and fp_component_single .error INVALID_COMPONENT;\n"
+"vp_scalarSuffix\n"
+" dot .and vp_component_single .error INVALID_COMPONENT;\n"
+"swizzleSuffix\n"
+" swizzleSuffix_1 .or\n"
+" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
+"swizzleSuffix_1\n"
+" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n"
+"swizzleSuffix_2\n"
+" swizzleSuffix_3 .or swizzleSuffix_4;\n"
+"swizzleSuffix_3\n"
+" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n"
+" vp_component_multi .error INVALID_COMPONENT;\n"
+"swizzleSuffix_4\n"
+" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
+" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
+" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
+"optionalSuffix\n"
+" optionalSuffix_1 .or\n"
+" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
+"optionalSuffix_1\n"
+" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n"
+"optionalSuffix_2\n"
+" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n"
+"optionalSuffix_3\n"
+" xyzwComponent_multi .and xyzwComponent_multi .and\n"
+" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n"
+"optionalSuffix_4\n"
+" rgbaComponent_multi .and rgbaComponent_multi .and\n"
+" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n"
+"optionalSuffix_5\n"
+" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
+" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
+" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n"
+" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
+" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
+" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
+" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
+"fp_component_single\n"
+" xyzwComponent_single .or rgbaComponent_single;\n"
+"vp_component_multi\n"
+" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
+" 'w' .emit COMPONENT_W;\n"
+"vp_component_single\n"
+" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W;\n"
+"xyzwComponent_multi\n"
+" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
+" 'w' .emit COMPONENT_W;\n"
+"xyzwComponent_single\n"
+" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W;\n"
+"rgbaComponent_multi\n"
+" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n"
+" 'a' .emit COMPONENT_W;\n"
+"rgbaComponent_single\n"
+" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n"
+" \"a\" .emit COMPONENT_W;\n"
+"fp_optionalMask\n"
+" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n"
+"vp_optionalMask\n"
+" xyzwMask .or .true .emit 0x0F;\n"
+"xyzwMask\n"
+" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n"
+"xyzwMask_1\n"
+" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n"
+" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n"
+" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n"
+" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n"
+"rgbaMask\n"
+" dot_ne .and rgbaMask_1;\n"
+"rgbaMask_1\n"
+" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n"
+" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n"
+" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n"
+" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n"
+"fp_namingStatement\n"
+" fp_ATTRIB_statement .emit ATTRIB .or\n"
+" fp_PARAM_statement .emit PARAM .or\n"
+" fp_TEMP_statement .emit TEMP .or\n"
+" fp_OUTPUT_statement .emit OUTPUT .or\n"
+" fp_ALIAS_statement .emit ALIAS;\n"
+"vp_namingStatement\n"
+" vp_ATTRIB_statement .emit ATTRIB .or\n"
+" vp_PARAM_statement .emit PARAM .or\n"
+" vp_TEMP_statement .emit TEMP .or\n"
+" ADDRESS_statement .emit ADDRESS .or\n"
+" vp_OUTPUT_statement .emit OUTPUT .or\n"
+" vp_ALIAS_statement .emit ALIAS;\n"
+"fp_ATTRIB_statement\n"
+" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n"
+" fragAttribBinding .error FRAGMENT_EXPECTED;\n"
+"vp_ATTRIB_statement\n"
+" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n"
+" vtxAttribBinding .error VERTEX_EXPECTED;\n"
+"fragAttribBinding\n"
+" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n"
+"vtxAttribBinding\n"
+" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n"
+"fragAttribItem\n"
+" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n"
+" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n"
+" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n"
+" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n"
+"fragAttribItem_1\n"
+" \"color\" .and optColorType;\n"
+"fragAttribItem_2\n"
+" \"texcoord\" .and optTexCoordNum;\n"
+"vtxAttribItem\n"
+" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n"
+" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n"
+" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n"
+" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n"
+" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n"
+" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n"
+" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n"
+" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n"
+"vtxAttribItem_1\n"
+" \"weight\" .and vtxOptWeightNum;\n"
+"vtxAttribItem_2\n"
+" \"color\" .and optColorType;\n"
+"vtxAttribItem_3\n"
+" \"texcoord\" .and optTexCoordNum;\n"
+"vtxAttribItem_4\n"
+" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n"
+"vtxAttribItem_5\n"
+" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n"
+"vtxAttribNum\n"
+" integer;\n"
+"vtxOptWeightNum\n"
+" vtxOptWeightNum_1 .or .true .emit 0x00;\n"
+"vtxOptWeightNum_1\n"
+" lbracket_ne .and vtxWeightNum .and rbracket;\n"
+"vtxWeightNum\n"
+" integer;\n"
+"fp_PARAM_statement\n"
+" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n"
+"vp_PARAM_statement\n"
+" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n"
+"fp_PARAM_singleStmt\n"
+" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n"
+" .true .emit PARAM_NULL;\n"
+"vp_PARAM_singleStmt\n"
+" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n"
+" .true .emit PARAM_NULL;\n"
+"fp_PARAM_multipleStmt\n"
+" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
+" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
+"vp_PARAM_multipleStmt\n"
+" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
+" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
+"optArraySize\n"
+" optional_integer;\n"
+"fp_paramSingleInit\n"
+" equal .and fp_paramSingleItemDecl;\n"
+"vp_paramSingleInit\n"
+" equal .and vp_paramSingleItemDecl;\n"
+"fp_paramMultipleInit\n"
+" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n"
+"vp_paramMultipleInit\n"
+" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n"
+"fp_paramMultInitList\n"
+" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n"
+"vp_paramMultInitList\n"
+" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n"
+"fp_paramMultInitList_1\n"
+" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n"
+"vp_paramMultInitList_1\n"
+" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n"
+"fp_paramSingleItemDecl\n"
+" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"vp_paramSingleItemDecl\n"
+" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"fp_paramSingleItemUse\n"
+" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstUse .emit PARAM_CONSTANT;\n"
+"vp_paramSingleItemUse\n"
+" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstUse .emit PARAM_CONSTANT;\n"
+"fp_paramMultipleItem\n"
+" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"vp_paramMultipleItem\n"
+" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"fp_stateMultipleItem\n"
+" stateMultipleItem_1 .or fp_stateSingleItem;\n"
+"vp_stateMultipleItem\n"
+" stateMultipleItem_1 .or vp_stateSingleItem;\n"
+"stateMultipleItem_1\n"
+" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n"
+"fp_stateSingleItem\n"
+" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
+"vp_stateSingleItem\n"
+" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
+"fp_stateSingleItem_1\n"
+" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
+" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n"
+"vp_stateSingleItem_1\n"
+" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
+" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n"
+" stateSingleItem_11;\n"
+"stateSingleItem_1\n"
+" stateMaterialItem .emit STATE_MATERIAL;\n"
+"stateSingleItem_2\n"
+" stateLightItem .emit STATE_LIGHT;\n"
+"stateSingleItem_3\n"
+" stateLightModelItem .emit STATE_LIGHT_MODEL;\n"
+"stateSingleItem_4\n"
+" stateLightProdItem .emit STATE_LIGHT_PROD;\n"
+"stateSingleItem_5\n"
+" stateTexEnvItem .emit STATE_TEX_ENV;\n"
+"stateSingleItem_6\n"
+" stateTexGenItem .emit STATE_TEX_GEN;\n"
+"stateSingleItem_7\n"
+" stateFogItem .emit STATE_FOG;\n"
+"stateSingleItem_8\n"
+" stateDepthItem .emit STATE_DEPTH;\n"
+"stateSingleItem_9\n"
+" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n"
+"stateSingleItem_10\n"
+" statePointItem .emit STATE_POINT;\n"
+"stateSingleItem_11\n"
+" stateMatrixRow .emit STATE_MATRIX_ROWS;\n"
+"stateMaterialItem\n"
+" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n"
+"stateMatProperty\n"
+" \"ambient\" .emit MATERIAL_AMBIENT .or\n"
+" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n"
+" \"specular\" .emit MATERIAL_SPECULAR .or\n"
+" \"emission\" .emit MATERIAL_EMISSION .or\n"
+" \"shininess\" .emit MATERIAL_SHININESS;\n"
+"stateLightItem\n"
+" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n"
+" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n"
+"stateLightProperty\n"
+" \"ambient\" .emit LIGHT_AMBIENT .or\n"
+" \"diffuse\" .emit LIGHT_DIFFUSE .or\n"
+" \"specular\" .emit LIGHT_SPECULAR .or\n"
+" \"position\" .emit LIGHT_POSITION .or\n"
+" \"attenuation\" .emit LIGHT_ATTENUATION .or\n"
+" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n"
+" \"half\" .emit LIGHT_HALF;\n"
+"stateLightProperty_1\n"
+" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n"
+"stateSpotProperty\n"
+" \"direction\";\n"
+"stateLightModelItem\n"
+" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n"
+"stateLModProperty\n"
+" stateLModProperty_1 .or stateLModProperty_2;\n"
+"stateLModProperty_1\n"
+" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n"
+"stateLModProperty_2\n"
+" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n"
+"stateLModProperty_3\n"
+" optFaceType .and dot .and \"scenecolor\";\n"
+"stateLightProdItem\n"
+" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n"
+" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n"
+"stateLProdProperty\n"
+" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n"
+" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n"
+" \"specular\" .emit LIGHT_PROD_SPECULAR;\n"
+"stateLightNumber\n"
+" integer;\n"
+"stateTexEnvItem\n"
+" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n"
+" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n"
+"stateTexEnvProperty\n"
+" \"color\" .emit TEX_ENV_COLOR;\n"
+"optLegacyTexUnitNum\n"
+" lbracket_ne .and legacyTexUnitNum .and rbracket;\n"
+"legacyTexUnitNum\n"
+" integer;\n"
+"stateTexGenItem\n"
+" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n"
+" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n"
+"stateTexGenType\n"
+" \"eye\" .emit TEX_GEN_EYE .or\n"
+" \"object\" .emit TEX_GEN_OBJECT;\n"
+"stateTexGenCoord\n"
+" \"s\" .emit COMPONENT_X .or\n"
+" \"t\" .emit COMPONENT_Y .or\n"
+" \"r\" .emit COMPONENT_Z .or\n"
+" \"q\" .emit COMPONENT_W;\n"
+"stateFogItem\n"
+" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n"
+"stateFogProperty\n"
+" \"color\" .emit FOG_COLOR .or\n"
+" \"params\" .emit FOG_PARAMS;\n"
+"stateDepthItem\n"
+" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n"
+"stateDepthProperty\n"
+" \"range\" .emit DEPTH_RANGE;\n"
+"stateClipPlaneItem\n"
+" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n"
+" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n"
+"stateClipPlaneNum\n"
+" integer;\n"
+"statePointItem\n"
+" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n"
+"statePointProperty\n"
+" \"size\" .emit POINT_SIZE .or\n"
+" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n"
+"stateMatrixRow\n"
+" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n"
+" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n"
+"stateMatrixRows\n"
+" stateMatrixItem .and optMatrixRows;\n"
+"optMatrixRows\n"
+" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n"
+"optMatrixRows_1\n"
+" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n"
+" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n"
+"stateMatrixItem\n"
+" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n"
+"stateOptMatModifier\n"
+" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n"
+"stateOptMatModifier_1\n"
+" dot_ne .and stateMatModifier;\n"
+"stateMatModifier\n"
+" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n"
+" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n"
+" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n"
+"stateMatrixRowNum\n"
+" integer_0_3;\n"
+"stateMatrixName\n"
+" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n"
+" \"projection\" .emit MATRIX_PROJECTION .or\n"
+" \"mvp\" .emit MATRIX_MVP .or\n"
+" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n"
+" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n"
+" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n"
+"stateMatrixName_1_1\n"
+" \"modelview\" .and stateOptModMatNum;\n"
+"stateMatrixName_1_2\n"
+" \"texture\" .and optTexCoordNum;\n"
+"stateMatrixName_1_3\n"
+" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n"
+"stateMatrixName_1_4\n"
+" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n"
+"stateOptModMatNum\n"
+" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n"
+" .true .emit 0x00;\n"
+"stateOptModMatNum_1\n"
+" lbracket_ne .and stateModMatNum .and rbracket;\n"
+"stateModMatNum\n"
+" integer;\n"
+"optTexCoordNum\n"
+" optTexCoordNum_1 .or .true .emit 0x00;\n"
+"optTexCoordNum_1\n"
+" lbracket_ne .and texCoordNum .and rbracket;\n"
+"texCoordNum\n"
+" integer;\n"
+"statePaletteMatNum\n"
+" integer;\n"
+"stateProgramMatNum\n"
+" integer;\n"
+"programSingleItem\n"
+" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
+"programSingleItem_1\n"
+" progEnvParam .or progLocalParam;\n"
+"programMultipleItem\n"
+" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
+"programMultipleItem_1\n"
+" progEnvParams .or progLocalParams;\n"
+"progEnvParams\n"
+" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n"
+"progEnvParamNums\n"
+" progEnvParamNums_1 .or progEnvParamNums_2;\n"
+"progEnvParamNums_1\n"
+" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n"
+"progEnvParamNums_2\n"
+" progEnvParamNum .and .true .emit 0x00;\n"
+"progEnvParam\n"
+" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n"
+"progLocalParams\n"
+" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n"
+"progLocalParamNums\n"
+" progLocalParamNums_1 .or progLocalParamNums_2;\n"
+"progLocalParamNums_1\n"
+" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n"
+"progLocalParamNums_2\n"
+" progLocalParamNum .and .true .emit 0x00;\n"
+"progLocalParam\n"
+" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n"
+"progEnvParamNum\n"
+" integer;\n"
+"progLocalParamNum\n"
+" integer;\n"
+"paramConstDecl\n"
+" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
+"paramConstUse\n"
+" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
+"paramConstScalarDecl\n"
+" signedFloatConstant;\n"
+"paramConstScalarUse\n"
+" floatConstant;\n"
+"paramConstVector\n"
+" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n"
+" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n"
+"paramConstVector_1\n"
+" lbrace_ne .and signedFloatConstant .and rbrace;\n"
+"paramConstVector_2\n"
+" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
+"paramConstVector_3\n"
+" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
+" signedFloatConstant .and rbrace;\n"
+"paramConstVector_4\n"
+" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
+" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
+"signedFloatConstant\n"
+" optionalSign .and floatConstant;\n"
+"floatConstant\n"
+" float;\n"
+"optionalSign\n"
+" optional_sign_ne;\n"
+"fp_TEMP_statement\n"
+" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n"
+"vp_TEMP_statement\n"
+" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
+"ADDRESS_statement\n"
+" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
+"fp_varNameList\n"
+" fp_varNameList_1 .or fp_establishName;\n"
+"vp_varNameList\n"
+" vp_varNameList_1 .or vp_establishName;\n"
+"fp_varNameList_1\n"
+" fp_establishName .and comma_ne .and fp_varNameList;\n"
+"vp_varNameList_1\n"
+" vp_establishName .and comma_ne .and vp_varNameList;\n"
+"fp_OUTPUT_statement\n"
+" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n"
+" fp_resultBinding .error RESULT_EXPECTED;\n"
+"vp_OUTPUT_statement\n"
+" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n"
+" vp_resultBinding .error RESULT_EXPECTED;\n"
+"fp_resultBinding\n"
+" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
+"vp_resultBinding\n"
+" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
+"fp_resultBinding_1\n"
+" \"color\" .emit FRAGMENT_RESULT_COLOR .or\n"
+" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n"
+"vp_resultBinding_1\n"
+" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n"
+" resultColBinding .emit VERTEX_RESULT_COLOR .or\n"
+" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n"
+" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n"
+" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n"
+"vp_resultBinding_2\n"
+" \"texcoord\" .and optTexCoordNum;\n"
+"resultColBinding\n"
+" \"color\" .and optFaceType .and optColorType;\n"
+"optFaceType\n"
+" FaceType .or .true .emit FACE_FRONT;\n"
+"FaceType\n"
+" dot_ne .and FaceProperty;\n"
+"FaceProperty\n"
+" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n"
+"optColorType\n"
+" ColorType .or .true .emit COLOR_PRIMARY;\n"
+"ColorType\n"
+" dot_ne .and ColorProperty;\n"
+"ColorProperty\n"
+" \"primary\" .emit COLOR_PRIMARY .or\n"
+" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n"
+"fp_ALIAS_statement\n"
+" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n"
+"vp_ALIAS_statement\n"
+" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n"
+"fp_ALIAS_statement_1\n"
+" space .and fp_establishName;\n"
+"vp_ALIAS_statement_1\n"
+" space .and vp_establishName;\n"
+"fp_establishName\n"
+" fp_identifier;\n"
+"vp_establishName\n"
+" vp_identifier;\n"
+"fp_establishedName\n"
+" fp_identifier;\n"
+"vp_establishedName\n"
+" vp_identifier;\n"
+"fp_establishedName_no_error_on_identifier\n"
+" fp_identifier_ne;\n"
+"vp_establishedName_no_error_on_identifier\n"
+" vp_identifier_ne;\n"
+"fp_identifier\n"
+" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"vp_identifier\n"
+" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"fp_identifier_ne\n"
+" fp_not_reserved_identifier .and identifier_ne;\n"
+"vp_identifier_ne\n"
+" vp_not_reserved_identifier .and identifier_ne;\n"
+"fp_not_reserved_identifier\n"
+" fp_not_reserved_identifier_1 .or .true;\n"
+"fp_not_reserved_identifier_1\n"
+" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
+"vp_not_reserved_identifier\n"
+" vp_not_reserved_identifier_1 .or .true;\n"
+"vp_not_reserved_identifier_1\n"
+" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
+"fp_reserved_identifier\n"
+" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n"
+" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n"
+" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n"
+" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n"
+" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n"
+" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n"
+" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n"
+" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n"
+" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n"
+" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n"
+"vp_reserved_identifier\n"
+" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n"
+" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n"
+" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n"
+" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n"
+" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n"
+"integer\n"
+" integer_ne .error INTEGER_EXPECTED;\n"
+"zero\n"
+" '0';\n"
+"leading_zeroes\n"
+" .loop zero;\n"
+"no_digit\n"
+" no_digit_1 .or .true;\n"
+"no_digit_1\n"
+" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n"
+"all_zeroes\n"
+" all_zeroes_1 .or no_digit_1;\n"
+"all_zeroes_1\n"
+" '0' .and .loop zero .and no_digit;\n"
+"integer_0_3\n"
+" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
+"integer_0_3_1\n"
+" integer_0_3_2 .or all_zeroes .emit '0';\n"
+"integer_0_3_2 \n"
+" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n"
+"integer_0_63\n"
+" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
+"integer_0_63_1\n"
+" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n"
+" all_zeroes .emit '0';\n"
+"integer_0_63_2 \n"
+" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
+"integer_0_63_3 \n"
+" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
+"integer_0_63_4 \n"
+" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n"
+"integer_0_63_5 \n"
+" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
+"integer_0_64\n"
+" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
+"integer_0_64_1\n"
+" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n"
+" all_zeroes .emit '0';\n"
+"integer_0_64_2 \n"
+" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
+"integer_0_64_3 \n"
+" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
+"integer_0_64_4 \n"
+" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n"
+"integer_0_64_5 \n"
+" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
+"optional_space\n"
+" space .or .true;\n"
+"space_dst\n"
+" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n"
+"space_src\n"
+" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" white_char .or comment_block;\n"
+"white_char\n"
+" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
+"comment_block\n"
+" '#' .and .loop comment_char .and new_line;\n"
+"comment_char\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"new_line\n"
+" '\\n' .or crlf .or '\\0';\n"
+"crlf\n"
+" '\\r' .and '\\n';\n"
+"semicolon\n"
+" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
+"comma\n"
+" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n"
+"comma_ne\n"
+" optional_space .and ',' .and optional_space;\n"
+"lbracket\n"
+" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n"
+"lbracket_ne\n"
+" optional_space .and '[' .and optional_space;\n"
+"rbracket\n"
+" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n"
+"dot\n"
+" optional_space .and '.' .error MISSING_DOT .and optional_space;\n"
+"dot_ne\n"
+" optional_space .and '.' .and optional_space;\n"
+"equal\n"
+" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n"
+"lbrace\n"
+" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n"
+"lbrace_ne\n"
+" optional_space .and '{' .and optional_space;\n"
+"rbrace\n"
+" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n"
+"dotdot\n"
+" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n"
+"dotdot_ne\n"
+" optional_space .and '.' .and '.' .and optional_space;\n"
+"float\n"
+" float_1 .or float_2 .or float_legacy;\n"
+"float_1\n"
+" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n"
+"float_2\n"
+" integer_ne .and float_3;\n"
+"float_3\n"
+" float_4 .or float_5;\n"
+"float_4\n"
+" '.' .and optional_integer .and optional_exponent;\n"
+"float_5\n"
+" exponent .emit 0x00;\n"
+"float_legacy\n"
+" integer_ne .and .true .emit 0x00 .emit 0x00;\n"
+"integer_ne\n"
+" integer_ne_1 .and .true .emit 0x00 .emit $;\n"
+"integer_ne_1\n"
+" digit10 .emit * .and .loop digit10 .emit *;\n"
+"optional_integer\n"
+" integer_ne .or .true .emit 0x00;\n"
+"optional_exponent\n"
+" exponent .or .true .emit 0x00;\n"
+"exponent\n"
+" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n"
+"exponent_1\n"
+" 'e' .or 'E';\n"
+"optional_sign_ne\n"
+" minus_ne .or plus_ne .or .true;\n"
+"plus_ne\n"
+" optional_space .and '+' .and optional_space;\n"
+"minus_ne\n"
+" optional_space .and '-' .emit '-' .and optional_space;\n"
+"identifier_ne\n"
+" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n"
+"follow_idchar\n"
+" first_idchar .or digit10;\n"
+"first_idchar\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
+"digit10\n"
+" '0'-'9';\n"
+".string __string_filter;\n"
+"__string_filter\n"
+" .loop __identifier_char;\n"
+"__identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n"
+"e_signature\n"
+" e_signature_char .and .loop e_signature_char;\n"
+"e_signature_char\n"
+" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
+"e_statement\n"
+" .loop e_statement_not_term;\n"
+"e_statement_not_term\n"
+" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"e_identifier\n"
+" e_identifier_first .and .loop e_identifier_next;\n"
+"e_identifier_first\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
+"e_identifier_next\n"
+" e_identifier_first .or '0'-'9';\n"
+"e_token\n"
+" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n"
+" '-' .or ',' .or ';';\n"
+"e_token_number\n"
+" e_token_digit .and .loop e_token_digit;\n"
+"e_token_digit\n"
+" '0'-'9';\n"
+"e_charordigit\n"
+" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
+""
diff --git a/src/mesa/shader/grammar.c b/src/mesa/shader/grammar.c
index 96449784571..0ed347bad51 100644
--- a/src/mesa/shader/grammar.c
+++ b/src/mesa/shader/grammar.c
@@ -1,2760 +1,2799 @@
-#ifndef GRAMMAR_PORT_BUILD
-#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file
-#endif
-
-/*
- Last Modified: 2004-II-8
-*/
-
-/*
- INTRODUCTION
- ------------
-
- The task is to check the syntax of an input string. Input string is a stream of ASCII
- characters terminated with a null-character ('\0'). Checking it using C language is
- difficult and hard to implement without bugs. It is hard to maintain and make changes when
- the syntax changes.
-
- This is because of a high redundancy of the C code. Large blocks of code are duplicated with
- only small changes. Even use of macros does not solve the problem because macros cannot
- erase the complexity of the problem.
-
- The resolution is to create a new language that will be highly oriented to our task. Once
- we describe a particular syntax, we are done. We can then focus on the code that implements
- the language. The size and complexity of it is relatively small than the code that directly
- checks the syntax.
-
- First, we must implement our new language. Here, the language is implemented in C, but it
- could also be implemented in any other language. The code is listed below. We must take
- a good care that it is bug free. This is simple because the code is simple and clean.
-
- Next, we must describe the syntax of our new language in itself. Once created and checked
- manually that it is correct, we can use it to check another scripts.
-
- Note that our new language loading code does not have to check the syntax. It is because we
- assume that the script describing itself is correct, and other scripts can be syntactically
- checked by the former script. The loading code must only do semantic checking which leads us to
- simple resolving references.
-
- THE LANGUAGE
- ------------
-
- Here I will describe the syntax of the new language (further called "Synek"). It is mainly a
- sequence of declarations terminated by a semicolon. The declaration consists of a symbol,
- which is an identifier, and its definition. A definition is in turn a sequence of specifiers
- connected with ".and" or ".or" operator. These operators cannot be mixed together in a one
- definition. Specifier can be a symbol, string, character, character range or a special
- keyword ".true" or ".false".
-
- On the very beginning of the script there is a declaration of a root symbol and is in the form:
- .syntax <root_symbol>;
- The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if
- the root symbol evaluates to true. A symbol evaluates to true if the definition associated with
- the symbol evaluates to true. Definition evaluation depends on the operator used to connect
- specifiers in the definition. If ".and" operator is used, definition evaluates to true if and
- only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to
- true if any of the specifiers evaluates to true. If definition contains only one specifier,
- it is evaluated as if it was connected with ".true" keyword by ".and" operator.
-
- If specifier is a ".true" keyword, it always evaluates to true.
-
- If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false
- when it does not evaluate to true.
-
- Character range specifier is in the form:
- '<first_character>' - '<second_character>'
- If specifier is a character range, it evaluates to true if character in the stream is greater
- or equal to <first_character> and less or equal to <second_character>. In that situation
- the stream pointer is advanced to point to next character in the stream. All C-style escape
- sequences are supported although trigraph sequences are not. The comparisions are performed
- on 8-bit unsigned integers.
-
- Character specifier is in the form:
- '<single_character>'
- It evaluates to true if the following character range specifier evaluates to true:
- '<single_character>' - '<single_character>'
-
- String specifier is in the form:
- "<string>"
- Let N be the number of characters in <string>. Let <string>[i] designate i-th character in
- <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)
- the following character specifier evaluates to true:
- '<string>[i]'
- If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.
-
- Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
- .loop <symbol> (1)
- where <symbol> is defined as follows:
- <symbol> <definition>; (2)
- Construction (1) is replaced by the following code:
- <symbol$1>
- and declaration (2) is replaced by the following:
- <symbol$1> <symbol$2> .or .true;
- <symbol$2> <symbol> .and <symbol$1>;
- <symbol> <definition>;
-
- ESCAPE SEQUENCES
- ----------------
-
- Synek supports all escape sequences in character specifiers. The mapping table is listed below.
- All occurences of the characters in the first column are replaced with the corresponding
- character in the second column.
-
- Escape sequence Represents
- ------------------------------------------------------------------------------------------------
- \a Bell (alert)
- \b Backspace
- \f Formfeed
- \n New line
- \r Carriage return
- \t Horizontal tab
- \v Vertical tab
- \' Single quotation mark
- \" Double quotation mark
- \\ Backslash
- \? Literal question mark
- \ooo ASCII character in octal notation
- \xhhh ASCII character in hexadecimal notation
- ------------------------------------------------------------------------------------------------
-
- RAISING ERRORS
- --------------
-
- Any specifier can be followed by a special construction that is executed when the specifier
- evaluates to false. The construction is in the form:
- .error <ERROR_TEXT>
- <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is
- in the form:
- .errtext <ERROR_TEXT> "<error_desc>"
- When specifier evaluates to false and this construction is present, parsing is stopped
- immediately and <error_desc> is returned as a result of parsing. The error position is also
- returned and it is meant as an offset from the beggining of the stream to the character that
- was valid so far. Example:
-
- (**** syntax script ****)
-
- .syntax program;
- .errtext MISSING_SEMICOLON "missing ';'"
- program declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and
- .loop space .and '\0';
- declaration "declare" .and .loop space .and identifier;
- space ' ';
-
- (**** sample code ****)
-
- declare foo ,
-
- In the example above checking the sample code will result in error message "missing ';'" and
- error position 12. The sample code is not correct. Note the presence of '\0' specifier to
- assure that there is no code after semicolon - only spaces.
- <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,
- the identifier and dollar signs are replaced by a string retrieved by invoking symbol with
- the identifier name. The starting position is the error position. The lenght of the resulting
- string is the position after invoking the symbol.
-
- PRODUCTION
- ----------
-
- Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers
- that evaluate to true. That is, every specifier and optional error construction can be followed
- by a number of emit constructions that are in the form:
- .emit <parameter>
- <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by
- 0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration
- in the form:
- .emtcode <identifier> <hex_number>
-
- When given specifier evaluates to true, all emits associated with the specifier are output
- in order they were declared. A star means that last-read character should be output instead
- of constant value. Example:
-
- (**** syntax script ****)
-
- .syntax foobar;
- .emtcode WORD_FOO 0x01
- .emtcode WORD_BAR 0x02
- foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
- FOO "foo" .and SPACE;
- BAR "bar" .and SPACE;
- SPACE ' ' .or '\0';
-
- (**** sample text 1 ****)
-
- foo
-
- (**** sample text 2 ****)
-
- foobar
-
- For both samples the result will be one-element array. For first sample text it will be
- value 1, for second - 0. Note that every text will be accepted because of presence of
- .true as an alternative.
-
- Another example:
-
- (**** syntax script ****)
-
- .syntax declaration;
- .emtcode VARIABLE 0x01
- declaration "declare" .and .loop space .and
- identifier .emit VARIABLE .and (1)
- .true .emit 0x00 .and (2)
- .loop space .and ';';
- space ' ' .or '\t';
- identifier .loop id_char .emit *; (3)
- id_char 'a'-'z' .or 'A'-'Z' .or '_';
-
- (**** sample code ****)
-
- declare fubar;
-
- In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to
- true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used
- to terminate the string with null to signal when the string ends. Specifier (3) outputs
- all characters that make declared identifier. The result of sample code will be the
- following array:
- { 1, 'f', 'u', 'b', 'a', 'r', 0 }
-
- If .emit is followed by dollar $, it means that current position should be output. Current
- position is a 32-bit unsigned integer distance from the very beginning of the parsed string to
- first character consumed by the specifier associated with the .emit instruction. Current
- position is stored in the output buffer in Little-Endian convention (the lowest byte comes
- first).
-*/
-
-static void mem_free (void **);
-
-/*
- internal error messages
-*/
-static const byte *OUT_OF_MEMORY = (byte *) "internal error 1001: out of physical memory";
-static const byte *UNRESOLVED_REFERENCE = (byte *) "internal error 1002: unresolved reference '$'";
-static const byte *INVALID_GRAMMAR_ID = (byte *) "internal error 1003: invalid grammar object";
-static const byte *INVALID_REGISTER_NAME = (byte *) "internal error 1004: invalid register name: '$'";
-
-static const byte *error_message = NULL;
-static byte *error_param = NULL; /* this is inserted into error_message in place of $ */
-static int error_position = -1;
-
-static byte *unknown = (byte *) "???";
-
-static void clear_last_error ()
-{
- /* reset error message */
- error_message = NULL;
-
- /* free error parameter - if error_param is a "???" don't free it - it's static */
- if (error_param != unknown)
- mem_free ((void **) &error_param);
- else
- error_param = NULL;
-
- /* reset error position */
- error_position = -1;
-}
-
-static void set_last_error (const byte *msg, byte *param, int pos)
-{
- /* error message can only be set only once */
- if (error_message != NULL)
- {
- mem_free (&param);
- return;
- }
-
- error_message = msg;
-
- if (param != NULL)
- error_param = param;
- else
- error_param = unknown;
-
- error_position = pos;
-}
-
-/*
- memory management routines
-*/
-static void *mem_alloc (size_t size)
-{
- void *ptr = grammar_alloc_malloc (size);
- if (ptr == NULL)
- set_last_error (OUT_OF_MEMORY, NULL, -1);
- return ptr;
-}
-
-static void *mem_copy (void *dst, const void *src, size_t size)
-{
- return grammar_memory_copy (dst, src, size);
-}
-
-static void mem_free (void **ptr)
-{
- grammar_alloc_free (*ptr);
- *ptr = NULL;
-}
-
-static void *mem_realloc (void *ptr, size_t old_size, size_t new_size)
-{
- void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size);
- if (ptr2 == NULL)
- set_last_error (OUT_OF_MEMORY, NULL, -1);
- return ptr2;
-}
-
-static byte *str_copy_n (byte *dst, const byte *src, size_t max_len)
-{
- return grammar_string_copy_n (dst, src, max_len);
-}
-
-static byte *str_duplicate (const byte *str)
-{
- byte *new_str = grammar_string_duplicate (str);
- if (new_str == NULL)
- set_last_error (OUT_OF_MEMORY, NULL, -1);
- return new_str;
-}
-
-static int str_equal (const byte *str1, const byte *str2)
-{
- return grammar_string_compare (str1, str2) == 0;
-}
-
-static int str_equal_n (const byte *str1, const byte *str2, unsigned int n)
-{
- return grammar_string_compare_n (str1, str2, n) == 0;
-}
-
-static unsigned int str_length (const byte *str)
-{
- return grammar_string_length (str);
-}
-
-/*
- string to byte map typedef
-*/
-typedef struct map_byte_
-{
- byte *key;
- byte data;
- struct map_byte_ *next;
-} map_byte;
-
-static void map_byte_create (map_byte **ma)
-{
- *ma = mem_alloc (sizeof (map_byte));
- if (*ma)
- {
- (**ma).key = NULL;
- (**ma).data = '\0';
- (**ma).next = NULL;
- }
-}
-
-/* XXX unfold the recursion */
-static void map_byte_destroy (map_byte **ma)
-{
- if (*ma)
- {
- map_byte_destroy (&(**ma).next);
- mem_free ((void **) &(**ma).key);
- mem_free ((void **) ma);
- }
-}
-
-static void map_byte_append (map_byte **ma, map_byte **nm)
-{
- while (*ma)
- ma = &(**ma).next;
- *ma = *nm;
-}
-
-/*
- searches the map for the specified key,
- returns pointer to the element with the specified key if it exists
- returns NULL otherwise
-*/
-map_byte *map_byte_locate (map_byte **ma, const byte *key)
-{
- while (*ma)
- {
- if (str_equal ((**ma).key, key))
- return *ma;
-
- ma = &(**ma).next;
- }
-
- set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
- return NULL;
-}
-
-/*
- searches the map for specified key,
- if the key is matched, *data is filled with data associated with the key,
- returns 0 if the key is matched,
- returns 1 otherwise
-*/
-static int map_byte_find (map_byte **ma, const byte *key, byte *data)
-{
- map_byte *found = map_byte_locate (ma, key);
- if (found != NULL)
- {
- *data = found->data;
-
- return 0;
- }
-
- return 1;
-}
-
-/*
- regbyte context typedef
-
- Each regbyte consists of its name and a default value. These are static and created at
- grammar script compile-time, for example the following line:
- .regbyte vertex_blend 0x00
- adds a new regbyte named "vertex_blend" to the static list and initializes it to 0.
- When the script is executed, this regbyte can be accessed by name for read and write. When a
- particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx
- stack. The new entry contains information abot which regbyte it references and its new value.
- When a given regbyte is accessed for read, the stack is searched top-down to find an
- entry that references the regbyte. The first matching entry is used to return the current
- value it holds. If no entry is found, the default value is returned.
-*/
-typedef struct regbyte_ctx_
-{
- map_byte *m_regbyte;
- byte m_current_value;
- struct regbyte_ctx_ *m_prev;
-} regbyte_ctx;
-
-static void regbyte_ctx_create (regbyte_ctx **re)
-{
- *re = mem_alloc (sizeof (regbyte_ctx));
- if (*re)
- {
- (**re).m_regbyte = NULL;
- (**re).m_prev = NULL;
- }
-}
-
-static void regbyte_ctx_destroy (regbyte_ctx **re)
-{
- if (*re)
- {
- mem_free ((void **) re);
- }
-}
-
-static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg)
-{
- /* first lookup in the register stack */
- while (*re != NULL)
- {
- if ((**re).m_regbyte == reg)
- return (**re).m_current_value;
-
- re = &(**re).m_prev;
- }
-
- /* if not found - return the default value */
- return reg->data;
-}
-
-/*
- emit type typedef
-*/
-typedef enum emit_type_
-{
- et_byte, /* explicit number */
- et_stream, /* eaten character */
- et_position /* current position */
-} emit_type;
-
-/*
- emit destination typedef
-*/
-typedef enum emit_dest_
-{
- ed_output, /* write to the output buffer */
- ed_regbyte /* write a particular regbyte */
-} emit_dest;
-
-/*
- emit typedef
-*/
-typedef struct emit_
-{
- emit_dest m_emit_dest;
- emit_type m_emit_type; /* ed_output */
- byte m_byte; /* et_byte */
- map_byte *m_regbyte; /* ed_regbyte */
- byte *m_regname; /* ed_regbyte - temporary */
- struct emit_ *m_next;
-} emit;
-
-static void emit_create (emit **em)
-{
- *em = mem_alloc (sizeof (emit));
- if (*em)
- {
- (**em).m_emit_dest = ed_output;
- (**em).m_emit_type = et_byte;
- (**em).m_byte = '\0';
- (**em).m_regbyte = NULL;
- (**em).m_regname = NULL;
- (**em).m_next = NULL;
- }
-}
-
-static void emit_destroy (emit **em)
-{
- if (*em)
- {
- emit_destroy (&(**em).m_next);
- mem_free ((void **) &(**em).m_regname);
- mem_free ((void **) em);
- }
-}
-
-/*
- error typedef
-*/
-typedef struct error_
-{
- byte *m_text;
- byte *m_token_name;
- struct rule_ *m_token;
-} error;
-
-static void error_create (error **er)
-{
- *er = mem_alloc (sizeof (error));
- if (*er)
- {
- (**er).m_text = NULL;
- (**er).m_token_name = NULL;
- (**er).m_token = NULL;
- }
-}
-
-static void error_destroy (error **er)
-{
- if (*er)
- {
- mem_free ((void **) &(**er).m_text);
- mem_free ((void **) &(**er).m_token_name);
- mem_free ((void **) er);
- }
-}
-
-struct dict_;
-static byte *error_get_token (error *, struct dict_ *, const byte *, unsigned int);
-
-/*
- condition operand type typedef
-*/
-typedef enum cond_oper_type_
-{
- cot_byte, /* constant 8-bit unsigned integer */
- cot_regbyte /* pointer to byte register containing the current value */
-} cond_oper_type;
-
-/*
- condition operand typedef
-*/
-typedef struct cond_oper_
-{
- cond_oper_type m_type;
- byte m_byte; /* cot_byte */
- map_byte *m_regbyte; /* cot_regbyte */
- byte *m_regname; /* cot_regbyte - temporary */
-} cond_oper;
-
-/*
- condition type typedef
-*/
-typedef enum cond_type_
-{
- ct_equal,
- ct_not_equal
-} cond_type;
-
-/*
- condition typedef
-*/
-typedef struct cond_
-{
- cond_type m_type;
- cond_oper m_operands[2];
-} cond;
-
-static void cond_create (cond **co)
-{
- *co = mem_alloc (sizeof (cond));
- if (*co)
- {
- (**co).m_operands[0].m_regname = NULL;
- (**co).m_operands[1].m_regname = NULL;
- }
-}
-
-static void cond_destroy (cond **co)
-{
- if (*co)
- {
- mem_free ((void **) &(**co).m_operands[0].m_regname);
- mem_free ((void **) &(**co).m_operands[1].m_regname);
- mem_free ((void **) co);
- }
-}
-
-/*
- specifier type typedef
-*/
-typedef enum spec_type_
-{
- st_false,
- st_true,
- st_byte,
- st_byte_range,
- st_string,
- st_identifier,
- st_identifier_loop,
- st_debug
-} spec_type;
-
-/*
- specifier typedef
-*/
-typedef struct spec_
-{
- spec_type m_spec_type;
- byte m_byte[2]; /* st_byte, st_byte_range */
- byte *m_string; /* st_string */
- struct rule_ *m_rule; /* st_identifier, st_identifier_loop */
- emit *m_emits;
- error *m_errtext;
- cond *m_cond;
- struct spec_ *m_next;
-} spec;
-
-static void spec_create (spec **sp)
-{
- *sp = mem_alloc (sizeof (spec));
- if (*sp)
- {
- (**sp).m_spec_type = st_false;
- (**sp).m_byte[0] = '\0';
- (**sp).m_byte[1] = '\0';
- (**sp).m_string = NULL;
- (**sp).m_rule = NULL;
- (**sp).m_emits = NULL;
- (**sp).m_errtext = NULL;
- (**sp).m_cond = NULL;
- (**sp).m_next = NULL;
- }
-}
-
-static void spec_destroy (spec **sp)
-{
- if (*sp)
- {
- spec_destroy (&(**sp).m_next);
- emit_destroy (&(**sp).m_emits);
- error_destroy (&(**sp).m_errtext);
- mem_free ((void **) &(**sp).m_string);
- cond_destroy (&(**sp).m_cond);
- mem_free ((void **) sp);
- }
-}
-
-static void spec_append (spec **sp, spec **ns)
-{
- while (*sp)
- sp = &(**sp).m_next;
- *sp = *ns;
-}
-
-/*
- operator typedef
-*/
-typedef enum oper_
-{
- op_none,
- op_and,
- op_or
-} oper;
-
-/*
- rule typedef
-*/
-typedef struct rule_
-{
- oper m_oper;
- spec *m_specs;
- struct rule_ *m_next;
-/* int m_referenced; */ /* for debugging purposes */
-} rule;
-
-static void rule_create (rule **ru)
-{
- *ru = mem_alloc (sizeof (rule));
- if (*ru)
- {
- (**ru).m_oper = op_none;
- (**ru).m_specs = NULL;
- (**ru).m_next = NULL;
-/* (**ru).m_referenced = 0; */
- }
-}
-
-static void rule_destroy (rule **ru)
-{
- if (*ru)
- {
- rule_destroy (&(**ru).m_next);
- spec_destroy (&(**ru).m_specs);
- mem_free ((void **) ru);
- }
-}
-
-static void rule_append (rule **ru, rule **nr)
-{
- while (*ru)
- ru = &(**ru).m_next;
- *ru = *nr;
-}
-
-/*
- returns unique grammar id
-*/
-static grammar next_valid_grammar_id ()
-{
- static grammar id = 0;
-
- return ++id;
-}
-
-/*
- dictionary typedef
-*/
-typedef struct dict_
-{
- rule *m_rulez;
- rule *m_syntax;
- rule *m_string;
- map_byte *m_regbytes;
- grammar m_id;
- struct dict_ *m_next;
-} dict;
-
-static void dict_create (dict **di)
-{
- *di = mem_alloc (sizeof (dict));
- if (*di)
- {
- (**di).m_rulez = NULL;
- (**di).m_syntax = NULL;
- (**di).m_string = NULL;
- (**di).m_regbytes = NULL;
- (**di).m_id = next_valid_grammar_id ();
- (**di).m_next = NULL;
- }
-}
-
-static void dict_destroy (dict **di)
-{
- if (*di)
- {
- rule_destroy (&(**di).m_rulez);
- map_byte_destroy (&(**di).m_regbytes);
- mem_free ((void **) di);
- }
-}
-
-static void dict_append (dict **di, dict **nd)
-{
- while (*di)
- di = &(**di).m_next;
- *di = *nd;
-}
-
-static void dict_find (dict **di, grammar key, dict **data)
-{
- while (*di)
- {
- if ((**di).m_id == key)
- {
- *data = *di;
- return;
- }
-
- di = &(**di).m_next;
- }
-
- *data = NULL;
-}
-
-static dict *g_dicts = NULL;
-
-/*
- byte array typedef
-
- XXX this class is going to be replaced by a faster one, soon
-*/
-typedef struct barray_
-{
- byte *data;
- unsigned int len;
-} barray;
-
-static void barray_create (barray **ba)
-{
- *ba = mem_alloc (sizeof (barray));
- if (*ba)
- {
- (**ba).data = NULL;
- (**ba).len = 0;
- }
-}
-
-static void barray_destroy (barray **ba)
-{
- if (*ba)
- {
- mem_free ((void **) &(**ba).data);
- mem_free ((void **) ba);
- }
-}
-
-/*
- reallocates byte array to requested size,
- returns 0 on success,
- returns 1 otherwise
-*/
-static int barray_resize (barray **ba, unsigned int nlen)
-{
- byte *new_pointer;
-
- if (nlen == 0)
- {
- mem_free ((void **) &(**ba).data);
- (**ba).data = NULL;
- (**ba).len = 0;
-
- return 0;
- }
- else
- {
- new_pointer = mem_realloc ((**ba).data, (**ba).len * sizeof (byte), nlen * sizeof (byte));
- if (new_pointer)
- {
- (**ba).data = new_pointer;
- (**ba).len = nlen;
-
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- adds byte array pointed by *nb to the end of array pointed by *ba,
- returns 0 on success,
- returns 1 otherwise
-*/
-static int barray_append (barray **ba, barray **nb)
-{
- const unsigned int len = (**ba).len;
-
- if (barray_resize (ba, (**ba).len + (**nb).len))
- return 1;
-
- mem_copy ((**ba).data + len, (**nb).data, (**nb).len);
-
- return 0;
-}
-
-/*
- adds emit chain pointed by em to the end of array pointed by *ba,
- returns 0 on success,
- returns 1 otherwise
-*/
-static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc)
-{
- emit *temp = em;
- unsigned int count = 0;
-
- while (temp)
- {
- if (temp->m_emit_dest == ed_output)
- if (temp->m_emit_type == et_position)
- count += 4; /* position is a 32-bit unsigned integer */
- else
- count++;
-
- temp = temp->m_next;
- }
-
- if (barray_resize (ba, (**ba).len + count))
- return 1;
-
- while (em)
- {
- if (em->m_emit_dest == ed_output)
- {
- if (em->m_emit_type == et_byte)
- (**ba).data[(**ba).len - count--] = em->m_byte;
- else if (em->m_emit_type == et_stream)
- (**ba).data[(**ba).len - count--] = c;
- else // em->type == et_position
- (**ba).data[(**ba).len - count--] = (byte) pos,
- (**ba).data[(**ba).len - count--] = (byte) (pos >> 8),
- (**ba).data[(**ba).len - count--] = (byte) (pos >> 16),
- (**ba).data[(**ba).len - count--] = (byte) (pos >> 24);
- }
- else
- {
- regbyte_ctx *new_rbc;
- regbyte_ctx_create (&new_rbc);
- if (new_rbc == NULL)
- return 1;
-
- new_rbc->m_prev = *rbc;
- new_rbc->m_regbyte = em->m_regbyte;
- *rbc = new_rbc;
-
- if (em->m_emit_type == et_byte)
- new_rbc->m_current_value = em->m_byte;
- else if (em->m_emit_type == et_stream)
- new_rbc->m_current_value = c;
- }
-
- em = em->m_next;
- }
-
- return 0;
-}
-
-/*
- string to string map typedef
-*/
-typedef struct map_str_
-{
- byte *key;
- byte *data;
- struct map_str_ *next;
-} map_str;
-
-static void map_str_create (map_str **ma)
-{
- *ma = mem_alloc (sizeof (map_str));
- if (*ma)
- {
- (**ma).key = NULL;
- (**ma).data = NULL;
- (**ma).next = NULL;
- }
-}
-
-static void map_str_destroy (map_str **ma)
-{
- if (*ma)
- {
- map_str_destroy (&(**ma).next);
- mem_free ((void **) &(**ma).key);
- mem_free ((void **) &(**ma).data);
- mem_free ((void **) ma);
- }
-}
-
-static void map_str_append (map_str **ma, map_str **nm)
-{
- while (*ma)
- ma = &(**ma).next;
- *ma = *nm;
-}
-
-/*
- searches the map for specified key,
- if the key is matched, *data is filled with data associated with the key,
- returns 0 if the key is matched,
- returns 1 otherwise
-*/
-static int map_str_find (map_str **ma, const byte *key, byte **data)
-{
- while (*ma)
- {
- if (str_equal ((**ma).key, key))
- {
- *data = str_duplicate ((**ma).data);
- if (*data == NULL)
- return 1;
-
- return 0;
- }
-
- ma = &(**ma).next;
- }
-
- set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
- return 1;
-}
-
-/*
- string to rule map typedef
-*/
-typedef struct map_rule_
-{
- byte *key;
- rule *data;
- struct map_rule_ *next;
-} map_rule;
-
-static void map_rule_create (map_rule **ma)
-{
- *ma = mem_alloc (sizeof (map_rule));
- if (*ma)
- {
- (**ma).key = NULL;
- (**ma).data = NULL;
- (**ma).next = NULL;
- }
-}
-
-static void map_rule_destroy (map_rule **ma)
-{
- if (*ma)
- {
- map_rule_destroy (&(**ma).next);
- mem_free ((void **) &(**ma).key);
- mem_free ((void **) ma);
- }
-}
-
-static void map_rule_append (map_rule **ma, map_rule **nm)
-{
- while (*ma)
- ma = &(**ma).next;
- *ma = *nm;
-}
-
-/*
- searches the map for specified key,
- if the key is matched, *data is filled with data associated with the key,
- returns 0 if the is matched,
- returns 1 otherwise
-*/
-static int map_rule_find (map_rule **ma, const byte *key, rule **data)
-{
- while (*ma)
- {
- if (str_equal ((**ma).key, key))
- {
- *data = (**ma).data;
-
- return 0;
- }
-
- ma = &(**ma).next;
- }
-
- set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
- return 1;
-}
-
-/*
- returns 1 if given character is a white space,
- returns 0 otherwise
-*/
-static int is_space (byte c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == '\r';
-}
-
-/*
- advances text pointer by 1 if character pointed by *text is a space,
- returns 1 if a space has been eaten,
- returns 0 otherwise
-*/
-static int eat_space (const byte **text)
-{
- if (is_space (**text))
- {
- (*text)++;
-
- return 1;
- }
-
- return 0;
-}
-
-/*
- returns 1 if text points to C-style comment start string "/*",
- returns 0 otherwise
-*/
-static int is_comment_start (const byte *text)
-{
- return text[0] == '/' && text[1] == '*';
-}
-
-/*
- advances text pointer to first character after C-style comment block - if any,
- returns 1 if C-style comment block has been encountered and eaten,
- returns 0 otherwise
-*/
-static int eat_comment (const byte **text)
-{
- if (is_comment_start (*text))
- {
- /* *text points to comment block - skip two characters to enter comment body */
- *text += 2;
- /* skip any character except consecutive '*' and '/' */
- while (!((*text)[0] == '*' && (*text)[1] == '/'))
- (*text)++;
- /* skip those two terminating characters */
- *text += 2;
-
- return 1;
- }
-
- return 0;
-}
-
-/*
- advances text pointer to first character that is neither space nor C-style comment block
-*/
-static void eat_spaces (const byte **text)
-{
- while (eat_space (text) || eat_comment (text))
- ;
-}
-
-/*
- resizes string pointed by *ptr to successfully add character c to the end of the string,
- returns 0 on success,
- returns 1 otherwise
-*/
-static int string_grow (byte **ptr, unsigned int *len, byte c)
-{
- /* reallocate the string in 16-byte increments */
- if ((*len & 0x0F) == 0x0F || *ptr == NULL)
- {
- byte *tmp = mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),
- ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));
- if (tmp == NULL)
- return 1;
-
- *ptr = tmp;
- }
-
- if (c)
- {
- /* append given character */
- (*ptr)[*len] = c;
- (*len)++;
- }
- (*ptr)[*len] = '\0';
-
- return 0;
-}
-
-/*
- returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _
- returns 0 otherwise
-*/
-static int is_identifier (byte c)
-{
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
-}
-
-/*
- copies characters from *text to *id until non-identifier character is encountered,
- assumes that *id points to NULL object - caller is responsible for later freeing the string,
- text pointer is advanced to point past the copied identifier,
- returns 0 if identifier was successfully copied,
- returns 1 otherwise
-*/
-static int get_identifier (const byte **text, byte **id)
-{
- const byte *t = *text;
- byte *p = NULL;
- unsigned int len = 0;
-
- if (string_grow (&p, &len, '\0'))
- return 1;
-
- /* loop while next character in buffer is valid for identifiers */
- while (is_identifier (*t))
- {
- if (string_grow (&p, &len, *t++))
- {
- mem_free ((void **) &p);
- return 1;
- }
- }
-
- *text = t;
- *id = p;
-
- return 0;
-}
-
-/*
- returns 1 if given character is HEX digit 0-9, A-F or a-f,
- returns 0 otherwise
-*/
-static int is_hex (byte c)
-{
- return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
-}
-
-/*
- returns value of passed character as if it was HEX digit
-*/
-static unsigned int hex2dec (byte c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- return c - 'a' + 10;
-}
-
-/*
- converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
- advances text pointer past the converted sequence,
- returns the converted value
-*/
-static unsigned int hex_convert (const byte **text)
-{
- unsigned int value = 0;
-
- while (is_hex (**text))
- {
- value = value * 0x10 + hex2dec (**text);
- (*text)++;
- }
-
- return value;
-}
-
-/*
- returns 1 if given character is OCT digit 0-7,
- returns 0 otherwise
-*/
-static int is_oct (byte c)
-{
- return c >= '0' && c <= '7';
-}
-
-/*
- returns value of passed character as if it was OCT digit
-*/
-static int oct2dec (byte c)
-{
- return c - '0';
-}
-
-static byte get_escape_sequence (const byte **text)
-{
- int value = 0;
-
- /* skip '\' character */
- (*text)++;
-
- switch (*(*text)++)
- {
- case '\'':
- return '\'';
- case '"':
- return '\"';
- case '?':
- return '\?';
- case '\\':
- return '\\';
- case 'a':
- return '\a';
- case 'b':
- return '\b';
- case 'f':
- return '\f';
- case 'n':
- return '\n';
- case 'r':
- return '\r';
- case 't':
- return '\t';
- case 'v':
- return '\v';
- case 'x':
- return (byte) hex_convert (text);
- }
-
- (*text)--;
- if (is_oct (**text))
- {
- value = oct2dec (*(*text)++);
- if (is_oct (**text))
- {
- value = value * 010 + oct2dec (*(*text)++);
- if (is_oct (**text))
- value = value * 010 + oct2dec (*(*text)++);
- }
- }
-
- return (byte) value;
-}
-
-/*
- copies characters from *text to *str until " or ' character is encountered,
- assumes that *str points to NULL object - caller is responsible for later freeing the string,
- assumes that *text points to " or ' character that starts the string,
- text pointer is advanced to point past the " or ' character,
- returns 0 if string was successfully copied,
- returns 1 otherwise
-*/
-static int get_string (const byte **text, byte **str)
-{
- const byte *t = *text;
- byte *p = NULL;
- unsigned int len = 0;
- byte term_char;
-
- if (string_grow (&p, &len, '\0'))
- return 1;
-
- /* read " or ' character that starts the string */
- term_char = *t++;
- /* while next character is not the terminating character */
- while (*t && *t != term_char)
- {
- byte c;
-
- if (*t == '\\')
- c = get_escape_sequence (&t);
- else
- c = *t++;
-
- if (string_grow (&p, &len, c))
- {
- mem_free ((void **) &p);
- return 1;
- }
- }
- /* skip " or ' character that ends the string */
- t++;
-
- *text = t;
- *str = p;
- return 0;
-}
-
-/*
- gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
- assumes that *text already points to <symbol>,
- returns 0 if emit code is successfully read,
- returns 1 otherwise
-*/
-static int get_emtcode (const byte **text, map_byte **ma)
-{
- const byte *t = *text;
- map_byte *m = NULL;
-
- map_byte_create (&m);
- if (m == NULL)
- return 1;
-
- if (get_identifier (&t, &m->key))
- {
- map_byte_destroy (&m);
- return 1;
- }
- eat_spaces (&t);
-
- if (*t == '\'')
- {
- byte *c;
-
- if (get_string (&t, &c))
- {
- map_byte_destroy (&m);
- return 1;
- }
-
- m->data = (byte) c[0];
- mem_free ((void **) &c);
- }
- else
- {
- /* skip HEX "0x" or "0X" prefix */
- t += 2;
- m->data = (byte) hex_convert (&t);
- }
-
- eat_spaces (&t);
-
- *text = t;
- *ma = m;
- return 0;
-}
-
-/*
- gets regbyte declaration, the syntax is: ".regbyte" " " <symbol> " " ("0x" | "0X") <hex_value>
- assumes that *text already points to <symbol>,
- returns 0 if regbyte is successfully read,
- returns 1 otherwise
-*/
-static int get_regbyte (const byte **text, map_byte **ma)
-{
- return get_emtcode (text, ma);
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise
-*/
-static int get_errtext (const byte **text, map_str **ma)
-{
- const byte *t = *text;
- map_str *m = NULL;
-
- map_str_create (&m);
- if (m == NULL)
- return 1;
-
- if (get_identifier (&t, &m->key))
- {
- map_str_destroy (&m);
- return 1;
- }
- eat_spaces (&t);
-
- if (get_string (&t, &m->data))
- {
- map_str_destroy (&m);
- return 1;
- }
- eat_spaces (&t);
-
- *text = t;
- *ma = m;
- return 0;
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise,
-*/
-static int get_error (const byte **text, error **er, map_str *maps)
-{
- const byte *t = *text;
- byte *temp = NULL;
-
- if (*t != '.')
- return 0;
-
- t++;
- if (get_identifier (&t, &temp))
- return 1;
- eat_spaces (&t);
-
- if (!str_equal ((byte *) "error", temp))
- {
- mem_free ((void **) &temp);
- return 0;
- }
-
- mem_free ((void **) &temp);
-
- error_create (er);
- if (*er == NULL)
- return 1;
-
- if (*t == '\"')
- {
- if (get_string (&t, &(**er).m_text))
- {
- error_destroy (er);
- return 1;
- }
- eat_spaces (&t);
- }
- else
- {
- if (get_identifier (&t, &temp))
- {
- error_destroy (er);
- return 1;
- }
- eat_spaces (&t);
-
- if (map_str_find (&maps, temp, &(**er).m_text))
- {
- mem_free ((void **) &temp);
- error_destroy (er);
- return 1;
- }
-
- mem_free ((void **) &temp);
- }
-
- /* try to extract "token" from "...$token$..." */
- {
- byte *processed = NULL;
- unsigned int len = 0, i = 0;
-
- if (string_grow (&processed, &len, '\0'))
- {
- error_destroy (er);
- return 1;
- }
-
- while (i < str_length ((**er).m_text))
- {
- /* check if the dollar sign is repeated - if so skip it */
- if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$')
- {
- if (string_grow (&processed, &len, '$'))
- {
- mem_free ((void **) &processed);
- error_destroy (er);
- return 1;
- }
-
- i += 2;
- }
- else if ((**er).m_text[i] != '$')
- {
- if (string_grow (&processed, &len, (**er).m_text[i]))
- {
- mem_free ((void **) &processed);
- error_destroy (er);
- return 1;
- }
-
- i++;
- }
- else
- {
- if (string_grow (&processed, &len, '$'))
- {
- mem_free ((void **) &processed);
- error_destroy (er);
- return 1;
- }
-
- {
- /* length of token being extracted */
- unsigned int tlen = 0;
-
- if (string_grow (&(**er).m_token_name, &tlen, '\0'))
- {
- mem_free ((void **) &processed);
- error_destroy (er);
- return 1;
- }
-
- /* skip the dollar sign */
- i++;
-
- while ((**er).m_text[i] != '$')
- {
- if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i]))
- {
- mem_free ((void **) &processed);
- error_destroy (er);
- return 1;
- }
-
- i++;
- }
-
- /* skip the dollar sign */
- i++;
- }
- }
- }
-
- mem_free ((void **) &(**er).m_text);
- (**er).m_text = processed;
- }
-
- *text = t;
- return 0;
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise,
-*/
-static int get_emits (const byte **text, emit **em, map_byte *mapb)
-{
- const byte *t = *text;
- byte *temp = NULL;
- emit *e = NULL;
- emit_dest dest;
-
- if (*t != '.')
- return 0;
-
- t++;
- if (get_identifier (&t, &temp))
- return 1;
- eat_spaces (&t);
-
- /* .emit */
- if (str_equal ((byte *) "emit", temp))
- dest = ed_output;
- /* .load */
- else if (str_equal ((byte *) "load", temp))
- dest = ed_regbyte;
- else
- {
- mem_free ((void **) &temp);
- return 0;
- }
-
- mem_free ((void **) &temp);
-
- emit_create (&e);
- if (e == NULL)
- return 1;
-
- e->m_emit_dest = dest;
-
- if (dest == ed_regbyte)
- {
- if (get_identifier (&t, &e->m_regname))
- {
- emit_destroy (&e);
- return 1;
- }
- eat_spaces (&t);
- }
-
- /* 0xNN */
- if (*t == '0')
- {
- t += 2;
- e->m_byte = (byte) hex_convert (&t);
-
- e->m_emit_type = et_byte;
- }
- /* * */
- else if (*t == '*')
- {
- t++;
-
- e->m_emit_type = et_stream;
- }
- /* $ */
- else if (*t == '$')
- {
- t++;
-
- e->m_emit_type = et_position;
- }
- /* 'c' */
- else if (*t == '\'')
- {
- if (get_string (&t, &temp))
- {
- emit_destroy (&e);
- return 1;
- }
- e->m_byte = (byte) temp[0];
-
- mem_free ((void **) &temp);
-
- e->m_emit_type = et_byte;
- }
- else
- {
- if (get_identifier (&t, &temp))
- {
- emit_destroy (&e);
- return 1;
- }
-
- if (map_byte_find (&mapb, temp, &e->m_byte))
- {
- mem_free ((void **) &temp);
- emit_destroy (&e);
- return 1;
- }
-
- mem_free ((void **) &temp);
-
- e->m_emit_type = et_byte;
- }
-
- eat_spaces (&t);
-
- if (get_emits (&t, &e->m_next, mapb))
- {
- emit_destroy (&e);
- return 1;
- }
-
- *text = t;
- *em = e;
- return 0;
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise,
-*/
-static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb)
-{
- const byte *t = *text;
- spec *s = NULL;
-
- spec_create (&s);
- if (s == NULL)
- return 1;
-
- /* first - read optional .if statement */
- if (*t == '.')
- {
- const byte *u = t;
- byte *keyword = NULL;
-
- /* skip the dot */
- u++;
-
- if (get_identifier (&u, &keyword))
- {
- spec_destroy (&s);
- return 1;
- }
-
- /* .if */
- if (str_equal ((byte *) "if", keyword))
- {
- cond_create (&s->m_cond);
- if (s->m_cond == NULL)
- {
- spec_destroy (&s);
- return 1;
- }
-
- /* skip the left paren */
- eat_spaces (&u);
- u++;
-
- /* get the left operand */
- eat_spaces (&u);
- if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname))
- {
- spec_destroy (&s);
- return 1;
- }
- s->m_cond->m_operands[0].m_type = cot_regbyte;
-
- /* get the operator (!= or ==) */
- eat_spaces (&u);
- if (*u == '!')
- s->m_cond->m_type = ct_not_equal;
- else
- s->m_cond->m_type = ct_equal;
- u += 2;
-
- /* skip the 0x prefix */
- eat_spaces (&u);
- u += 2;
-
- /* get the right operand */
- s->m_cond->m_operands[1].m_byte = hex_convert (&u);
- s->m_cond->m_operands[1].m_type = cot_byte;
-
- /* skip the right paren */
- eat_spaces (&u);
- u++;
-
- eat_spaces (&u);
-
- t = u;
- }
-
- mem_free ((void **) &keyword);
- }
-
- if (*t == '\'')
- {
- byte *temp = NULL;
-
- if (get_string (&t, &temp))
- {
- spec_destroy (&s);
- return 1;
- }
- eat_spaces (&t);
-
- if (*t == '-')
- {
- byte *temp2 = NULL;
-
- /* skip the '-' character */
- t++;
- eat_spaces (&t);
-
- if (get_string (&t, &temp2))
- {
- mem_free ((void **) &temp);
- spec_destroy (&s);
- return 1;
- }
- eat_spaces (&t);
-
- s->m_spec_type = st_byte_range;
- s->m_byte[0] = *temp;
- s->m_byte[1] = *temp2;
-
- mem_free ((void **) &temp2);
- }
- else
- {
- s->m_spec_type = st_byte;
- *s->m_byte = *temp;
- }
-
- mem_free ((void **) &temp);
- }
- else if (*t == '"')
- {
- if (get_string (&t, &s->m_string))
- {
- spec_destroy (&s);
- return 1;
- }
- eat_spaces (&t);
-
- s->m_spec_type = st_string;
- }
- else if (*t == '.')
- {
- byte *keyword = NULL;
-
- /* skip the dot */
- t++;
-
- if (get_identifier (&t, &keyword))
- {
- spec_destroy (&s);
- return 1;
- }
- eat_spaces (&t);
-
- /* .true */
- if (str_equal ((byte *) "true", keyword))
- {
- s->m_spec_type = st_true;
- }
- /* .false */
- else if (str_equal ((byte *) "false", keyword))
- {
- s->m_spec_type = st_false;
- }
- /* .debug */
- else if (str_equal ((byte *) "debug", keyword))
- {
- s->m_spec_type = st_debug;
- }
- /* .loop */
- else if (str_equal ((byte *) "loop", keyword))
- {
- if (get_identifier (&t, &s->m_string))
- {
- mem_free ((void **) &keyword);
- spec_destroy (&s);
- return 1;
- }
- eat_spaces (&t);
-
- s->m_spec_type = st_identifier_loop;
- }
-
- mem_free ((void **) &keyword);
- }
- else
- {
- if (get_identifier (&t, &s->m_string))
- {
- spec_destroy (&s);
- return 1;
- }
- eat_spaces (&t);
-
- s->m_spec_type = st_identifier;
- }
-
- if (get_error (&t, &s->m_errtext, maps))
- {
- spec_destroy (&s);
- return 1;
- }
-
- if (get_emits (&t, &s->m_emits, mapb))
- {
- spec_destroy (&s);
- return 1;
- }
-
- *text = t;
- *sp = s;
- return 0;
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise,
-*/
-static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)
-{
- const byte *t = *text;
- rule *r = NULL;
-
- rule_create (&r);
- if (r == NULL)
- return 1;
-
- if (get_spec (&t, &r->m_specs, maps, mapb))
- {
- rule_destroy (&r);
- return 1;
- }
-
- while (*t != ';')
- {
- byte *op = NULL;
- spec *sp = NULL;
-
- /* skip the dot that precedes "and" or "or" */
- t++;
-
- /* read "and" or "or" keyword */
- if (get_identifier (&t, &op))
- {
- rule_destroy (&r);
- return 1;
- }
- eat_spaces (&t);
-
- if (r->m_oper == op_none)
- {
- /* .and */
- if (str_equal ((byte *) "and", op))
- r->m_oper = op_and;
- /* .or */
- else
- r->m_oper = op_or;
- }
-
- mem_free ((void **) &op);
-
- if (get_spec (&t, &sp, maps, mapb))
- {
- rule_destroy (&r);
- return 1;
- }
-
- spec_append (&r->m_specs, &sp);
- }
-
- /* skip the semicolon */
- t++;
- eat_spaces (&t);
-
- *text = t;
- *ru = r;
- return 0;
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise,
-*/
-static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)
-{
- if (map_rule_find (&mapr, symbol, ru))
- return 1;
-
-/* (**ru).m_referenced = 1; */
-
- return 0;
-}
-
-/*
- returns 0 on success,
- returns 1 otherwise,
-*/
-static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,
- byte **string_symbol, map_byte *regbytes)
-{
- rule *rulez = di->m_rulez;
-
- /* update dependecies for the root and lexer symbols */
- if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||
- (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))
- return 1;
-
- mem_free ((void **) syntax_symbol);
- mem_free ((void **) string_symbol);
-
- /* update dependecies for the rest of the rules */
- while (rulez)
- {
- spec *sp = rulez->m_specs;
-
- /* iterate through all the specifiers */
- while (sp)
- {
- /* update dependency for identifier */
- if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)
- {
- if (update_dependency (mapr, sp->m_string, &sp->m_rule))
- return 1;
-
- mem_free ((void **) &sp->m_string);
- }
-
- /* some errtexts reference to a rule */
- if (sp->m_errtext && sp->m_errtext->m_token_name)
- {
- if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))
- return 1;
-
- mem_free ((void **) &sp->m_errtext->m_token_name);
- }
-
- /* update dependency for condition */
- if (sp->m_cond)
- {
- int i;
- for (i = 0; i < 2; i++)
- if (sp->m_cond->m_operands[i].m_type == cot_regbyte)
- {
- sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (&regbytes,
- sp->m_cond->m_operands[i].m_regname);
-
- if (sp->m_cond->m_operands[i].m_regbyte == NULL)
- return 1;
-
- mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);
- }
- }
-
- /* update dependency for all .load instructions */
- if (sp->m_emits)
- {
- emit *em = sp->m_emits;
- while (em != NULL)
- {
- if (em->m_emit_dest == ed_regbyte)
- {
- em->m_regbyte = map_byte_locate (&regbytes, em->m_regname);
-
- if (em->m_regbyte == NULL)
- return 1;
-
- mem_free ((void **) &em->m_regname);
- }
-
- em = em->m_next;
- }
- }
-
- sp = sp->m_next;
- }
-
- rulez = rulez->m_next;
- }
-
-/* check for unreferenced symbols */
-/* de = di->m_defntns;
- while (de)
- {
- if (!de->m_referenced)
- {
- map_def *ma = mapd;
- while (ma)
- {
- if (ma->data == de)
- {
- assert (0);
- break;
- }
- ma = ma->next;
- }
- }
- de = de->m_next;
- }
-*/
- return 0;
-}
-
-static int satisfies_condition (cond *co, regbyte_ctx *ctx)
-{
- byte values[2];
- int i;
-
- if (co == NULL)
- return 1;
-
- for (i = 0; i < 2; i++)
- switch (co->m_operands[i].m_type)
- {
- case cot_byte:
- values[i] = co->m_operands[i].m_byte;
- break;
- case cot_regbyte:
- values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);
- break;
- }
-
- switch (co->m_type)
- {
- case ct_equal:
- return values[0] == values[1];
- case ct_not_equal:
- return values[0] != values[1];
- }
-
- return 0;
-}
-
-static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)
-{
- while (top != limit)
- {
- regbyte_ctx *rbc = top->m_prev;
- regbyte_ctx_destroy (&top);
- top = rbc;
- }
-}
-
-typedef enum match_result_
-{
- mr_not_matched, /* the examined string does not match */
- mr_matched, /* the examined string matches */
- mr_error_raised, /* mr_not_matched + error has been raised */
- mr_dont_emit, /* used by identifier loops only */
- mr_internal_error /* an internal error has occured such as out of memory */
-} match_result;
-
-/*
- This function does the main job. It parses the text and generates output data.
-
- XXX optimize it - the barray seems to be the bottleneck
-*/
-static match_result match (dict *di, const byte *text, unsigned int *index, rule *ru, barray **ba,
- int filtering_string, regbyte_ctx **rbc)
-{
- unsigned int ind = *index;
- match_result status = mr_not_matched;
- spec *sp = ru->m_specs;
- regbyte_ctx *ctx = *rbc;
-
- /* for every specifier in the rule */
- while (sp)
- {
- unsigned int i, len, save_ind = ind;
- barray *array = NULL;
-
- if (satisfies_condition (sp->m_cond, ctx))
- {
- switch (sp->m_spec_type)
- {
- case st_identifier:
- barray_create (&array);
- if (array == NULL)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- return mr_internal_error;
- }
-
- status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
- if (status == mr_internal_error)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
- return mr_internal_error;
- }
- break;
- case st_string:
- len = str_length (sp->m_string);
-
- /* prefilter the stream */
- if (!filtering_string && di->m_string)
- {
- barray *ba;
- unsigned int filter_index = 0;
- match_result result;
- regbyte_ctx *null_ctx = NULL;
-
- barray_create (&ba);
- if (ba == NULL)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- return mr_internal_error;
- }
-
- result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);
-
- if (result == mr_internal_error)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&ba);
- return mr_internal_error;
- }
-
- if (result != mr_matched)
- {
- barray_destroy (&ba);
- status = mr_not_matched;
- break;
- }
-
- barray_destroy (&ba);
-
- if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))
- {
- status = mr_not_matched;
- break;
- }
-
- status = mr_matched;
- ind += len;
- }
- else
- {
- status = mr_matched;
- for (i = 0; status == mr_matched && i < len; i++)
- if (text[ind + i] != sp->m_string[i])
- status = mr_not_matched;
- if (status == mr_matched)
- ind += len;
- }
- break;
- case st_byte:
- status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
- if (status == mr_matched)
- ind++;
- break;
- case st_byte_range:
- status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?
- mr_matched : mr_not_matched;
- if (status == mr_matched)
- ind++;
- break;
- case st_true:
- status = mr_matched;
- break;
- case st_false:
- status = mr_not_matched;
- break;
- case st_debug:
- status = ru->m_oper == op_and ? mr_matched : mr_not_matched;
- break;
- case st_identifier_loop:
- barray_create (&array);
- if (array == NULL)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- return mr_internal_error;
- }
-
- status = mr_dont_emit;
- for (;;)
- {
- match_result result;
-
- save_ind = ind;
- result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
-
- if (result == mr_error_raised)
- {
- status = result;
- break;
- }
- else if (result == mr_matched)
- {
- if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||
- barray_append (ba, &array))
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
- return mr_internal_error;
- }
- barray_destroy (&array);
- barray_create (&array);
- if (array == NULL)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- return mr_internal_error;
- }
- }
- else if (result == mr_internal_error)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
- return mr_internal_error;
- }
- else
- break;
- }
- break;
- }
- }
- else
- {
- status = mr_not_matched;
- }
-
- if (status == mr_error_raised)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
-
- return mr_error_raised;
- }
-
- if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
-
- if (sp->m_errtext)
- {
- set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,
- ind), ind);
-
- return mr_error_raised;
- }
-
- return mr_not_matched;
- }
-
- if (status == mr_matched)
- {
- if (sp->m_emits)
- if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx))
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
- return mr_internal_error;
- }
-
- if (array)
- if (barray_append (ba, &array))
- {
- free_regbyte_ctx_stack (ctx, *rbc);
- barray_destroy (&array);
- return mr_internal_error;
- }
- }
-
- barray_destroy (&array);
-
- /* if the rule operator is a logical or, we pick up the first matching specifier */
- if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))
- {
- *index = ind;
- *rbc = ctx;
- return mr_matched;
- }
-
- sp = sp->m_next;
- }
-
- /* everything went fine - all specifiers match up */
- if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))
- {
- *index = ind;
- *rbc = ctx;
- return mr_matched;
- }
-
- free_regbyte_ctx_stack (ctx, *rbc);
- return mr_not_matched;
-}
-
-static byte *error_get_token (error *er, dict *di, const byte *text, unsigned int ind)
-{
- byte *str = NULL;
-
- if (er->m_token)
- {
- barray *ba;
- unsigned int filter_index = 0;
- regbyte_ctx *ctx = NULL;
-
- barray_create (&ba);
- if (ba != NULL)
- {
- if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched &&
- filter_index)
- {
- str = mem_alloc (filter_index + 1);
- if (str != NULL)
- {
- str_copy_n (str, text + ind, filter_index);
- str[filter_index] = '\0';
- }
- }
- barray_destroy (&ba);
- }
- }
-
- return str;
-}
-
-typedef struct grammar_load_state_
-{
- dict *di;
- byte *syntax_symbol;
- byte *string_symbol;
- map_str *maps;
- map_byte *mapb;
- map_rule *mapr;
-} grammar_load_state;
-
-static void grammar_load_state_create (grammar_load_state **gr)
-{
- *gr = mem_alloc (sizeof (grammar_load_state));
- if (*gr)
- {
- (**gr).di = NULL;
- (**gr).syntax_symbol = NULL;
- (**gr).string_symbol = NULL;
- (**gr).maps = NULL;
- (**gr).mapb = NULL;
- (**gr).mapr = NULL;
- }
-}
-
-static void grammar_load_state_destroy (grammar_load_state **gr)
-{
- if (*gr)
- {
- dict_destroy (&(**gr).di);
- mem_free ((void **) &(**gr).syntax_symbol);
- mem_free ((void **) &(**gr).string_symbol);
- map_str_destroy (&(**gr).maps);
- map_byte_destroy (&(**gr).mapb);
- map_rule_destroy (&(**gr).mapr);
- mem_free ((void **) gr);
- }
-}
-
-/*
- the API
-*/
-
-grammar grammar_load_from_text (const byte *text)
-{
- grammar_load_state *g = NULL;
- grammar id = 0;
-
- clear_last_error ();
-
- grammar_load_state_create (&g);
- if (g == NULL)
- return 0;
-
- dict_create (&g->di);
- if (g->di == NULL)
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- eat_spaces (&text);
-
- /* skip ".syntax" keyword */
- text += 7;
- eat_spaces (&text);
-
- /* retrieve root symbol */
- if (get_identifier (&text, &g->syntax_symbol))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
- eat_spaces (&text);
-
- /* skip semicolon */
- text++;
- eat_spaces (&text);
-
- while (*text)
- {
- byte *symbol = NULL;
- int is_dot = *text == '.';
-
- if (is_dot)
- text++;
-
- if (get_identifier (&text, &symbol))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
- eat_spaces (&text);
-
- /* .emtcode */
- if (is_dot && str_equal (symbol, (byte *) "emtcode"))
- {
- map_byte *ma = NULL;
-
- mem_free ((void **) &symbol);
-
- if (get_emtcode (&text, &ma))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- map_byte_append (&g->mapb, &ma);
- }
- /* .regbyte */
- else if (is_dot && str_equal (symbol, (byte *) "regbyte"))
- {
- map_byte *ma = NULL;
-
- mem_free ((void **) &symbol);
-
- if (get_regbyte (&text, &ma))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- map_byte_append (&g->di->m_regbytes, &ma);
- }
- /* .errtext */
- else if (is_dot && str_equal (symbol, (byte *) "errtext"))
- {
- map_str *ma = NULL;
-
- mem_free ((void **) &symbol);
-
- if (get_errtext (&text, &ma))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- map_str_append (&g->maps, &ma);
- }
- /* .string */
- else if (is_dot && str_equal (symbol, (byte *) "string"))
- {
- mem_free ((void **) &symbol);
-
- if (g->di->m_string != NULL)
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- if (get_identifier (&text, &g->string_symbol))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- /* skip semicolon */
- eat_spaces (&text);
- text++;
- eat_spaces (&text);
- }
- else
- {
- rule *ru = NULL;
- map_rule *ma = NULL;
-
- if (get_rule (&text, &ru, g->maps, g->mapb))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- rule_append (&g->di->m_rulez, &ru);
-
- /* if a rule consist of only one specifier, give it an ".and" operator */
- if (ru->m_oper == op_none)
- ru->m_oper = op_and;
-
- map_rule_create (&ma);
- if (ma == NULL)
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- ma->key = symbol;
- ma->data = ru;
- map_rule_append (&g->mapr, &ma);
- }
- }
-
- if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol,
- g->di->m_regbytes))
- {
- grammar_load_state_destroy (&g);
- return 0;
- }
-
- dict_append (&g_dicts, &g->di);
- id = g->di->m_id;
- g->di = NULL;
-
- grammar_load_state_destroy (&g);
-
- return id;
-}
-
-int grammar_set_reg8 (grammar id, const byte *name, byte value)
-{
- dict *di = NULL;
- map_byte *reg = NULL;
-
- clear_last_error ();
-
- dict_find (&g_dicts, id, &di);
- if (di == NULL)
- {
- set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
- return 0;
- }
-
- reg = map_byte_locate (&di->m_regbytes, name);
- if (reg == NULL)
- {
- set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1);
- return 0;
- }
-
- reg->data = value;
- return 1;
-}
-
-int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size)
-{
- dict *di = NULL;
- barray *ba = NULL;
- unsigned int index = 0;
- regbyte_ctx *rbc = NULL;
-
- clear_last_error ();
-
- dict_find (&g_dicts, id, &di);
- if (di == NULL)
- {
- set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
- return 0;
- }
-
- barray_create (&ba);
- if (ba == NULL)
- return 0;
-
- *prod = NULL;
- *size = 0;
-
- if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched)
- {
- barray_destroy (&ba);
- free_regbyte_ctx_stack (rbc, NULL);
- return 0;
- }
-
- free_regbyte_ctx_stack (rbc, NULL);
-
- *prod = mem_alloc (ba->len * sizeof (byte));
- if (*prod == NULL)
- {
- barray_destroy (&ba);
- return 0;
- }
-
- mem_copy (*prod, ba->data, ba->len * sizeof (byte));
- *size = ba->len;
- barray_destroy (&ba);
-
- return 1;
-}
-
-int grammar_destroy (grammar id)
-{
- dict **di = &g_dicts;
-
- clear_last_error ();
-
- while (*di != NULL)
- {
- if ((**di).m_id == id)
- {
- dict *tmp = *di;
- *di = (**di).m_next;
- dict_destroy (&tmp);
- return 1;
- }
-
- di = &(**di).m_next;
- }
-
- set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
- return 0;
-}
-
-void grammar_get_last_error (byte *text, unsigned int size, int *pos)
-{
- unsigned int len = 0, dots_made = 0;
- const byte *p = error_message;
-
- *text = '\0';
-
-#define APPEND_CHARACTER(x) if (dots_made == 0) {\
- if (len < size - 1) {\
- text[len++] = (x); text[len] = '\0';\
- } else {\
- int i;\
- for (i = 0; i < 3; i++)\
- if (--len >= 0)\
- text[len] = '.';\
- dots_made = 1;\
- }\
- }
-
- if (p)
- while (*p)
- if (*p == '$')
- {
- const byte *r = error_param;
-
- while (*r)
- {
- APPEND_CHARACTER(*r)
- r++;
- }
-
- p++;
- }
- else
- {
- APPEND_CHARACTER(*p)
- p++;
- }
-
- *pos = error_position;
-
-#undef APPEND_CHARACTER
-
-}
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * \file grammar.c
+ * syntax parsing engine
+ * \author Michal Krol
+ */
+
+#ifndef GRAMMAR_PORT_BUILD
+#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file
+#endif
+
+/*
+ Last Modified: 2004-II-8
+*/
+
+/*
+ INTRODUCTION
+ ------------
+
+ The task is to check the syntax of an input string. Input string is a stream of ASCII
+ characters terminated with a null-character ('\0'). Checking it using C language is
+ difficult and hard to implement without bugs. It is hard to maintain and make changes when
+ the syntax changes.
+
+ This is because of a high redundancy of the C code. Large blocks of code are duplicated with
+ only small changes. Even use of macros does not solve the problem because macros cannot
+ erase the complexity of the problem.
+
+ The resolution is to create a new language that will be highly oriented to our task. Once
+ we describe a particular syntax, we are done. We can then focus on the code that implements
+ the language. The size and complexity of it is relatively small than the code that directly
+ checks the syntax.
+
+ First, we must implement our new language. Here, the language is implemented in C, but it
+ could also be implemented in any other language. The code is listed below. We must take
+ a good care that it is bug free. This is simple because the code is simple and clean.
+
+ Next, we must describe the syntax of our new language in itself. Once created and checked
+ manually that it is correct, we can use it to check another scripts.
+
+ Note that our new language loading code does not have to check the syntax. It is because we
+ assume that the script describing itself is correct, and other scripts can be syntactically
+ checked by the former script. The loading code must only do semantic checking which leads us to
+ simple resolving references.
+
+ THE LANGUAGE
+ ------------
+
+ Here I will describe the syntax of the new language (further called "Synek"). It is mainly a
+ sequence of declarations terminated by a semicolon. The declaration consists of a symbol,
+ which is an identifier, and its definition. A definition is in turn a sequence of specifiers
+ connected with ".and" or ".or" operator. These operators cannot be mixed together in a one
+ definition. Specifier can be a symbol, string, character, character range or a special
+ keyword ".true" or ".false".
+
+ On the very beginning of the script there is a declaration of a root symbol and is in the form:
+ .syntax <root_symbol>;
+ The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if
+ the root symbol evaluates to true. A symbol evaluates to true if the definition associated with
+ the symbol evaluates to true. Definition evaluation depends on the operator used to connect
+ specifiers in the definition. If ".and" operator is used, definition evaluates to true if and
+ only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to
+ true if any of the specifiers evaluates to true. If definition contains only one specifier,
+ it is evaluated as if it was connected with ".true" keyword by ".and" operator.
+
+ If specifier is a ".true" keyword, it always evaluates to true.
+
+ If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false
+ when it does not evaluate to true.
+
+ Character range specifier is in the form:
+ '<first_character>' - '<second_character>'
+ If specifier is a character range, it evaluates to true if character in the stream is greater
+ or equal to <first_character> and less or equal to <second_character>. In that situation
+ the stream pointer is advanced to point to next character in the stream. All C-style escape
+ sequences are supported although trigraph sequences are not. The comparisions are performed
+ on 8-bit unsigned integers.
+
+ Character specifier is in the form:
+ '<single_character>'
+ It evaluates to true if the following character range specifier evaluates to true:
+ '<single_character>' - '<single_character>'
+
+ String specifier is in the form:
+ "<string>"
+ Let N be the number of characters in <string>. Let <string>[i] designate i-th character in
+ <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)
+ the following character specifier evaluates to true:
+ '<string>[i]'
+ If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.
+
+ Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
+ .loop <symbol> (1)
+ where <symbol> is defined as follows:
+ <symbol> <definition>; (2)
+ Construction (1) is replaced by the following code:
+ <symbol$1>
+ and declaration (2) is replaced by the following:
+ <symbol$1> <symbol$2> .or .true;
+ <symbol$2> <symbol> .and <symbol$1>;
+ <symbol> <definition>;
+
+ Synek supports also a register mechanizm. User can, in its SYN file, declare a number of
+ registers that can be accessed in the syn body. Each reg has its name and a default value.
+ The register is one byte wide. The C code can change the default value by calling
+ grammar_set_reg8() with grammar id, register name and a new value. As we know, each rule is
+ a sequence of specifiers joined with .and or .or operator. And now each specifier can be
+ prefixed with a condition expression in a form ".if (<reg_name> <operator> <hex_literal>)"
+ where <operator> can be == or !=. If the condition evaluates to false, the specifier
+ evaluates to .false. Otherwise it evalutes to the specifier.
+
+ ESCAPE SEQUENCES
+ ----------------
+
+ Synek supports all escape sequences in character specifiers. The mapping table is listed below.
+ All occurences of the characters in the first column are replaced with the corresponding
+ character in the second column.
+
+ Escape sequence Represents
+ ------------------------------------------------------------------------------------------------
+ \a Bell (alert)
+ \b Backspace
+ \f Formfeed
+ \n New line
+ \r Carriage return
+ \t Horizontal tab
+ \v Vertical tab
+ \' Single quotation mark
+ \" Double quotation mark
+ \\ Backslash
+ \? Literal question mark
+ \ooo ASCII character in octal notation
+ \xhhh ASCII character in hexadecimal notation
+ ------------------------------------------------------------------------------------------------
+
+ RAISING ERRORS
+ --------------
+
+ Any specifier can be followed by a special construction that is executed when the specifier
+ evaluates to false. The construction is in the form:
+ .error <ERROR_TEXT>
+ <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is
+ in the form:
+ .errtext <ERROR_TEXT> "<error_desc>"
+ When specifier evaluates to false and this construction is present, parsing is stopped
+ immediately and <error_desc> is returned as a result of parsing. The error position is also
+ returned and it is meant as an offset from the beggining of the stream to the character that
+ was valid so far. Example:
+
+ (**** syntax script ****)
+
+ .syntax program;
+ .errtext MISSING_SEMICOLON "missing ';'"
+ program declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and
+ .loop space .and '\0';
+ declaration "declare" .and .loop space .and identifier;
+ space ' ';
+
+ (**** sample code ****)
+
+ declare foo ,
+
+ In the example above checking the sample code will result in error message "missing ';'" and
+ error position 12. The sample code is not correct. Note the presence of '\0' specifier to
+ assure that there is no code after semicolon - only spaces.
+ <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,
+ the identifier and dollar signs are replaced by a string retrieved by invoking symbol with
+ the identifier name. The starting position is the error position. The lenght of the resulting
+ string is the position after invoking the symbol.
+
+ PRODUCTION
+ ----------
+
+ Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers
+ that evaluate to true. That is, every specifier and optional error construction can be followed
+ by a number of emit constructions that are in the form:
+ .emit <parameter>
+ <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by
+ 0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration
+ in the form:
+ .emtcode <identifier> <hex_number>
+
+ When given specifier evaluates to true, all emits associated with the specifier are output
+ in order they were declared. A star means that last-read character should be output instead
+ of constant value. Example:
+
+ (**** syntax script ****)
+
+ .syntax foobar;
+ .emtcode WORD_FOO 0x01
+ .emtcode WORD_BAR 0x02
+ foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
+ FOO "foo" .and SPACE;
+ BAR "bar" .and SPACE;
+ SPACE ' ' .or '\0';
+
+ (**** sample text 1 ****)
+
+ foo
+
+ (**** sample text 2 ****)
+
+ foobar
+
+ For both samples the result will be one-element array. For first sample text it will be
+ value 1, for second - 0. Note that every text will be accepted because of presence of
+ .true as an alternative.
+
+ Another example:
+
+ (**** syntax script ****)
+
+ .syntax declaration;
+ .emtcode VARIABLE 0x01
+ declaration "declare" .and .loop space .and
+ identifier .emit VARIABLE .and (1)
+ .true .emit 0x00 .and (2)
+ .loop space .and ';';
+ space ' ' .or '\t';
+ identifier .loop id_char .emit *; (3)
+ id_char 'a'-'z' .or 'A'-'Z' .or '_';
+
+ (**** sample code ****)
+
+ declare fubar;
+
+ In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to
+ true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used
+ to terminate the string with null to signal when the string ends. Specifier (3) outputs
+ all characters that make declared identifier. The result of sample code will be the
+ following array:
+ { 1, 'f', 'u', 'b', 'a', 'r', 0 }
+
+ If .emit is followed by dollar $, it means that current position should be output. Current
+ position is a 32-bit unsigned integer distance from the very beginning of the parsed string to
+ first character consumed by the specifier associated with the .emit instruction. Current
+ position is stored in the output buffer in Little-Endian convention (the lowest byte comes
+ first).
+*/
+
+static void mem_free (void **);
+
+/*
+ internal error messages
+*/
+static const byte *OUT_OF_MEMORY = (byte *) "internal error 1001: out of physical memory";
+static const byte *UNRESOLVED_REFERENCE = (byte *) "internal error 1002: unresolved reference '$'";
+static const byte *INVALID_GRAMMAR_ID = (byte *) "internal error 1003: invalid grammar object";
+static const byte *INVALID_REGISTER_NAME = (byte *) "internal error 1004: invalid register name: '$'";
+
+static const byte *error_message = NULL;
+static byte *error_param = NULL; /* this is inserted into error_message in place of $ */
+static int error_position = -1;
+
+static byte *unknown = (byte *) "???";
+
+static void clear_last_error ()
+{
+ /* reset error message */
+ error_message = NULL;
+
+ /* free error parameter - if error_param is a "???" don't free it - it's static */
+ if (error_param != unknown)
+ mem_free ((void **) &error_param);
+ else
+ error_param = NULL;
+
+ /* reset error position */
+ error_position = -1;
+}
+
+static void set_last_error (const byte *msg, byte *param, int pos)
+{
+ /* error message can only be set only once */
+ if (error_message != NULL)
+ {
+ mem_free (&param);
+ return;
+ }
+
+ error_message = msg;
+
+ if (param != NULL)
+ error_param = param;
+ else
+ error_param = unknown;
+
+ error_position = pos;
+}
+
+/*
+ memory management routines
+*/
+static void *mem_alloc (size_t size)
+{
+ void *ptr = grammar_alloc_malloc (size);
+ if (ptr == NULL)
+ set_last_error (OUT_OF_MEMORY, NULL, -1);
+ return ptr;
+}
+
+static void *mem_copy (void *dst, const void *src, size_t size)
+{
+ return grammar_memory_copy (dst, src, size);
+}
+
+static void mem_free (void **ptr)
+{
+ grammar_alloc_free (*ptr);
+ *ptr = NULL;
+}
+
+static void *mem_realloc (void *ptr, size_t old_size, size_t new_size)
+{
+ void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size);
+ if (ptr2 == NULL)
+ set_last_error (OUT_OF_MEMORY, NULL, -1);
+ return ptr2;
+}
+
+static byte *str_copy_n (byte *dst, const byte *src, size_t max_len)
+{
+ return grammar_string_copy_n (dst, src, max_len);
+}
+
+static byte *str_duplicate (const byte *str)
+{
+ byte *new_str = grammar_string_duplicate (str);
+ if (new_str == NULL)
+ set_last_error (OUT_OF_MEMORY, NULL, -1);
+ return new_str;
+}
+
+static int str_equal (const byte *str1, const byte *str2)
+{
+ return grammar_string_compare (str1, str2) == 0;
+}
+
+static int str_equal_n (const byte *str1, const byte *str2, unsigned int n)
+{
+ return grammar_string_compare_n (str1, str2, n) == 0;
+}
+
+static unsigned int str_length (const byte *str)
+{
+ return grammar_string_length (str);
+}
+
+/*
+ string to byte map typedef
+*/
+typedef struct map_byte_
+{
+ byte *key;
+ byte data;
+ struct map_byte_ *next;
+} map_byte;
+
+static void map_byte_create (map_byte **ma)
+{
+ *ma = mem_alloc (sizeof (map_byte));
+ if (*ma)
+ {
+ (**ma).key = NULL;
+ (**ma).data = '\0';
+ (**ma).next = NULL;
+ }
+}
+
+/* XXX unfold the recursion */
+static void map_byte_destroy (map_byte **ma)
+{
+ if (*ma)
+ {
+ map_byte_destroy (&(**ma).next);
+ mem_free ((void **) &(**ma).key);
+ mem_free ((void **) ma);
+ }
+}
+
+static void map_byte_append (map_byte **ma, map_byte **nm)
+{
+ while (*ma)
+ ma = &(**ma).next;
+ *ma = *nm;
+}
+
+/*
+ searches the map for the specified key,
+ returns pointer to the element with the specified key if it exists
+ returns NULL otherwise
+*/
+map_byte *map_byte_locate (map_byte **ma, const byte *key)
+{
+ while (*ma)
+ {
+ if (str_equal ((**ma).key, key))
+ return *ma;
+
+ ma = &(**ma).next;
+ }
+
+ set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+ return NULL;
+}
+
+/*
+ searches the map for specified key,
+ if the key is matched, *data is filled with data associated with the key,
+ returns 0 if the key is matched,
+ returns 1 otherwise
+*/
+static int map_byte_find (map_byte **ma, const byte *key, byte *data)
+{
+ map_byte *found = map_byte_locate (ma, key);
+ if (found != NULL)
+ {
+ *data = found->data;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ regbyte context typedef
+
+ Each regbyte consists of its name and a default value. These are static and created at
+ grammar script compile-time, for example the following line:
+ .regbyte vertex_blend 0x00
+ adds a new regbyte named "vertex_blend" to the static list and initializes it to 0.
+ When the script is executed, this regbyte can be accessed by name for read and write. When a
+ particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx
+ stack. The new entry contains information abot which regbyte it references and its new value.
+ When a given regbyte is accessed for read, the stack is searched top-down to find an
+ entry that references the regbyte. The first matching entry is used to return the current
+ value it holds. If no entry is found, the default value is returned.
+*/
+typedef struct regbyte_ctx_
+{
+ map_byte *m_regbyte;
+ byte m_current_value;
+ struct regbyte_ctx_ *m_prev;
+} regbyte_ctx;
+
+static void regbyte_ctx_create (regbyte_ctx **re)
+{
+ *re = mem_alloc (sizeof (regbyte_ctx));
+ if (*re)
+ {
+ (**re).m_regbyte = NULL;
+ (**re).m_prev = NULL;
+ }
+}
+
+static void regbyte_ctx_destroy (regbyte_ctx **re)
+{
+ if (*re)
+ {
+ mem_free ((void **) re);
+ }
+}
+
+static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg)
+{
+ /* first lookup in the register stack */
+ while (*re != NULL)
+ {
+ if ((**re).m_regbyte == reg)
+ return (**re).m_current_value;
+
+ re = &(**re).m_prev;
+ }
+
+ /* if not found - return the default value */
+ return reg->data;
+}
+
+/*
+ emit type typedef
+*/
+typedef enum emit_type_
+{
+ et_byte, /* explicit number */
+ et_stream, /* eaten character */
+ et_position /* current position */
+} emit_type;
+
+/*
+ emit destination typedef
+*/
+typedef enum emit_dest_
+{
+ ed_output, /* write to the output buffer */
+ ed_regbyte /* write a particular regbyte */
+} emit_dest;
+
+/*
+ emit typedef
+*/
+typedef struct emit_
+{
+ emit_dest m_emit_dest;
+ emit_type m_emit_type; /* ed_output */
+ byte m_byte; /* et_byte */
+ map_byte *m_regbyte; /* ed_regbyte */
+ byte *m_regname; /* ed_regbyte - temporary */
+ struct emit_ *m_next;
+} emit;
+
+static void emit_create (emit **em)
+{
+ *em = mem_alloc (sizeof (emit));
+ if (*em)
+ {
+ (**em).m_emit_dest = ed_output;
+ (**em).m_emit_type = et_byte;
+ (**em).m_byte = '\0';
+ (**em).m_regbyte = NULL;
+ (**em).m_regname = NULL;
+ (**em).m_next = NULL;
+ }
+}
+
+static void emit_destroy (emit **em)
+{
+ if (*em)
+ {
+ emit_destroy (&(**em).m_next);
+ mem_free ((void **) &(**em).m_regname);
+ mem_free ((void **) em);
+ }
+}
+
+/*
+ error typedef
+*/
+typedef struct error_
+{
+ byte *m_text;
+ byte *m_token_name;
+ struct rule_ *m_token;
+} error;
+
+static void error_create (error **er)
+{
+ *er = mem_alloc (sizeof (error));
+ if (*er)
+ {
+ (**er).m_text = NULL;
+ (**er).m_token_name = NULL;
+ (**er).m_token = NULL;
+ }
+}
+
+static void error_destroy (error **er)
+{
+ if (*er)
+ {
+ mem_free ((void **) &(**er).m_text);
+ mem_free ((void **) &(**er).m_token_name);
+ mem_free ((void **) er);
+ }
+}
+
+struct dict_;
+static byte *error_get_token (error *, struct dict_ *, const byte *, unsigned int);
+
+/*
+ condition operand type typedef
+*/
+typedef enum cond_oper_type_
+{
+ cot_byte, /* constant 8-bit unsigned integer */
+ cot_regbyte /* pointer to byte register containing the current value */
+} cond_oper_type;
+
+/*
+ condition operand typedef
+*/
+typedef struct cond_oper_
+{
+ cond_oper_type m_type;
+ byte m_byte; /* cot_byte */
+ map_byte *m_regbyte; /* cot_regbyte */
+ byte *m_regname; /* cot_regbyte - temporary */
+} cond_oper;
+
+/*
+ condition type typedef
+*/
+typedef enum cond_type_
+{
+ ct_equal,
+ ct_not_equal
+} cond_type;
+
+/*
+ condition typedef
+*/
+typedef struct cond_
+{
+ cond_type m_type;
+ cond_oper m_operands[2];
+} cond;
+
+static void cond_create (cond **co)
+{
+ *co = mem_alloc (sizeof (cond));
+ if (*co)
+ {
+ (**co).m_operands[0].m_regname = NULL;
+ (**co).m_operands[1].m_regname = NULL;
+ }
+}
+
+static void cond_destroy (cond **co)
+{
+ if (*co)
+ {
+ mem_free ((void **) &(**co).m_operands[0].m_regname);
+ mem_free ((void **) &(**co).m_operands[1].m_regname);
+ mem_free ((void **) co);
+ }
+}
+
+/*
+ specifier type typedef
+*/
+typedef enum spec_type_
+{
+ st_false,
+ st_true,
+ st_byte,
+ st_byte_range,
+ st_string,
+ st_identifier,
+ st_identifier_loop,
+ st_debug
+} spec_type;
+
+/*
+ specifier typedef
+*/
+typedef struct spec_
+{
+ spec_type m_spec_type;
+ byte m_byte[2]; /* st_byte, st_byte_range */
+ byte *m_string; /* st_string */
+ struct rule_ *m_rule; /* st_identifier, st_identifier_loop */
+ emit *m_emits;
+ error *m_errtext;
+ cond *m_cond;
+ struct spec_ *m_next;
+} spec;
+
+static void spec_create (spec **sp)
+{
+ *sp = mem_alloc (sizeof (spec));
+ if (*sp)
+ {
+ (**sp).m_spec_type = st_false;
+ (**sp).m_byte[0] = '\0';
+ (**sp).m_byte[1] = '\0';
+ (**sp).m_string = NULL;
+ (**sp).m_rule = NULL;
+ (**sp).m_emits = NULL;
+ (**sp).m_errtext = NULL;
+ (**sp).m_cond = NULL;
+ (**sp).m_next = NULL;
+ }
+}
+
+static void spec_destroy (spec **sp)
+{
+ if (*sp)
+ {
+ spec_destroy (&(**sp).m_next);
+ emit_destroy (&(**sp).m_emits);
+ error_destroy (&(**sp).m_errtext);
+ mem_free ((void **) &(**sp).m_string);
+ cond_destroy (&(**sp).m_cond);
+ mem_free ((void **) sp);
+ }
+}
+
+static void spec_append (spec **sp, spec **ns)
+{
+ while (*sp)
+ sp = &(**sp).m_next;
+ *sp = *ns;
+}
+
+/*
+ operator typedef
+*/
+typedef enum oper_
+{
+ op_none,
+ op_and,
+ op_or
+} oper;
+
+/*
+ rule typedef
+*/
+typedef struct rule_
+{
+ oper m_oper;
+ spec *m_specs;
+ struct rule_ *m_next;
+/* int m_referenced; */ /* for debugging purposes */
+} rule;
+
+static void rule_create (rule **ru)
+{
+ *ru = mem_alloc (sizeof (rule));
+ if (*ru)
+ {
+ (**ru).m_oper = op_none;
+ (**ru).m_specs = NULL;
+ (**ru).m_next = NULL;
+/* (**ru).m_referenced = 0; */
+ }
+}
+
+static void rule_destroy (rule **ru)
+{
+ if (*ru)
+ {
+ rule_destroy (&(**ru).m_next);
+ spec_destroy (&(**ru).m_specs);
+ mem_free ((void **) ru);
+ }
+}
+
+static void rule_append (rule **ru, rule **nr)
+{
+ while (*ru)
+ ru = &(**ru).m_next;
+ *ru = *nr;
+}
+
+/*
+ returns unique grammar id
+*/
+static grammar next_valid_grammar_id ()
+{
+ static grammar id = 0;
+
+ return ++id;
+}
+
+/*
+ dictionary typedef
+*/
+typedef struct dict_
+{
+ rule *m_rulez;
+ rule *m_syntax;
+ rule *m_string;
+ map_byte *m_regbytes;
+ grammar m_id;
+ struct dict_ *m_next;
+} dict;
+
+static void dict_create (dict **di)
+{
+ *di = mem_alloc (sizeof (dict));
+ if (*di)
+ {
+ (**di).m_rulez = NULL;
+ (**di).m_syntax = NULL;
+ (**di).m_string = NULL;
+ (**di).m_regbytes = NULL;
+ (**di).m_id = next_valid_grammar_id ();
+ (**di).m_next = NULL;
+ }
+}
+
+static void dict_destroy (dict **di)
+{
+ if (*di)
+ {
+ rule_destroy (&(**di).m_rulez);
+ map_byte_destroy (&(**di).m_regbytes);
+ mem_free ((void **) di);
+ }
+}
+
+static void dict_append (dict **di, dict **nd)
+{
+ while (*di)
+ di = &(**di).m_next;
+ *di = *nd;
+}
+
+static void dict_find (dict **di, grammar key, dict **data)
+{
+ while (*di)
+ {
+ if ((**di).m_id == key)
+ {
+ *data = *di;
+ return;
+ }
+
+ di = &(**di).m_next;
+ }
+
+ *data = NULL;
+}
+
+static dict *g_dicts = NULL;
+
+/*
+ byte array typedef
+
+ XXX this class is going to be replaced by a faster one, soon
+*/
+typedef struct barray_
+{
+ byte *data;
+ unsigned int len;
+} barray;
+
+static void barray_create (barray **ba)
+{
+ *ba = mem_alloc (sizeof (barray));
+ if (*ba)
+ {
+ (**ba).data = NULL;
+ (**ba).len = 0;
+ }
+}
+
+static void barray_destroy (barray **ba)
+{
+ if (*ba)
+ {
+ mem_free ((void **) &(**ba).data);
+ mem_free ((void **) ba);
+ }
+}
+
+/*
+ reallocates byte array to requested size,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int barray_resize (barray **ba, unsigned int nlen)
+{
+ byte *new_pointer;
+
+ if (nlen == 0)
+ {
+ mem_free ((void **) &(**ba).data);
+ (**ba).data = NULL;
+ (**ba).len = 0;
+
+ return 0;
+ }
+ else
+ {
+ new_pointer = mem_realloc ((**ba).data, (**ba).len * sizeof (byte), nlen * sizeof (byte));
+ if (new_pointer)
+ {
+ (**ba).data = new_pointer;
+ (**ba).len = nlen;
+
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ adds byte array pointed by *nb to the end of array pointed by *ba,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int barray_append (barray **ba, barray **nb)
+{
+ const unsigned int len = (**ba).len;
+
+ if (barray_resize (ba, (**ba).len + (**nb).len))
+ return 1;
+
+ mem_copy ((**ba).data + len, (**nb).data, (**nb).len);
+
+ return 0;
+}
+
+/*
+ adds emit chain pointed by em to the end of array pointed by *ba,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc)
+{
+ emit *temp = em;
+ unsigned int count = 0;
+
+ while (temp)
+ {
+ if (temp->m_emit_dest == ed_output)
+ if (temp->m_emit_type == et_position)
+ count += 4; /* position is a 32-bit unsigned integer */
+ else
+ count++;
+
+ temp = temp->m_next;
+ }
+
+ if (barray_resize (ba, (**ba).len + count))
+ return 1;
+
+ while (em)
+ {
+ if (em->m_emit_dest == ed_output)
+ {
+ if (em->m_emit_type == et_byte)
+ (**ba).data[(**ba).len - count--] = em->m_byte;
+ else if (em->m_emit_type == et_stream)
+ (**ba).data[(**ba).len - count--] = c;
+ else // em->type == et_position
+ (**ba).data[(**ba).len - count--] = (byte) pos,
+ (**ba).data[(**ba).len - count--] = (byte) (pos >> 8),
+ (**ba).data[(**ba).len - count--] = (byte) (pos >> 16),
+ (**ba).data[(**ba).len - count--] = (byte) (pos >> 24);
+ }
+ else
+ {
+ regbyte_ctx *new_rbc;
+ regbyte_ctx_create (&new_rbc);
+ if (new_rbc == NULL)
+ return 1;
+
+ new_rbc->m_prev = *rbc;
+ new_rbc->m_regbyte = em->m_regbyte;
+ *rbc = new_rbc;
+
+ if (em->m_emit_type == et_byte)
+ new_rbc->m_current_value = em->m_byte;
+ else if (em->m_emit_type == et_stream)
+ new_rbc->m_current_value = c;
+ }
+
+ em = em->m_next;
+ }
+
+ return 0;
+}
+
+/*
+ string to string map typedef
+*/
+typedef struct map_str_
+{
+ byte *key;
+ byte *data;
+ struct map_str_ *next;
+} map_str;
+
+static void map_str_create (map_str **ma)
+{
+ *ma = mem_alloc (sizeof (map_str));
+ if (*ma)
+ {
+ (**ma).key = NULL;
+ (**ma).data = NULL;
+ (**ma).next = NULL;
+ }
+}
+
+static void map_str_destroy (map_str **ma)
+{
+ if (*ma)
+ {
+ map_str_destroy (&(**ma).next);
+ mem_free ((void **) &(**ma).key);
+ mem_free ((void **) &(**ma).data);
+ mem_free ((void **) ma);
+ }
+}
+
+static void map_str_append (map_str **ma, map_str **nm)
+{
+ while (*ma)
+ ma = &(**ma).next;
+ *ma = *nm;
+}
+
+/*
+ searches the map for specified key,
+ if the key is matched, *data is filled with data associated with the key,
+ returns 0 if the key is matched,
+ returns 1 otherwise
+*/
+static int map_str_find (map_str **ma, const byte *key, byte **data)
+{
+ while (*ma)
+ {
+ if (str_equal ((**ma).key, key))
+ {
+ *data = str_duplicate ((**ma).data);
+ if (*data == NULL)
+ return 1;
+
+ return 0;
+ }
+
+ ma = &(**ma).next;
+ }
+
+ set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+ return 1;
+}
+
+/*
+ string to rule map typedef
+*/
+typedef struct map_rule_
+{
+ byte *key;
+ rule *data;
+ struct map_rule_ *next;
+} map_rule;
+
+static void map_rule_create (map_rule **ma)
+{
+ *ma = mem_alloc (sizeof (map_rule));
+ if (*ma)
+ {
+ (**ma).key = NULL;
+ (**ma).data = NULL;
+ (**ma).next = NULL;
+ }
+}
+
+static void map_rule_destroy (map_rule **ma)
+{
+ if (*ma)
+ {
+ map_rule_destroy (&(**ma).next);
+ mem_free ((void **) &(**ma).key);
+ mem_free ((void **) ma);
+ }
+}
+
+static void map_rule_append (map_rule **ma, map_rule **nm)
+{
+ while (*ma)
+ ma = &(**ma).next;
+ *ma = *nm;
+}
+
+/*
+ searches the map for specified key,
+ if the key is matched, *data is filled with data associated with the key,
+ returns 0 if the is matched,
+ returns 1 otherwise
+*/
+static int map_rule_find (map_rule **ma, const byte *key, rule **data)
+{
+ while (*ma)
+ {
+ if (str_equal ((**ma).key, key))
+ {
+ *data = (**ma).data;
+
+ return 0;
+ }
+
+ ma = &(**ma).next;
+ }
+
+ set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+ return 1;
+}
+
+/*
+ returns 1 if given character is a white space,
+ returns 0 otherwise
+*/
+static int is_space (byte c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+}
+
+/*
+ advances text pointer by 1 if character pointed by *text is a space,
+ returns 1 if a space has been eaten,
+ returns 0 otherwise
+*/
+static int eat_space (const byte **text)
+{
+ if (is_space (**text))
+ {
+ (*text)++;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ returns 1 if text points to C-style comment start string "/*",
+ returns 0 otherwise
+*/
+static int is_comment_start (const byte *text)
+{
+ return text[0] == '/' && text[1] == '*';
+}
+
+/*
+ advances text pointer to first character after C-style comment block - if any,
+ returns 1 if C-style comment block has been encountered and eaten,
+ returns 0 otherwise
+*/
+static int eat_comment (const byte **text)
+{
+ if (is_comment_start (*text))
+ {
+ /* *text points to comment block - skip two characters to enter comment body */
+ *text += 2;
+ /* skip any character except consecutive '*' and '/' */
+ while (!((*text)[0] == '*' && (*text)[1] == '/'))
+ (*text)++;
+ /* skip those two terminating characters */
+ *text += 2;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ advances text pointer to first character that is neither space nor C-style comment block
+*/
+static void eat_spaces (const byte **text)
+{
+ while (eat_space (text) || eat_comment (text))
+ ;
+}
+
+/*
+ resizes string pointed by *ptr to successfully add character c to the end of the string,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int string_grow (byte **ptr, unsigned int *len, byte c)
+{
+ /* reallocate the string in 16-byte increments */
+ if ((*len & 0x0F) == 0x0F || *ptr == NULL)
+ {
+ byte *tmp = mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),
+ ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));
+ if (tmp == NULL)
+ return 1;
+
+ *ptr = tmp;
+ }
+
+ if (c)
+ {
+ /* append given character */
+ (*ptr)[*len] = c;
+ (*len)++;
+ }
+ (*ptr)[*len] = '\0';
+
+ return 0;
+}
+
+/*
+ returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _
+ returns 0 otherwise
+*/
+static int is_identifier (byte c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+}
+
+/*
+ copies characters from *text to *id until non-identifier character is encountered,
+ assumes that *id points to NULL object - caller is responsible for later freeing the string,
+ text pointer is advanced to point past the copied identifier,
+ returns 0 if identifier was successfully copied,
+ returns 1 otherwise
+*/
+static int get_identifier (const byte **text, byte **id)
+{
+ const byte *t = *text;
+ byte *p = NULL;
+ unsigned int len = 0;
+
+ if (string_grow (&p, &len, '\0'))
+ return 1;
+
+ /* loop while next character in buffer is valid for identifiers */
+ while (is_identifier (*t))
+ {
+ if (string_grow (&p, &len, *t++))
+ {
+ mem_free ((void **) &p);
+ return 1;
+ }
+ }
+
+ *text = t;
+ *id = p;
+
+ return 0;
+}
+
+/*
+ returns 1 if given character is HEX digit 0-9, A-F or a-f,
+ returns 0 otherwise
+*/
+static int is_hex (byte c)
+{
+ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
+}
+
+/*
+ returns value of passed character as if it was HEX digit
+*/
+static unsigned int hex2dec (byte c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return c - 'a' + 10;
+}
+
+/*
+ converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
+ advances text pointer past the converted sequence,
+ returns the converted value
+*/
+static unsigned int hex_convert (const byte **text)
+{
+ unsigned int value = 0;
+
+ while (is_hex (**text))
+ {
+ value = value * 0x10 + hex2dec (**text);
+ (*text)++;
+ }
+
+ return value;
+}
+
+/*
+ returns 1 if given character is OCT digit 0-7,
+ returns 0 otherwise
+*/
+static int is_oct (byte c)
+{
+ return c >= '0' && c <= '7';
+}
+
+/*
+ returns value of passed character as if it was OCT digit
+*/
+static int oct2dec (byte c)
+{
+ return c - '0';
+}
+
+static byte get_escape_sequence (const byte **text)
+{
+ int value = 0;
+
+ /* skip '\' character */
+ (*text)++;
+
+ switch (*(*text)++)
+ {
+ case '\'':
+ return '\'';
+ case '"':
+ return '\"';
+ case '?':
+ return '\?';
+ case '\\':
+ return '\\';
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case 'x':
+ return (byte) hex_convert (text);
+ }
+
+ (*text)--;
+ if (is_oct (**text))
+ {
+ value = oct2dec (*(*text)++);
+ if (is_oct (**text))
+ {
+ value = value * 010 + oct2dec (*(*text)++);
+ if (is_oct (**text))
+ value = value * 010 + oct2dec (*(*text)++);
+ }
+ }
+
+ return (byte) value;
+}
+
+/*
+ copies characters from *text to *str until " or ' character is encountered,
+ assumes that *str points to NULL object - caller is responsible for later freeing the string,
+ assumes that *text points to " or ' character that starts the string,
+ text pointer is advanced to point past the " or ' character,
+ returns 0 if string was successfully copied,
+ returns 1 otherwise
+*/
+static int get_string (const byte **text, byte **str)
+{
+ const byte *t = *text;
+ byte *p = NULL;
+ unsigned int len = 0;
+ byte term_char;
+
+ if (string_grow (&p, &len, '\0'))
+ return 1;
+
+ /* read " or ' character that starts the string */
+ term_char = *t++;
+ /* while next character is not the terminating character */
+ while (*t && *t != term_char)
+ {
+ byte c;
+
+ if (*t == '\\')
+ c = get_escape_sequence (&t);
+ else
+ c = *t++;
+
+ if (string_grow (&p, &len, c))
+ {
+ mem_free ((void **) &p);
+ return 1;
+ }
+ }
+ /* skip " or ' character that ends the string */
+ t++;
+
+ *text = t;
+ *str = p;
+ return 0;
+}
+
+/*
+ gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
+ assumes that *text already points to <symbol>,
+ returns 0 if emit code is successfully read,
+ returns 1 otherwise
+*/
+static int get_emtcode (const byte **text, map_byte **ma)
+{
+ const byte *t = *text;
+ map_byte *m = NULL;
+
+ map_byte_create (&m);
+ if (m == NULL)
+ return 1;
+
+ if (get_identifier (&t, &m->key))
+ {
+ map_byte_destroy (&m);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (*t == '\'')
+ {
+ byte *c;
+
+ if (get_string (&t, &c))
+ {
+ map_byte_destroy (&m);
+ return 1;
+ }
+
+ m->data = (byte) c[0];
+ mem_free ((void **) &c);
+ }
+ else
+ {
+ /* skip HEX "0x" or "0X" prefix */
+ t += 2;
+ m->data = (byte) hex_convert (&t);
+ }
+
+ eat_spaces (&t);
+
+ *text = t;
+ *ma = m;
+ return 0;
+}
+
+/*
+ gets regbyte declaration, the syntax is: ".regbyte" " " <symbol> " " ("0x" | "0X") <hex_value>
+ assumes that *text already points to <symbol>,
+ returns 0 if regbyte is successfully read,
+ returns 1 otherwise
+*/
+static int get_regbyte (const byte **text, map_byte **ma)
+{
+ return get_emtcode (text, ma);
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int get_errtext (const byte **text, map_str **ma)
+{
+ const byte *t = *text;
+ map_str *m = NULL;
+
+ map_str_create (&m);
+ if (m == NULL)
+ return 1;
+
+ if (get_identifier (&t, &m->key))
+ {
+ map_str_destroy (&m);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (get_string (&t, &m->data))
+ {
+ map_str_destroy (&m);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ *text = t;
+ *ma = m;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_error (const byte **text, error **er, map_str *maps)
+{
+ const byte *t = *text;
+ byte *temp = NULL;
+
+ if (*t != '.')
+ return 0;
+
+ t++;
+ if (get_identifier (&t, &temp))
+ return 1;
+ eat_spaces (&t);
+
+ if (!str_equal ((byte *) "error", temp))
+ {
+ mem_free ((void **) &temp);
+ return 0;
+ }
+
+ mem_free ((void **) &temp);
+
+ error_create (er);
+ if (*er == NULL)
+ return 1;
+
+ if (*t == '\"')
+ {
+ if (get_string (&t, &(**er).m_text))
+ {
+ error_destroy (er);
+ return 1;
+ }
+ eat_spaces (&t);
+ }
+ else
+ {
+ if (get_identifier (&t, &temp))
+ {
+ error_destroy (er);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (map_str_find (&maps, temp, &(**er).m_text))
+ {
+ mem_free ((void **) &temp);
+ error_destroy (er);
+ return 1;
+ }
+
+ mem_free ((void **) &temp);
+ }
+
+ /* try to extract "token" from "...$token$..." */
+ {
+ byte *processed = NULL;
+ unsigned int len = 0, i = 0;
+
+ if (string_grow (&processed, &len, '\0'))
+ {
+ error_destroy (er);
+ return 1;
+ }
+
+ while (i < str_length ((**er).m_text))
+ {
+ /* check if the dollar sign is repeated - if so skip it */
+ if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$')
+ {
+ if (string_grow (&processed, &len, '$'))
+ {
+ mem_free ((void **) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ i += 2;
+ }
+ else if ((**er).m_text[i] != '$')
+ {
+ if (string_grow (&processed, &len, (**er).m_text[i]))
+ {
+ mem_free ((void **) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ i++;
+ }
+ else
+ {
+ if (string_grow (&processed, &len, '$'))
+ {
+ mem_free ((void **) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ {
+ /* length of token being extracted */
+ unsigned int tlen = 0;
+
+ if (string_grow (&(**er).m_token_name, &tlen, '\0'))
+ {
+ mem_free ((void **) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ /* skip the dollar sign */
+ i++;
+
+ while ((**er).m_text[i] != '$')
+ {
+ if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i]))
+ {
+ mem_free ((void **) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ i++;
+ }
+
+ /* skip the dollar sign */
+ i++;
+ }
+ }
+ }
+
+ mem_free ((void **) &(**er).m_text);
+ (**er).m_text = processed;
+ }
+
+ *text = t;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_emits (const byte **text, emit **em, map_byte *mapb)
+{
+ const byte *t = *text;
+ byte *temp = NULL;
+ emit *e = NULL;
+ emit_dest dest;
+
+ if (*t != '.')
+ return 0;
+
+ t++;
+ if (get_identifier (&t, &temp))
+ return 1;
+ eat_spaces (&t);
+
+ /* .emit */
+ if (str_equal ((byte *) "emit", temp))
+ dest = ed_output;
+ /* .load */
+ else if (str_equal ((byte *) "load", temp))
+ dest = ed_regbyte;
+ else
+ {
+ mem_free ((void **) &temp);
+ return 0;
+ }
+
+ mem_free ((void **) &temp);
+
+ emit_create (&e);
+ if (e == NULL)
+ return 1;
+
+ e->m_emit_dest = dest;
+
+ if (dest == ed_regbyte)
+ {
+ if (get_identifier (&t, &e->m_regname))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+ eat_spaces (&t);
+ }
+
+ /* 0xNN */
+ if (*t == '0')
+ {
+ t += 2;
+ e->m_byte = (byte) hex_convert (&t);
+
+ e->m_emit_type = et_byte;
+ }
+ /* * */
+ else if (*t == '*')
+ {
+ t++;
+
+ e->m_emit_type = et_stream;
+ }
+ /* $ */
+ else if (*t == '$')
+ {
+ t++;
+
+ e->m_emit_type = et_position;
+ }
+ /* 'c' */
+ else if (*t == '\'')
+ {
+ if (get_string (&t, &temp))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+ e->m_byte = (byte) temp[0];
+
+ mem_free ((void **) &temp);
+
+ e->m_emit_type = et_byte;
+ }
+ else
+ {
+ if (get_identifier (&t, &temp))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+
+ if (map_byte_find (&mapb, temp, &e->m_byte))
+ {
+ mem_free ((void **) &temp);
+ emit_destroy (&e);
+ return 1;
+ }
+
+ mem_free ((void **) &temp);
+
+ e->m_emit_type = et_byte;
+ }
+
+ eat_spaces (&t);
+
+ if (get_emits (&t, &e->m_next, mapb))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+
+ *text = t;
+ *em = e;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb)
+{
+ const byte *t = *text;
+ spec *s = NULL;
+
+ spec_create (&s);
+ if (s == NULL)
+ return 1;
+
+ /* first - read optional .if statement */
+ if (*t == '.')
+ {
+ const byte *u = t;
+ byte *keyword = NULL;
+
+ /* skip the dot */
+ u++;
+
+ if (get_identifier (&u, &keyword))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ /* .if */
+ if (str_equal ((byte *) "if", keyword))
+ {
+ cond_create (&s->m_cond);
+ if (s->m_cond == NULL)
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ /* skip the left paren */
+ eat_spaces (&u);
+ u++;
+
+ /* get the left operand */
+ eat_spaces (&u);
+ if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ s->m_cond->m_operands[0].m_type = cot_regbyte;
+
+ /* get the operator (!= or ==) */
+ eat_spaces (&u);
+ if (*u == '!')
+ s->m_cond->m_type = ct_not_equal;
+ else
+ s->m_cond->m_type = ct_equal;
+ u += 2;
+
+ /* skip the 0x prefix */
+ eat_spaces (&u);
+ u += 2;
+
+ /* get the right operand */
+ s->m_cond->m_operands[1].m_byte = hex_convert (&u);
+ s->m_cond->m_operands[1].m_type = cot_byte;
+
+ /* skip the right paren */
+ eat_spaces (&u);
+ u++;
+
+ eat_spaces (&u);
+
+ t = u;
+ }
+
+ mem_free ((void **) &keyword);
+ }
+
+ if (*t == '\'')
+ {
+ byte *temp = NULL;
+
+ if (get_string (&t, &temp))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (*t == '-')
+ {
+ byte *temp2 = NULL;
+
+ /* skip the '-' character */
+ t++;
+ eat_spaces (&t);
+
+ if (get_string (&t, &temp2))
+ {
+ mem_free ((void **) &temp);
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_byte_range;
+ s->m_byte[0] = *temp;
+ s->m_byte[1] = *temp2;
+
+ mem_free ((void **) &temp2);
+ }
+ else
+ {
+ s->m_spec_type = st_byte;
+ *s->m_byte = *temp;
+ }
+
+ mem_free ((void **) &temp);
+ }
+ else if (*t == '"')
+ {
+ if (get_string (&t, &s->m_string))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_string;
+ }
+ else if (*t == '.')
+ {
+ byte *keyword = NULL;
+
+ /* skip the dot */
+ t++;
+
+ if (get_identifier (&t, &keyword))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ /* .true */
+ if (str_equal ((byte *) "true", keyword))
+ {
+ s->m_spec_type = st_true;
+ }
+ /* .false */
+ else if (str_equal ((byte *) "false", keyword))
+ {
+ s->m_spec_type = st_false;
+ }
+ /* .debug */
+ else if (str_equal ((byte *) "debug", keyword))
+ {
+ s->m_spec_type = st_debug;
+ }
+ /* .loop */
+ else if (str_equal ((byte *) "loop", keyword))
+ {
+ if (get_identifier (&t, &s->m_string))
+ {
+ mem_free ((void **) &keyword);
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_identifier_loop;
+ }
+
+ mem_free ((void **) &keyword);
+ }
+ else
+ {
+ if (get_identifier (&t, &s->m_string))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_identifier;
+ }
+
+ if (get_error (&t, &s->m_errtext, maps))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ if (get_emits (&t, &s->m_emits, mapb))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ *text = t;
+ *sp = s;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)
+{
+ const byte *t = *text;
+ rule *r = NULL;
+
+ rule_create (&r);
+ if (r == NULL)
+ return 1;
+
+ if (get_spec (&t, &r->m_specs, maps, mapb))
+ {
+ rule_destroy (&r);
+ return 1;
+ }
+
+ while (*t != ';')
+ {
+ byte *op = NULL;
+ spec *sp = NULL;
+
+ /* skip the dot that precedes "and" or "or" */
+ t++;
+
+ /* read "and" or "or" keyword */
+ if (get_identifier (&t, &op))
+ {
+ rule_destroy (&r);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (r->m_oper == op_none)
+ {
+ /* .and */
+ if (str_equal ((byte *) "and", op))
+ r->m_oper = op_and;
+ /* .or */
+ else
+ r->m_oper = op_or;
+ }
+
+ mem_free ((void **) &op);
+
+ if (get_spec (&t, &sp, maps, mapb))
+ {
+ rule_destroy (&r);
+ return 1;
+ }
+
+ spec_append (&r->m_specs, &sp);
+ }
+
+ /* skip the semicolon */
+ t++;
+ eat_spaces (&t);
+
+ *text = t;
+ *ru = r;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)
+{
+ if (map_rule_find (&mapr, symbol, ru))
+ return 1;
+
+/* (**ru).m_referenced = 1; */
+
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,
+ byte **string_symbol, map_byte *regbytes)
+{
+ rule *rulez = di->m_rulez;
+
+ /* update dependecies for the root and lexer symbols */
+ if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||
+ (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))
+ return 1;
+
+ mem_free ((void **) syntax_symbol);
+ mem_free ((void **) string_symbol);
+
+ /* update dependecies for the rest of the rules */
+ while (rulez)
+ {
+ spec *sp = rulez->m_specs;
+
+ /* iterate through all the specifiers */
+ while (sp)
+ {
+ /* update dependency for identifier */
+ if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)
+ {
+ if (update_dependency (mapr, sp->m_string, &sp->m_rule))
+ return 1;
+
+ mem_free ((void **) &sp->m_string);
+ }
+
+ /* some errtexts reference to a rule */
+ if (sp->m_errtext && sp->m_errtext->m_token_name)
+ {
+ if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))
+ return 1;
+
+ mem_free ((void **) &sp->m_errtext->m_token_name);
+ }
+
+ /* update dependency for condition */
+ if (sp->m_cond)
+ {
+ int i;
+ for (i = 0; i < 2; i++)
+ if (sp->m_cond->m_operands[i].m_type == cot_regbyte)
+ {
+ sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (&regbytes,
+ sp->m_cond->m_operands[i].m_regname);
+
+ if (sp->m_cond->m_operands[i].m_regbyte == NULL)
+ return 1;
+
+ mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);
+ }
+ }
+
+ /* update dependency for all .load instructions */
+ if (sp->m_emits)
+ {
+ emit *em = sp->m_emits;
+ while (em != NULL)
+ {
+ if (em->m_emit_dest == ed_regbyte)
+ {
+ em->m_regbyte = map_byte_locate (&regbytes, em->m_regname);
+
+ if (em->m_regbyte == NULL)
+ return 1;
+
+ mem_free ((void **) &em->m_regname);
+ }
+
+ em = em->m_next;
+ }
+ }
+
+ sp = sp->m_next;
+ }
+
+ rulez = rulez->m_next;
+ }
+
+/* check for unreferenced symbols */
+/* de = di->m_defntns;
+ while (de)
+ {
+ if (!de->m_referenced)
+ {
+ map_def *ma = mapd;
+ while (ma)
+ {
+ if (ma->data == de)
+ {
+ assert (0);
+ break;
+ }
+ ma = ma->next;
+ }
+ }
+ de = de->m_next;
+ }
+*/
+ return 0;
+}
+
+static int satisfies_condition (cond *co, regbyte_ctx *ctx)
+{
+ byte values[2];
+ int i;
+
+ if (co == NULL)
+ return 1;
+
+ for (i = 0; i < 2; i++)
+ switch (co->m_operands[i].m_type)
+ {
+ case cot_byte:
+ values[i] = co->m_operands[i].m_byte;
+ break;
+ case cot_regbyte:
+ values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);
+ break;
+ }
+
+ switch (co->m_type)
+ {
+ case ct_equal:
+ return values[0] == values[1];
+ case ct_not_equal:
+ return values[0] != values[1];
+ }
+
+ return 0;
+}
+
+static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)
+{
+ while (top != limit)
+ {
+ regbyte_ctx *rbc = top->m_prev;
+ regbyte_ctx_destroy (&top);
+ top = rbc;
+ }
+}
+
+typedef enum match_result_
+{
+ mr_not_matched, /* the examined string does not match */
+ mr_matched, /* the examined string matches */
+ mr_error_raised, /* mr_not_matched + error has been raised */
+ mr_dont_emit, /* used by identifier loops only */
+ mr_internal_error /* an internal error has occured such as out of memory */
+} match_result;
+
+/*
+ This function does the main job. It parses the text and generates output data.
+
+ XXX optimize it - the barray seems to be the bottleneck
+*/
+static match_result match (dict *di, const byte *text, unsigned int *index, rule *ru, barray **ba,
+ int filtering_string, regbyte_ctx **rbc)
+{
+ unsigned int ind = *index;
+ match_result status = mr_not_matched;
+ spec *sp = ru->m_specs;
+ regbyte_ctx *ctx = *rbc;
+
+ /* for every specifier in the rule */
+ while (sp)
+ {
+ unsigned int i, len, save_ind = ind;
+ barray *array = NULL;
+
+ if (satisfies_condition (sp->m_cond, ctx))
+ {
+ switch (sp->m_spec_type)
+ {
+ case st_identifier:
+ barray_create (&array);
+ if (array == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
+ if (status == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ break;
+ case st_string:
+ len = str_length (sp->m_string);
+
+ /* prefilter the stream */
+ if (!filtering_string && di->m_string)
+ {
+ barray *ba;
+ unsigned int filter_index = 0;
+ match_result result;
+ regbyte_ctx *null_ctx = NULL;
+
+ barray_create (&ba);
+ if (ba == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);
+
+ if (result == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&ba);
+ return mr_internal_error;
+ }
+
+ if (result != mr_matched)
+ {
+ barray_destroy (&ba);
+ status = mr_not_matched;
+ break;
+ }
+
+ barray_destroy (&ba);
+
+ if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))
+ {
+ status = mr_not_matched;
+ break;
+ }
+
+ status = mr_matched;
+ ind += len;
+ }
+ else
+ {
+ status = mr_matched;
+ for (i = 0; status == mr_matched && i < len; i++)
+ if (text[ind + i] != sp->m_string[i])
+ status = mr_not_matched;
+ if (status == mr_matched)
+ ind += len;
+ }
+ break;
+ case st_byte:
+ status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
+ if (status == mr_matched)
+ ind++;
+ break;
+ case st_byte_range:
+ status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?
+ mr_matched : mr_not_matched;
+ if (status == mr_matched)
+ ind++;
+ break;
+ case st_true:
+ status = mr_matched;
+ break;
+ case st_false:
+ status = mr_not_matched;
+ break;
+ case st_debug:
+ status = ru->m_oper == op_and ? mr_matched : mr_not_matched;
+ break;
+ case st_identifier_loop:
+ barray_create (&array);
+ if (array == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ status = mr_dont_emit;
+ for (;;)
+ {
+ match_result result;
+
+ save_ind = ind;
+ result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
+
+ if (result == mr_error_raised)
+ {
+ status = result;
+ break;
+ }
+ else if (result == mr_matched)
+ {
+ if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||
+ barray_append (ba, &array))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ barray_destroy (&array);
+ barray_create (&array);
+ if (array == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+ }
+ else if (result == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ else
+ break;
+ }
+ break;
+ }
+ }
+ else
+ {
+ status = mr_not_matched;
+ }
+
+ if (status == mr_error_raised)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+
+ return mr_error_raised;
+ }
+
+ if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+
+ if (sp->m_errtext)
+ {
+ set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,
+ ind), ind);
+
+ return mr_error_raised;
+ }
+
+ return mr_not_matched;
+ }
+
+ if (status == mr_matched)
+ {
+ if (sp->m_emits)
+ if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+
+ if (array)
+ if (barray_append (ba, &array))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ }
+
+ barray_destroy (&array);
+
+ /* if the rule operator is a logical or, we pick up the first matching specifier */
+ if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))
+ {
+ *index = ind;
+ *rbc = ctx;
+ return mr_matched;
+ }
+
+ sp = sp->m_next;
+ }
+
+ /* everything went fine - all specifiers match up */
+ if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))
+ {
+ *index = ind;
+ *rbc = ctx;
+ return mr_matched;
+ }
+
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_not_matched;
+}
+
+static byte *error_get_token (error *er, dict *di, const byte *text, unsigned int ind)
+{
+ byte *str = NULL;
+
+ if (er->m_token)
+ {
+ barray *ba;
+ unsigned int filter_index = 0;
+ regbyte_ctx *ctx = NULL;
+
+ barray_create (&ba);
+ if (ba != NULL)
+ {
+ if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched &&
+ filter_index)
+ {
+ str = mem_alloc (filter_index + 1);
+ if (str != NULL)
+ {
+ str_copy_n (str, text + ind, filter_index);
+ str[filter_index] = '\0';
+ }
+ }
+ barray_destroy (&ba);
+ }
+ }
+
+ return str;
+}
+
+typedef struct grammar_load_state_
+{
+ dict *di;
+ byte *syntax_symbol;
+ byte *string_symbol;
+ map_str *maps;
+ map_byte *mapb;
+ map_rule *mapr;
+} grammar_load_state;
+
+static void grammar_load_state_create (grammar_load_state **gr)
+{
+ *gr = mem_alloc (sizeof (grammar_load_state));
+ if (*gr)
+ {
+ (**gr).di = NULL;
+ (**gr).syntax_symbol = NULL;
+ (**gr).string_symbol = NULL;
+ (**gr).maps = NULL;
+ (**gr).mapb = NULL;
+ (**gr).mapr = NULL;
+ }
+}
+
+static void grammar_load_state_destroy (grammar_load_state **gr)
+{
+ if (*gr)
+ {
+ dict_destroy (&(**gr).di);
+ mem_free ((void **) &(**gr).syntax_symbol);
+ mem_free ((void **) &(**gr).string_symbol);
+ map_str_destroy (&(**gr).maps);
+ map_byte_destroy (&(**gr).mapb);
+ map_rule_destroy (&(**gr).mapr);
+ mem_free ((void **) gr);
+ }
+}
+
+/*
+ the API
+*/
+
+grammar grammar_load_from_text (const byte *text)
+{
+ grammar_load_state *g = NULL;
+ grammar id = 0;
+
+ clear_last_error ();
+
+ grammar_load_state_create (&g);
+ if (g == NULL)
+ return 0;
+
+ dict_create (&g->di);
+ if (g->di == NULL)
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ eat_spaces (&text);
+
+ /* skip ".syntax" keyword */
+ text += 7;
+ eat_spaces (&text);
+
+ /* retrieve root symbol */
+ if (get_identifier (&text, &g->syntax_symbol))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+ eat_spaces (&text);
+
+ /* skip semicolon */
+ text++;
+ eat_spaces (&text);
+
+ while (*text)
+ {
+ byte *symbol = NULL;
+ int is_dot = *text == '.';
+
+ if (is_dot)
+ text++;
+
+ if (get_identifier (&text, &symbol))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+ eat_spaces (&text);
+
+ /* .emtcode */
+ if (is_dot && str_equal (symbol, (byte *) "emtcode"))
+ {
+ map_byte *ma = NULL;
+
+ mem_free ((void **) &symbol);
+
+ if (get_emtcode (&text, &ma))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ map_byte_append (&g->mapb, &ma);
+ }
+ /* .regbyte */
+ else if (is_dot && str_equal (symbol, (byte *) "regbyte"))
+ {
+ map_byte *ma = NULL;
+
+ mem_free ((void **) &symbol);
+
+ if (get_regbyte (&text, &ma))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ map_byte_append (&g->di->m_regbytes, &ma);
+ }
+ /* .errtext */
+ else if (is_dot && str_equal (symbol, (byte *) "errtext"))
+ {
+ map_str *ma = NULL;
+
+ mem_free ((void **) &symbol);
+
+ if (get_errtext (&text, &ma))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ map_str_append (&g->maps, &ma);
+ }
+ /* .string */
+ else if (is_dot && str_equal (symbol, (byte *) "string"))
+ {
+ mem_free ((void **) &symbol);
+
+ if (g->di->m_string != NULL)
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ if (get_identifier (&text, &g->string_symbol))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ /* skip semicolon */
+ eat_spaces (&text);
+ text++;
+ eat_spaces (&text);
+ }
+ else
+ {
+ rule *ru = NULL;
+ map_rule *ma = NULL;
+
+ if (get_rule (&text, &ru, g->maps, g->mapb))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ rule_append (&g->di->m_rulez, &ru);
+
+ /* if a rule consist of only one specifier, give it an ".and" operator */
+ if (ru->m_oper == op_none)
+ ru->m_oper = op_and;
+
+ map_rule_create (&ma);
+ if (ma == NULL)
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ ma->key = symbol;
+ ma->data = ru;
+ map_rule_append (&g->mapr, &ma);
+ }
+ }
+
+ if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol,
+ g->di->m_regbytes))
+ {
+ grammar_load_state_destroy (&g);
+ return 0;
+ }
+
+ dict_append (&g_dicts, &g->di);
+ id = g->di->m_id;
+ g->di = NULL;
+
+ grammar_load_state_destroy (&g);
+
+ return id;
+}
+
+int grammar_set_reg8 (grammar id, const byte *name, byte value)
+{
+ dict *di = NULL;
+ map_byte *reg = NULL;
+
+ clear_last_error ();
+
+ dict_find (&g_dicts, id, &di);
+ if (di == NULL)
+ {
+ set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+ return 0;
+ }
+
+ reg = map_byte_locate (&di->m_regbytes, name);
+ if (reg == NULL)
+ {
+ set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1);
+ return 0;
+ }
+
+ reg->data = value;
+ return 1;
+}
+
+int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size)
+{
+ dict *di = NULL;
+ barray *ba = NULL;
+ unsigned int index = 0;
+ regbyte_ctx *rbc = NULL;
+
+ clear_last_error ();
+
+ dict_find (&g_dicts, id, &di);
+ if (di == NULL)
+ {
+ set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+ return 0;
+ }
+
+ barray_create (&ba);
+ if (ba == NULL)
+ return 0;
+
+ *prod = NULL;
+ *size = 0;
+
+ if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched)
+ {
+ barray_destroy (&ba);
+ free_regbyte_ctx_stack (rbc, NULL);
+ return 0;
+ }
+
+ free_regbyte_ctx_stack (rbc, NULL);
+
+ *prod = mem_alloc (ba->len * sizeof (byte));
+ if (*prod == NULL)
+ {
+ barray_destroy (&ba);
+ return 0;
+ }
+
+ mem_copy (*prod, ba->data, ba->len * sizeof (byte));
+ *size = ba->len;
+ barray_destroy (&ba);
+
+ return 1;
+}
+
+int grammar_destroy (grammar id)
+{
+ dict **di = &g_dicts;
+
+ clear_last_error ();
+
+ while (*di != NULL)
+ {
+ if ((**di).m_id == id)
+ {
+ dict *tmp = *di;
+ *di = (**di).m_next;
+ dict_destroy (&tmp);
+ return 1;
+ }
+
+ di = &(**di).m_next;
+ }
+
+ set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+ return 0;
+}
+
+void grammar_get_last_error (byte *text, unsigned int size, int *pos)
+{
+ unsigned int len = 0, dots_made = 0;
+ const byte *p = error_message;
+
+ *text = '\0';
+
+#define APPEND_CHARACTER(x) if (dots_made == 0) {\
+ if (len < size - 1) {\
+ text[len++] = (x); text[len] = '\0';\
+ } else {\
+ int i;\
+ for (i = 0; i < 3; i++)\
+ if (--len >= 0)\
+ text[len] = '.';\
+ dots_made = 1;\
+ }\
+ }
+
+ if (p)
+ while (*p)
+ if (*p == '$')
+ {
+ const byte *r = error_param;
+
+ while (*r)
+ {
+ APPEND_CHARACTER(*r)
+ r++;
+ }
+
+ p++;
+ }
+ else
+ {
+ APPEND_CHARACTER(*p)
+ p++;
+ }
+
+ *pos = error_position;
+
+#undef APPEND_CHARACTER
+
+}
+
diff --git a/src/mesa/shader/grammar.h b/src/mesa/shader/grammar.h
index 152ebc1086a..41a484e69c5 100644
--- a/src/mesa/shader/grammar.h
+++ b/src/mesa/shader/grammar.h
@@ -1,68 +1,92 @@
-#ifndef GRAMMAR_H
-#define GRAMMAR_H
-
-
-#ifndef GRAMMAR_PORT_INCLUDE
-#error Do not include this file directly, include your grammar_XXX.h instead
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void grammar_alloc_free (void *);
-void *grammar_alloc_malloc (unsigned int);
-void *grammar_alloc_realloc (void *, unsigned int, unsigned int);
-void *grammar_memory_copy (void *, const void *, unsigned int);
-int grammar_string_compare (const byte *, const byte *);
-int grammar_string_compare_n (const byte *, const byte *, unsigned int);
-byte *grammar_string_copy (byte *, const byte *);
-byte *grammar_string_copy_n (byte *, const byte *, unsigned int);
-byte *grammar_string_duplicate (const byte *);
-unsigned int grammar_string_length (const byte *);
-
-/*
- loads grammar script from null-terminated ASCII <text>
- returns unique grammar id to grammar object
- returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text)
-*/
-grammar grammar_load_from_text (const byte *text);
-
-/*
- sets a new <value> to a register <name> for grammar <id>
- returns 0 on error (call grammar_get_last_error to retrieve the error text)
- returns 1 on success
-*/
-int grammar_set_reg8 (grammar id, const byte *name, byte value);
-
-/*
- checks if a null-terminated <text> matches given grammar <id>
- returns 0 on error (call grammar_get_last_error to retrieve the error text)
- returns 1 on success, the <prod> points to newly allocated buffer with production and <size>
- is filled with the production size
- call grammar_alloc_free to free the memory block pointed by <prod>
-*/
-int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size);
-
-/*
- destroys grammar object identified by <id>
- returns 0 on error (call grammar_get_last_error to retrieve the error text)
- returns 1 on success
-*/
-int grammar_destroy (grammar id);
-
-/*
- retrieves last grammar error reported either by grammar_load_from_text, grammar_check
- or grammar_destroy
- the user allocated <text> buffer receives error description, <pos> points to error position,
- <size> is the size of the text buffer to fill in - it must be at least 4 bytes long,
-*/
-void grammar_get_last_error (byte *text, unsigned int size, int *pos);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+#ifndef GRAMMAR_H
+#define GRAMMAR_H
+
+
+#ifndef GRAMMAR_PORT_INCLUDE
+#error Do not include this file directly, include your grammar_XXX.h instead
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grammar_alloc_free (void *);
+void *grammar_alloc_malloc (unsigned int);
+void *grammar_alloc_realloc (void *, unsigned int, unsigned int);
+void *grammar_memory_copy (void *, const void *, unsigned int);
+int grammar_string_compare (const byte *, const byte *);
+int grammar_string_compare_n (const byte *, const byte *, unsigned int);
+byte *grammar_string_copy (byte *, const byte *);
+byte *grammar_string_copy_n (byte *, const byte *, unsigned int);
+byte *grammar_string_duplicate (const byte *);
+unsigned int grammar_string_length (const byte *);
+
+/*
+ loads grammar script from null-terminated ASCII <text>
+ returns unique grammar id to grammar object
+ returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text)
+*/
+grammar grammar_load_from_text (const byte *text);
+
+/*
+ sets a new <value> to a register <name> for grammar <id>
+ returns 0 on error (call grammar_get_last_error to retrieve the error text)
+ returns 1 on success
+*/
+int grammar_set_reg8 (grammar id, const byte *name, byte value);
+
+/*
+ checks if a null-terminated <text> matches given grammar <id>
+ returns 0 on error (call grammar_get_last_error to retrieve the error text)
+ returns 1 on success, the <prod> points to newly allocated buffer with production and <size>
+ is filled with the production size
+ call grammar_alloc_free to free the memory block pointed by <prod>
+*/
+int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size);
+
+/*
+ destroys grammar object identified by <id>
+ returns 0 on error (call grammar_get_last_error to retrieve the error text)
+ returns 1 on success
+*/
+int grammar_destroy (grammar id);
+
+/*
+ retrieves last grammar error reported either by grammar_load_from_text, grammar_check
+ or grammar_destroy
+ the user allocated <text> buffer receives error description, <pos> points to error position,
+ <size> is the size of the text buffer to fill in - it must be at least 4 bytes long,
+*/
+void grammar_get_last_error (byte *text, unsigned int size, int *pos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/mesa/shader/grammar_mesa.c b/src/mesa/shader/grammar_mesa.c
index b9cb17fc382..0aadac58bc5 100644
--- a/src/mesa/shader/grammar_mesa.c
+++ b/src/mesa/shader/grammar_mesa.c
@@ -1,57 +1,87 @@
-#include "grammar_mesa.h"
-
-#define GRAMMAR_PORT_BUILD 1
-#include "grammar.c"
-#undef GRAMMAR_PORT_BUILD
-
-
-void grammar_alloc_free (void *ptr)
-{
- _mesa_free (ptr);
-}
-
-void *grammar_alloc_malloc (unsigned int size)
-{
- return _mesa_malloc (size);
-}
-
-void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size)
-{
- return _mesa_realloc (ptr, old_size, size);
-}
-
-void *grammar_memory_copy (void *dst, const void * src, unsigned int size)
-{
- return _mesa_memcpy (dst, src, size);
-}
-
-int grammar_string_compare (const byte *str1, const byte *str2)
-{
- return _mesa_strcmp ((const char *) str1, (const char *) str2);
-}
-
-int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n)
-{
- return _mesa_strncmp ((const char *) str1, (const char *) str2, n);
-}
-
-byte *grammar_string_copy (byte *dst, const byte *src)
-{
- return (byte *) _mesa_strcpy ((char *) dst, (const char *) src);
-}
-
-byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n)
-{
- return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n);
-}
-
-byte *grammar_string_duplicate (const byte *src)
-{
- return (byte *) _mesa_strdup ((const char *) src);
-}
-
-unsigned int grammar_string_length (const byte *str)
-{
- return _mesa_strlen ((const char *) str);
-}
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * \file grammar_mesa.c
+ * mesa3d port to syntax parsing engine
+ * \author Michal Krol
+ */
+
+#include "grammar_mesa.h"
+
+#define GRAMMAR_PORT_BUILD 1
+#include "grammar.c"
+#undef GRAMMAR_PORT_BUILD
+
+
+void grammar_alloc_free (void *ptr)
+{
+ _mesa_free (ptr);
+}
+
+void *grammar_alloc_malloc (unsigned int size)
+{
+ return _mesa_malloc (size);
+}
+
+void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size)
+{
+ return _mesa_realloc (ptr, old_size, size);
+}
+
+void *grammar_memory_copy (void *dst, const void * src, unsigned int size)
+{
+ return _mesa_memcpy (dst, src, size);
+}
+
+int grammar_string_compare (const byte *str1, const byte *str2)
+{
+ return _mesa_strcmp ((const char *) str1, (const char *) str2);
+}
+
+int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n)
+{
+ return _mesa_strncmp ((const char *) str1, (const char *) str2, n);
+}
+
+byte *grammar_string_copy (byte *dst, const byte *src)
+{
+ return (byte *) _mesa_strcpy ((char *) dst, (const char *) src);
+}
+
+byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n)
+{
+ return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n);
+}
+
+byte *grammar_string_duplicate (const byte *src)
+{
+ return (byte *) _mesa_strdup ((const char *) src);
+}
+
+unsigned int grammar_string_length (const byte *str)
+{
+ return _mesa_strlen ((const char *) str);
+}
+
diff --git a/src/mesa/shader/grammar_mesa.h b/src/mesa/shader/grammar_mesa.h
index 77a8804636e..c14033a9d45 100644
--- a/src/mesa/shader/grammar_mesa.h
+++ b/src/mesa/shader/grammar_mesa.h
@@ -1,19 +1,43 @@
-#ifndef GRAMMAR_MESA_H
-#define GRAMMAR_MESA_H
-
-
-#include "imports.h"
-/* NOTE: include Mesa 3-D specific headers here */
-
-
-typedef GLuint grammar;
-typedef GLubyte byte;
-
-
-#define GRAMMAR_PORT_INCLUDE 1
-#include "grammar.h"
-#undef GRAMMAR_PORT_INCLUDE
-
-
-#endif
-
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+#ifndef GRAMMAR_MESA_H
+#define GRAMMAR_MESA_H
+
+
+#include "imports.h"
+/* NOTE: include Mesa 3-D specific headers here */
+
+
+typedef GLuint grammar;
+typedef GLubyte byte;
+
+
+#define GRAMMAR_PORT_INCLUDE 1
+#include "grammar.h"
+#undef GRAMMAR_PORT_INCLUDE
+
+
+#endif
+
diff --git a/src/mesa/shader/grammar_syn.h b/src/mesa/shader/grammar_syn.h
index 766196ad3fd..9c3419ece82 100644
--- a/src/mesa/shader/grammar_syn.h
+++ b/src/mesa/shader/grammar_syn.h
@@ -1,196 +1,226 @@
-".syntax grammar;\n"
-".emtcode DECLARATION_END 0x00\n"
-".emtcode DECLARATION_EMITCODE 0x01\n"
-".emtcode DECLARATION_ERRORTEXT 0x02\n"
-".emtcode DECLARATION_REGBYTE 0x03\n"
-".emtcode DECLARATION_LEXER 0x04\n"
-".emtcode DECLARATION_RULE 0x05\n"
-".emtcode SPECIFIER_END 0x00\n"
-".emtcode SPECIFIER_AND_TAG 0x01\n"
-".emtcode SPECIFIER_OR_TAG 0x02\n"
-".emtcode SPECIFIER_CHARACTER_RANGE 0x03\n"
-".emtcode SPECIFIER_CHARACTER 0x04\n"
-".emtcode SPECIFIER_STRING 0x05\n"
-".emtcode SPECIFIER_IDENTIFIER 0x06\n"
-".emtcode SPECIFIER_TRUE 0x07\n"
-".emtcode SPECIFIER_FALSE 0x08\n"
-".emtcode SPECIFIER_DEBUG 0x09\n"
-".emtcode IDENTIFIER_NO_LOOP 0x00\n"
-".emtcode IDENTIFIER_LOOP 0x01\n"
-".emtcode ERROR_NOT_PRESENT 0x00\n"
-".emtcode ERROR_PRESENT 0x01\n"
-".emtcode EMIT_NULL 0x00\n"
-".emtcode EMIT_INTEGER 0x01\n"
-".emtcode EMIT_IDENTIFIER 0x02\n"
-".emtcode EMIT_CHARACTER 0x03\n"
-".emtcode EMIT_LAST_CHARACTER 0x04\n"
-".emtcode EMIT_CURRENT_POSITION 0x05\n"
-".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n"
-".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n"
-".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n"
-".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n"
-".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n"
-".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n"
-"grammar\n"
-" grammar_1 .error INVALID_GRAMMAR;\n"
-"grammar_1\n"
-" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n"
-" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n"
-"optional_space\n"
-" space .or .true;\n"
-"space\n"
-" single_space .and .loop single_space;\n"
-"single_space\n"
-" white_char .or comment_block;\n"
-"white_char\n"
-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
-"comment_block\n"
-" '/' .and '*' .and .loop comment_char .and '*' .and '/';\n"
-"comment_char\n"
-" comment_char_no_star .or comment_char_1;\n"
-"comment_char_1\n"
-" '*' .and comment_char_no_slash;\n"
-"comment_char_no_star\n"
-" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
-"comment_char_no_slash\n"
-" '\\x30'-'\\xFF' .or '\\x01'-'\\x2E';\n"
-"identifier\n"
-" identifier_ne .error IDENTIFIER_EXPECTED;\n"
-"identifier_ne\n"
-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n"
-"first_idchar\n"
-" 'a'-'z' .or 'A'-'Z' .or '_';\n"
-"follow_idchar\n"
-" first_idchar .or digit_dec;\n"
-"digit_dec\n"
-" '0'-'9';\n"
-"semicolon\n"
-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
-"declaration_list\n"
-" declaration .and .loop declaration;\n"
-"declaration\n"
-" emitcode_definition .emit DECLARATION_EMITCODE .or\n"
-" errortext_definition .emit DECLARATION_ERRORTEXT .or\n"
-" regbyte_definition .emit DECLARATION_REGBYTE .or\n"
-" lexer_definition .emit DECLARATION_LEXER .or\n"
-" rule_definition .emit DECLARATION_RULE;\n"
-"emitcode_definition\n"
-" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n"
-"integer\n"
-" integer_ne .error INTEGER_EXPECTED;\n"
-"integer_ne\n"
-" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n"
-"hex_prefix\n"
-" '0' .and hex_prefix_1;\n"
-"hex_prefix_1\n"
-" 'x' .or 'X';\n"
-"digit_hex\n"
-" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n"
-"space_or_null\n"
-" space .or '\\0';\n"
-"errortext_definition\n"
-" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n"
-"string\n"
-" string_ne .error STRING_EXPECTED;\n"
-"string_ne\n"
-" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n"
-"string_char_double_quotes\n"
-" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n"
-"string_char\n"
-" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n"
-" '\\x01'-'\\x09';\n"
-"escape_sequence\n"
-" '\\\\' .emit * .and escape_code;\n"
-"escape_code\n"
-" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n"
-"simple_escape_code\n"
-" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n"
-"hex_escape_code\n"
-" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n"
-"oct_escape_code\n"
-" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n"
-"digit_oct\n"
-" '0'-'7';\n"
-"optional_digit_oct\n"
-" digit_oct .emit * .or .true;\n"
-"regbyte_definition\n"
-" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n"
-"lexer_definition\n"
-" \".string\" .and space .and identifier .and semicolon;\n"
-"rule_definition\n"
-" identifier_ne .and space .and definition;\n"
-"definition\n"
-" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n"
-"optional_specifiers_and_or\n"
-" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n"
-"specifier\n"
-" specifier_condition .and optional_space .and specifier_rule;\n"
-"specifier_condition\n"
-" specifier_condition_1 .or .true;\n"
-"specifier_condition_1\n"
-" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n"
-" right_operand .and optional_space .and ')';\n"
-"left_operand\n"
-" identifier;\n"
-"operator\n"
-" operator_1 .or operator_2;\n"
-"operator_1\n"
-" optional_space .and '!' .and '=' .and optional_space;\n"
-"operator_2\n"
-" optional_space .and '=' .and '=' .and optional_space;\n"
-"right_operand\n"
-" integer;\n"
-"specifier_rule\n"
-" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n"
-"specifier_rule_1\n"
-" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n"
-" character .emit SPECIFIER_CHARACTER .or\n"
-" string_ne .emit SPECIFIER_STRING .or\n"
-" \".true\" .emit SPECIFIER_TRUE .or\n"
-" \".false\" .emit SPECIFIER_FALSE .or\n"
-" \".debug\" .emit SPECIFIER_DEBUG .or\n"
-" loop_identifier .emit SPECIFIER_IDENTIFIER;\n"
-"character\n"
-" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n"
-"string_char_single_quotes\n"
-" escape_sequence .or string_char .emit * .or '\"' .emit *;\n"
-"character_range\n"
-" character .and optional_space .and '-' .and optional_space .and character;\n"
-"loop_identifier\n"
-" optional_loop .and identifier;\n"
-"optional_loop\n"
-" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_NO_LOOP;\n"
-"optional_loop_1\n"
-" \".loop\" .and space;\n"
-"optional_error\n"
-" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n"
-"error\n"
-" space .and \".error\" .and space .and identifier;\n"
-"emit\n"
-" emit_output .or emit_regbyte;\n"
-"emit_output\n"
-" space .and \".emit\" .and space .and emit_param;\n"
-"emit_param\n"
-" integer_ne .emit EMIT_INTEGER .or\n"
-" identifier_ne .emit EMIT_IDENTIFIER .or\n"
-" character .emit EMIT_CHARACTER .or\n"
-" '*' .emit EMIT_LAST_CHARACTER .or\n"
-" '$' .emit EMIT_CURRENT_POSITION;\n"
-"emit_regbyte\n"
-" space .and \".load\" .and space .and identifier .and space .and emit_param;\n"
-"and_specifiers\n"
-" and_specifier .and .loop and_specifier;\n"
-"or_specifiers\n"
-" or_specifier .and .loop or_specifier;\n"
-"and_specifier\n"
-" space .and \".and\" .and space .and specifier;\n"
-"or_specifier\n"
-" space .and \".or\" .and space .and specifier;\n"
-".string __string_filter;\n"
-"__string_filter\n"
-" __first_identifier_char .and .loop __next_identifier_char;\n"
-"__first_identifier_char\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n"
-"__next_identifier_char\n"
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
-"" \ No newline at end of file
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * \file grammar_syn.h
+ * syntax parsing engine language syntax
+ * \author Michal Krol
+ */
+
+".syntax grammar;\n"
+".emtcode DECLARATION_END 0x00\n"
+".emtcode DECLARATION_EMITCODE 0x01\n"
+".emtcode DECLARATION_ERRORTEXT 0x02\n"
+".emtcode DECLARATION_REGBYTE 0x03\n"
+".emtcode DECLARATION_LEXER 0x04\n"
+".emtcode DECLARATION_RULE 0x05\n"
+".emtcode SPECIFIER_END 0x00\n"
+".emtcode SPECIFIER_AND_TAG 0x01\n"
+".emtcode SPECIFIER_OR_TAG 0x02\n"
+".emtcode SPECIFIER_CHARACTER_RANGE 0x03\n"
+".emtcode SPECIFIER_CHARACTER 0x04\n"
+".emtcode SPECIFIER_STRING 0x05\n"
+".emtcode SPECIFIER_IDENTIFIER 0x06\n"
+".emtcode SPECIFIER_TRUE 0x07\n"
+".emtcode SPECIFIER_FALSE 0x08\n"
+".emtcode SPECIFIER_DEBUG 0x09\n"
+".emtcode IDENTIFIER_NO_LOOP 0x00\n"
+".emtcode IDENTIFIER_LOOP 0x01\n"
+".emtcode ERROR_NOT_PRESENT 0x00\n"
+".emtcode ERROR_PRESENT 0x01\n"
+".emtcode EMIT_NULL 0x00\n"
+".emtcode EMIT_INTEGER 0x01\n"
+".emtcode EMIT_IDENTIFIER 0x02\n"
+".emtcode EMIT_CHARACTER 0x03\n"
+".emtcode EMIT_LAST_CHARACTER 0x04\n"
+".emtcode EMIT_CURRENT_POSITION 0x05\n"
+".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n"
+".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n"
+".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n"
+".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n"
+".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n"
+".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n"
+"grammar\n"
+" grammar_1 .error INVALID_GRAMMAR;\n"
+"grammar_1\n"
+" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n"
+" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n"
+"optional_space\n"
+" space .or .true;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" white_char .or comment_block;\n"
+"white_char\n"
+" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
+"comment_block\n"
+" '/' .and '*' .and .loop comment_char .and '*' .and '/';\n"
+"comment_char\n"
+" comment_char_no_star .or comment_char_1;\n"
+"comment_char_1\n"
+" '*' .and comment_char_no_slash;\n"
+"comment_char_no_star\n"
+" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
+"comment_char_no_slash\n"
+" '\\x30'-'\\xFF' .or '\\x01'-'\\x2E';\n"
+"identifier\n"
+" identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"identifier_ne\n"
+" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n"
+"first_idchar\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"follow_idchar\n"
+" first_idchar .or digit_dec;\n"
+"digit_dec\n"
+" '0'-'9';\n"
+"semicolon\n"
+" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
+"declaration_list\n"
+" declaration .and .loop declaration;\n"
+"declaration\n"
+" emitcode_definition .emit DECLARATION_EMITCODE .or\n"
+" errortext_definition .emit DECLARATION_ERRORTEXT .or\n"
+" regbyte_definition .emit DECLARATION_REGBYTE .or\n"
+" lexer_definition .emit DECLARATION_LEXER .or\n"
+" rule_definition .emit DECLARATION_RULE;\n"
+"emitcode_definition\n"
+" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n"
+"integer\n"
+" integer_ne .error INTEGER_EXPECTED;\n"
+"integer_ne\n"
+" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n"
+"hex_prefix\n"
+" '0' .and hex_prefix_1;\n"
+"hex_prefix_1\n"
+" 'x' .or 'X';\n"
+"digit_hex\n"
+" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n"
+"space_or_null\n"
+" space .or '\\0';\n"
+"errortext_definition\n"
+" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n"
+"string\n"
+" string_ne .error STRING_EXPECTED;\n"
+"string_ne\n"
+" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n"
+"string_char_double_quotes\n"
+" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n"
+"string_char\n"
+" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n"
+" '\\x01'-'\\x09';\n"
+"escape_sequence\n"
+" '\\\\' .emit * .and escape_code;\n"
+"escape_code\n"
+" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n"
+"simple_escape_code\n"
+" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n"
+"hex_escape_code\n"
+" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n"
+"oct_escape_code\n"
+" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n"
+"digit_oct\n"
+" '0'-'7';\n"
+"optional_digit_oct\n"
+" digit_oct .emit * .or .true;\n"
+"regbyte_definition\n"
+" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n"
+"lexer_definition\n"
+" \".string\" .and space .and identifier .and semicolon;\n"
+"rule_definition\n"
+" identifier_ne .and space .and definition;\n"
+"definition\n"
+" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n"
+"optional_specifiers_and_or\n"
+" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n"
+"specifier\n"
+" specifier_condition .and optional_space .and specifier_rule;\n"
+"specifier_condition\n"
+" specifier_condition_1 .or .true;\n"
+"specifier_condition_1\n"
+" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n"
+" right_operand .and optional_space .and ')';\n"
+"left_operand\n"
+" identifier;\n"
+"operator\n"
+" operator_1 .or operator_2;\n"
+"operator_1\n"
+" optional_space .and '!' .and '=' .and optional_space;\n"
+"operator_2\n"
+" optional_space .and '=' .and '=' .and optional_space;\n"
+"right_operand\n"
+" integer;\n"
+"specifier_rule\n"
+" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n"
+"specifier_rule_1\n"
+" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n"
+" character .emit SPECIFIER_CHARACTER .or\n"
+" string_ne .emit SPECIFIER_STRING .or\n"
+" \".true\" .emit SPECIFIER_TRUE .or\n"
+" \".false\" .emit SPECIFIER_FALSE .or\n"
+" \".debug\" .emit SPECIFIER_DEBUG .or\n"
+" loop_identifier .emit SPECIFIER_IDENTIFIER;\n"
+"character\n"
+" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n"
+"string_char_single_quotes\n"
+" escape_sequence .or string_char .emit * .or '\"' .emit *;\n"
+"character_range\n"
+" character .and optional_space .and '-' .and optional_space .and character;\n"
+"loop_identifier\n"
+" optional_loop .and identifier;\n"
+"optional_loop\n"
+" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_NO_LOOP;\n"
+"optional_loop_1\n"
+" \".loop\" .and space;\n"
+"optional_error\n"
+" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n"
+"error\n"
+" space .and \".error\" .and space .and identifier;\n"
+"emit\n"
+" emit_output .or emit_regbyte;\n"
+"emit_output\n"
+" space .and \".emit\" .and space .and emit_param;\n"
+"emit_param\n"
+" integer_ne .emit EMIT_INTEGER .or\n"
+" identifier_ne .emit EMIT_IDENTIFIER .or\n"
+" character .emit EMIT_CHARACTER .or\n"
+" '*' .emit EMIT_LAST_CHARACTER .or\n"
+" '$' .emit EMIT_CURRENT_POSITION;\n"
+"emit_regbyte\n"
+" space .and \".load\" .and space .and identifier .and space .and emit_param;\n"
+"and_specifiers\n"
+" and_specifier .and .loop and_specifier;\n"
+"or_specifiers\n"
+" or_specifier .and .loop or_specifier;\n"
+"and_specifier\n"
+" space .and \".and\" .and space .and specifier;\n"
+"or_specifier\n"
+" space .and \".or\" .and space .and specifier;\n"
+".string __string_filter;\n"
+"__string_filter\n"
+" __first_identifier_char .and .loop __next_identifier_char;\n"
+"__first_identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n"
+"__next_identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
+""