-.syntax program;\r
-\r
-/*\r
- This value must be incremented every time emit code values or structure of the production\r
- array changes. This value is placed at the beginning of the production array. The loader\r
- compares the value with its REVISION value. If they do not match, the loader is not up\r
- to date.\r
-*/\r
-.emtcode REVISION 0x07\r
-\r
-/* program type */\r
-.emtcode FRAGMENT_PROGRAM 0x01\r
-.emtcode VERTEX_PROGRAM 0x02\r
-\r
-/* program section */\r
-.emtcode OPTION 0x01\r
-.emtcode INSTRUCTION 0x02\r
-.emtcode DECLARATION 0x03\r
-.emtcode END 0x04\r
-\r
-/* GL_ARB_fragment_program option flags */\r
-.emtcode ARB_PRECISION_HINT_FASTEST 0x01\r
-.emtcode ARB_PRECISION_HINT_NICEST 0x02\r
-.emtcode ARB_FOG_EXP 0x04\r
-.emtcode ARB_FOG_EXP2 0x08\r
-.emtcode ARB_FOG_LINEAR 0x10\r
-\r
-/* GL_ARB_vertex_program option flags */\r
-.emtcode ARB_POSITION_INVARIANT 0x20\r
-\r
-/* GL_ARB_fragment_program_shadow option flags */\r
-.emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40\r
-\r
-/* GL_ARB_fragment_program instruction class */\r
-.emtcode OP_ALU_INST 0x00\r
-.emtcode OP_TEX_INST 0x01\r
-\r
-/* GL_ARB_vertex_program instruction class */\r
-/* OP_ALU_INST */\r
-\r
-/* GL_ARB_fragment_program instruction type */\r
-.emtcode OP_ALU_VECTOR 0x00\r
-.emtcode OP_ALU_SCALAR 0x01\r
-.emtcode OP_ALU_BINSC 0x02\r
-.emtcode OP_ALU_BIN 0x03\r
-.emtcode OP_ALU_TRI 0x04\r
-.emtcode OP_ALU_SWZ 0x05\r
-.emtcode OP_TEX_SAMPLE 0x06\r
-.emtcode OP_TEX_KIL 0x07\r
-\r
-/* GL_ARB_vertex_program instruction type */\r
-.emtcode OP_ALU_ARL 0x08\r
-/* OP_ALU_VECTOR */\r
-/* OP_ALU_SCALAR */\r
-/* OP_ALU_BINSC */\r
-/* OP_ALU_BIN */\r
-/* OP_ALU_TRI */\r
-/* OP_ALU_SWZ */\r
-\r
-/* GL_ARB_fragment_program instruction code */\r
-.emtcode OP_ABS 0x00\r
-.emtcode OP_ABS_SAT 0x1B\r
-.emtcode OP_FLR 0x09\r
-.emtcode OP_FLR_SAT 0x26\r
-.emtcode OP_FRC 0x0A\r
-.emtcode OP_FRC_SAT 0x27\r
-.emtcode OP_LIT 0x0C\r
-.emtcode OP_LIT_SAT 0x2A\r
-.emtcode OP_MOV 0x11\r
-.emtcode OP_MOV_SAT 0x30\r
-.emtcode OP_COS 0x1F\r
-.emtcode OP_COS_SAT 0x20\r
-.emtcode OP_EX2 0x07\r
-.emtcode OP_EX2_SAT 0x25\r
-.emtcode OP_LG2 0x0B\r
-.emtcode OP_LG2_SAT 0x29\r
-.emtcode OP_RCP 0x14\r
-.emtcode OP_RCP_SAT 0x33\r
-.emtcode OP_RSQ 0x15\r
-.emtcode OP_RSQ_SAT 0x34\r
-.emtcode OP_SIN 0x38\r
-.emtcode OP_SIN_SAT 0x39\r
-.emtcode OP_SCS 0x35\r
-.emtcode OP_SCS_SAT 0x36\r
-.emtcode OP_POW 0x13\r
-.emtcode OP_POW_SAT 0x32\r
-.emtcode OP_ADD 0x01\r
-.emtcode OP_ADD_SAT 0x1C\r
-.emtcode OP_DP3 0x03\r
-.emtcode OP_DP3_SAT 0x21\r
-.emtcode OP_DP4 0x04\r
-.emtcode OP_DP4_SAT 0x22\r
-.emtcode OP_DPH 0x05\r
-.emtcode OP_DPH_SAT 0x23\r
-.emtcode OP_DST 0x06\r
-.emtcode OP_DST_SAT 0x24\r
-.emtcode OP_MAX 0x0F\r
-.emtcode OP_MAX_SAT 0x2E\r
-.emtcode OP_MIN 0x10\r
-.emtcode OP_MIN_SAT 0x2F\r
-.emtcode OP_MUL 0x12\r
-.emtcode OP_MUL_SAT 0x31\r
-.emtcode OP_SGE 0x16\r
-.emtcode OP_SGE_SAT 0x37\r
-.emtcode OP_SLT 0x17\r
-.emtcode OP_SLT_SAT 0x3A\r
-.emtcode OP_SUB 0x18\r
-.emtcode OP_SUB_SAT 0x3B\r
-.emtcode OP_XPD 0x1A\r
-.emtcode OP_XPD_SAT 0x43\r
-.emtcode OP_CMP 0x1D\r
-.emtcode OP_CMP_SAT 0x1E\r
-.emtcode OP_LRP 0x2B\r
-.emtcode OP_LRP_SAT 0x2C\r
-.emtcode OP_MAD 0x0E\r
-.emtcode OP_MAD_SAT 0x2D\r
-.emtcode OP_SWZ 0x19\r
-.emtcode OP_SWZ_SAT 0x3C\r
-.emtcode OP_TEX 0x3D\r
-.emtcode OP_TEX_SAT 0x3E\r
-.emtcode OP_TXB 0x3F\r
-.emtcode OP_TXB_SAT 0x40\r
-.emtcode OP_TXP 0x41\r
-.emtcode OP_TXP_SAT 0x42\r
-.emtcode OP_KIL 0x28\r
-\r
-/* GL_ARB_vertex_program instruction code */\r
-.emtcode OP_ARL 0x02\r
-/* OP_ABS */\r
-/* OP_FLR */\r
-/* OP_FRC */\r
-/* OP_LIT */\r
-/* OP_MOV */\r
-/* OP_EX2 */\r
-.emtcode OP_EXP 0x08\r
-/* OP_LG2 */\r
-.emtcode OP_LOG 0x0D\r
-/* OP_RCP */\r
-/* OP_RSQ */\r
-/* OP_POW */\r
-/* OP_ADD */\r
-/* OP_DP3 */\r
-/* OP_DP4 */\r
-/* OP_DPH */\r
-/* OP_DST */\r
-/* OP_MAX */\r
-/* OP_MIN */\r
-/* OP_MUL */\r
-/* OP_SGE */\r
-/* OP_SLT */\r
-/* OP_SUB */\r
-/* OP_XPD */\r
-/* OP_MAD */\r
-/* OP_SWZ */\r
-\r
-/* fragment attribute binding */\r
-.emtcode FRAGMENT_ATTRIB_COLOR 0x01\r
-.emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\r
-.emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\r
-.emtcode FRAGMENT_ATTRIB_POSITION 0x04\r
-\r
-/* vertex attribute binding */\r
-.emtcode VERTEX_ATTRIB_POSITION 0x01\r
-.emtcode VERTEX_ATTRIB_WEIGHT 0x02\r
-.emtcode VERTEX_ATTRIB_NORMAL 0x03\r
-.emtcode VERTEX_ATTRIB_COLOR 0x04\r
-.emtcode VERTEX_ATTRIB_FOGCOORD 0x05\r
-.emtcode VERTEX_ATTRIB_TEXCOORD 0x06\r
-.emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\r
-.emtcode VERTEX_ATTRIB_GENERIC 0x08\r
-\r
-/* fragment result binding */\r
-.emtcode FRAGMENT_RESULT_COLOR 0x01\r
-.emtcode FRAGMENT_RESULT_DEPTH 0x02\r
-\r
-/* vertex result binding */\r
-.emtcode VERTEX_RESULT_POSITION 0x01\r
-.emtcode VERTEX_RESULT_COLOR 0x02\r
-.emtcode VERTEX_RESULT_FOGCOORD 0x03\r
-.emtcode VERTEX_RESULT_POINTSIZE 0x04\r
-.emtcode VERTEX_RESULT_TEXCOORD 0x05\r
-\r
-/* texture target */\r
-.emtcode TEXTARGET_1D 0x01\r
-.emtcode TEXTARGET_2D 0x02\r
-.emtcode TEXTARGET_3D 0x03\r
-.emtcode TEXTARGET_RECT 0x04\r
-.emtcode TEXTARGET_CUBE 0x05\r
-/* GL_ARB_fragment_program_shadow */\r
-.emtcode TEXTARGET_SHADOW1D 0x06\r
-.emtcode TEXTARGET_SHADOW2D 0x07\r
-.emtcode TEXTARGET_SHADOWRECT 0x08\r
-\r
-/* face type */\r
-.emtcode FACE_FRONT 0x00\r
-.emtcode FACE_BACK 0x01\r
-\r
-/* color type */\r
-.emtcode COLOR_PRIMARY 0x00\r
-.emtcode COLOR_SECONDARY 0x01\r
-\r
-/* component */\r
-.emtcode COMPONENT_X 0x00\r
-.emtcode COMPONENT_Y 0x01\r
-.emtcode COMPONENT_Z 0x02\r
-.emtcode COMPONENT_W 0x03\r
-.emtcode COMPONENT_0 0x04\r
-.emtcode COMPONENT_1 0x05\r
-\r
-/* array index type */\r
-.emtcode ARRAY_INDEX_ABSOLUTE 0x00\r
-.emtcode ARRAY_INDEX_RELATIVE 0x01\r
-\r
-/* matrix name */\r
-.emtcode MATRIX_MODELVIEW 0x01\r
-.emtcode MATRIX_PROJECTION 0x02\r
-.emtcode MATRIX_MVP 0x03\r
-.emtcode MATRIX_TEXTURE 0x04\r
-.emtcode MATRIX_PALETTE 0x05\r
-.emtcode MATRIX_PROGRAM 0x06\r
-\r
-/* matrix modifier */\r
-.emtcode MATRIX_MODIFIER_IDENTITY 0x00\r
-.emtcode MATRIX_MODIFIER_INVERSE 0x01\r
-.emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\r
-.emtcode MATRIX_MODIFIER_INVTRANS 0x03\r
-\r
-/* constant type */\r
-.emtcode CONSTANT_SCALAR 0x01\r
-.emtcode CONSTANT_VECTOR 0x02\r
-\r
-/* program param type */\r
-.emtcode PROGRAM_PARAM_ENV 0x01\r
-.emtcode PROGRAM_PARAM_LOCAL 0x02\r
-\r
-/* register type */\r
-.emtcode REGISTER_ATTRIB 0x01\r
-.emtcode REGISTER_PARAM 0x02\r
-.emtcode REGISTER_RESULT 0x03\r
-.emtcode REGISTER_ESTABLISHED_NAME 0x04\r
-\r
-/* param binding */\r
-.emtcode PARAM_NULL 0x00\r
-.emtcode PARAM_ARRAY_ELEMENT 0x01\r
-.emtcode PARAM_STATE_ELEMENT 0x02\r
-.emtcode PARAM_PROGRAM_ELEMENT 0x03\r
-.emtcode PARAM_PROGRAM_ELEMENTS 0x04\r
-.emtcode PARAM_CONSTANT 0x05\r
-\r
-/* param state property */\r
-.emtcode STATE_MATERIAL 0x01\r
-.emtcode STATE_LIGHT 0x02\r
-.emtcode STATE_LIGHT_MODEL 0x03\r
-.emtcode STATE_LIGHT_PROD 0x04\r
-.emtcode STATE_FOG 0x05\r
-.emtcode STATE_MATRIX_ROWS 0x06\r
-/* GL_ARB_fragment_program */\r
-.emtcode STATE_TEX_ENV 0x07\r
-.emtcode STATE_DEPTH 0x08\r
-/* GL_ARB_vertex_program */\r
-.emtcode STATE_TEX_GEN 0x09\r
-.emtcode STATE_CLIP_PLANE 0x0A\r
-.emtcode STATE_POINT 0x0B\r
-\r
-/* state material property */\r
-.emtcode MATERIAL_AMBIENT 0x01\r
-.emtcode MATERIAL_DIFFUSE 0x02\r
-.emtcode MATERIAL_SPECULAR 0x03\r
-.emtcode MATERIAL_EMISSION 0x04\r
-.emtcode MATERIAL_SHININESS 0x05\r
-\r
-/* state light property */\r
-.emtcode LIGHT_AMBIENT 0x01\r
-.emtcode LIGHT_DIFFUSE 0x02\r
-.emtcode LIGHT_SPECULAR 0x03\r
-.emtcode LIGHT_POSITION 0x04\r
-.emtcode LIGHT_ATTENUATION 0x05\r
-.emtcode LIGHT_HALF 0x06\r
-.emtcode LIGHT_SPOT_DIRECTION 0x07\r
-\r
-/* state light model property */\r
-.emtcode LIGHT_MODEL_AMBIENT 0x01\r
-.emtcode LIGHT_MODEL_SCENECOLOR 0x02\r
-\r
-/* state light product property */\r
-.emtcode LIGHT_PROD_AMBIENT 0x01\r
-.emtcode LIGHT_PROD_DIFFUSE 0x02\r
-.emtcode LIGHT_PROD_SPECULAR 0x03\r
-\r
-/* state texture environment property */\r
-.emtcode TEX_ENV_COLOR 0x01\r
-\r
-/* state texture generation coord property */\r
-.emtcode TEX_GEN_EYE 0x01\r
-.emtcode TEX_GEN_OBJECT 0x02\r
-\r
-/* state fog property */\r
-.emtcode FOG_COLOR 0x01\r
-.emtcode FOG_PARAMS 0x02\r
-\r
-/* state depth property */\r
-.emtcode DEPTH_RANGE 0x01\r
-\r
-/* state point parameters property */\r
-.emtcode POINT_SIZE 0x01\r
-.emtcode POINT_ATTENUATION 0x02\r
-\r
-/* declaration */\r
-.emtcode ATTRIB 0x01\r
-.emtcode PARAM 0x02\r
-.emtcode TEMP 0x03\r
-.emtcode OUTPUT 0x04\r
-.emtcode ALIAS 0x05\r
-/* GL_ARB_vertex_program */\r
-.emtcode ADDRESS 0x06\r
-\r
-/* error messages */\r
-.errtext UNKNOWN_PROGRAM_SIGNATURE "1001: '$e_signature$': unknown program signature"\r
-.errtext MISSING_END_OR_INVALID_STATEMENT "1002: '$e_statement$': invalid statement"\r
-.errtext CODE_AFTER_END "1003: '$e_statement$': code after 'END' keyword"\r
-.errtext INVALID_PROGRAM_OPTION "1004: '$e_identifier$': invalid program option"\r
-.errtext EXT_SWIZ_COMP_EXPECTED "1005: extended swizzle component expected but '$e_token$' found"\r
-.errtext TEX_TARGET_EXPECTED "1006: texture target expected but '$e_token$' found"\r
-.errtext TEXTURE_EXPECTED "1007: 'texture' expected but '$e_identifier$' found"\r
-.errtext SOURCE_REGISTER_EXPECTED "1008: source register expected but '$e_token$' found"\r
-.errtext DESTINATION_REGISTER_EXPECTED "1009: destination register expected but '$e_token$' found"\r
-.errtext INVALID_ADDRESS_COMPONENT "1010: '$e_identifier$': invalid address component"\r
-.errtext INVALID_ADDRESS_WRITEMASK "1011: '$e_identifier$': invalid address writemask"\r
-.errtext INVALID_COMPONENT "1012: '$e_charordigit$': invalid component"\r
-.errtext INVALID_SUFFIX "1013: '$e_identifier$': invalid suffix"\r
-.errtext INVALID_WRITEMASK "1014: '$e_identifier$': invalid writemask"\r
-.errtext FRAGMENT_EXPECTED "1015: 'fragment' expected but '$e_identifier$' found"\r
-.errtext VERTEX_EXPECTED "1016: 'vertex' expected but '$e_identifier$' found"\r
-.errtext INVALID_FRAGMENT_PROPERTY "1017: '$e_identifier$': invalid fragment property"\r
-.errtext INVALID_VERTEX_PROPERTY "1018: '$e_identifier$': invalid vertex property"\r
-.errtext INVALID_STATE_PROPERTY "1019: '$e_identifier$': invalid state property"\r
-.errtext INVALID_MATERIAL_PROPERTY "1020: '$e_identifier$': invalid material property"\r
-.errtext INVALID_LIGHT_PROPERTY "1021: '$e_identifier$': invalid light property"\r
-.errtext INVALID_SPOT_PROPERTY "1022: '$e_identifier$': invalid spot property"\r
-.errtext INVALID_LIGHTMODEL_PROPERTY "1023: '$e_identifier$': invalid light model property"\r
-.errtext INVALID_LIGHTPROD_PROPERTY "1024: '$e_identifier$': invalid light product property"\r
-.errtext INVALID_TEXENV_PROPERTY "1025: '$e_identifier$': invalid texture environment property"\r
-.errtext INVALID_TEXGEN_PROPERTY "1026: '$e_identifier$': invalid texture generating property"\r
-.errtext INVALID_TEXGEN_COORD "1027: '$e_identifier$': invalid texture generating coord"\r
-.errtext INVALID_FOG_PROPERTY "1028: '$e_identifier$': invalid fog property"\r
-.errtext INVALID_DEPTH_PROPERTY "1029: '$e_identifier$': invalid depth property"\r
-.errtext INVALID_CLIPPLANE_PROPERTY "1030: '$e_identifier$': invalid clip plane property"\r
-.errtext INVALID_POINT_PROPERTY "1031: '$e_identifier$': invalid point property"\r
-.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED "1032: matrix row selector or modifier expected but '$e_token$' found"\r
-.errtext INVALID_MATRIX_NAME "1033: '$e_identifier$': invalid matrix name"\r
-.errtext INVALID_PROGRAM_PROPERTY "1034: '$e_identifier$': invalid program property"\r
-.errtext RESULT_EXPECTED "1035: 'result' expected but '$e_token$' found"\r
-.errtext INVALID_RESULT_PROPERTY "1036: '$e_identifier$': invalid result property"\r
-.errtext INVALID_FACE_PROPERTY "1037: '$e_identifier$': invalid face property"\r
-.errtext INVALID_COLOR_PROPERTY "1038: '$e_identifier$': invalid color property"\r
-.errtext IDENTIFIER_EXPECTED "1039: identifier expected but '$e_token$' found"\r
-.errtext RESERVED_KEYWORD "1040: use of reserved keyword as an identifier"\r
-.errtext INTEGER_EXPECTED "1041: integer value expected but '$e_token$' found"\r
-.errtext MISSING_SEMICOLON "1042: ';' expected but '$e_token$' found"\r
-.errtext MISSING_COMMA "1043: ',' expected but '$e_token$' found"\r
-.errtext MISSING_LBRACKET "1044: '[' expected but '$e_token$' found"\r
-.errtext MISSING_RBRACKET "1045: ']' expected but '$e_token$' found"\r
-.errtext MISSING_DOT "1046: '.' expected but '$e_token$' found"\r
-.errtext MISSING_EQUAL "1047: '=' expected but '$e_token$' found"\r
-.errtext MISSING_LBRACE "1048: '{' expected but '$e_token$' found"\r
-.errtext MISSING_RBRACE "1049: '}' expected but '$e_token$' found"\r
-.errtext MISSING_DOTDOT "1050: '..' expected but '$e_token$' found"\r
-.errtext MISSING_FRACTION_OR_EXPONENT "1051: missing fraction part or exponent"\r
-.errtext MISSING_DOT_OR_EXPONENT "1052: missing '.' or exponent"\r
-.errtext EXPONENT_VALUE_EXPECTED "1053: exponent value expected"\r
-.errtext INTEGER_OUT_OF_RANGE "1054: integer value out of range"\r
-.errtext OPERATION_NEEDS_DESTINATION_VARIABLE "1055: operation needs destination variable"\r
-.errtext OPERATION_NEEDS_SOURCE_VARIABLE "1056: operation needs source variable"\r
-.errtext ADDRESS_REGISTER_EXPECTED "1057: address register expected but '$e_token$' found"\r
-.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED "1058: address register or integer literal expected but '$e_token$' found"\r
-\r
-/* extension presence condition registers */\r
-\r
-/* GL_ARB_vertex_blend */\r
-/* GL_EXT_vertex_weighting */\r
-.regbyte vertex_blend 0x00\r
-\r
-/* GL_ARB_matrix_palette */\r
-.regbyte matrix_palette 0x00\r
-\r
-/* GL_ARB_point_parameters */\r
-/* GL_EXT_point_parameters */\r
-.regbyte point_parameters 0x01\r
-\r
-/* GL_EXT_secondary_color */\r
-.regbyte secondary_color 0x01\r
-\r
-/* GL_EXT_fog_coord */\r
-.regbyte fog_coord 0x01\r
-\r
-/* GL_EXT_texture_rectangle */\r
-/* GL_NV_texture_rectangle */\r
-.regbyte texture_rectangle 0x01\r
-\r
-/* GL_ARB_fragment_program_shadow */\r
-.regbyte fragment_program_shadow 0x00\r
-\r
-/* option presence condition registers */\r
-/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */\r
-/* register is set to 1 to indicate that the OPTION was specified. */\r
-\r
-/* GL_ARB_fragment_program */\r
-.regbyte ARB_precision_hint_fastest 0x00\r
-.regbyte ARB_precision_hint_nicest 0x00\r
-.regbyte ARB_fog_exp 0x00\r
-.regbyte ARB_fog_exp2 0x00\r
-.regbyte ARB_fog_linear 0x00\r
-\r
-/* GL_ARB_vertex_program */\r
-.regbyte ARB_position_invariant 0x00\r
-\r
-/* GL_ARB_fragment_program_shadow */\r
-.regbyte ARB_fragment_program_shadow 0x00\r
-\r
-/* program target condition register */\r
-/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */\r
-/* to distinguish between them we need a register that will store for us the current target. */\r
-/* the client will typically set the register to apropriate value before parsing a particular */\r
-/* program. the mapping between program targets and their values is listed below. */\r
-/* */\r
-/* program target register value */\r
-/* ---------------------------------------------- */\r
-/* FRAGMENT_PROGRAM 0x10 */\r
-/* VERTEX_PROGRAM 0x20 */\r
-/* */\r
-/* the initial value of the register is 0 to catch potential errors with not setting the register */\r
-/* with the proper value. */\r
-.regbyte program_target 0x00\r
-\r
-/*\r
- <program> ::= <optionSequence> <statementSequence> "END"\r
-*/\r
-program\r
- programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\r
-programs\r
- .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\r
- .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\r
-frag_program_1_0\r
- '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\r
- optional_space .and fp_optionSequence .and fp_statementSequence .and\r
- "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\r
- '\0' .error CODE_AFTER_END;\r
-vert_program_1_0\r
- '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\r
- optional_space .and vp_optionSequence .and vp_statementSequence .and\r
- "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\r
- '\0' .error CODE_AFTER_END;\r
-\r
-/*\r
- <optionSequence> ::= <optionSequence> <option>\r
- | ""\r
-*/\r
-fp_optionSequence\r
- .loop fp_option;\r
-vp_optionSequence\r
- .loop vp_option;\r
-\r
-/*\r
- <option> ::= "OPTION" <identifier> ";"\r
-\r
-NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of\r
- these options is encountered, the other one is automatically disabled.\r
- the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear.\r
-*/\r
-fp_option\r
- "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\r
- fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\r
-vp_option\r
- "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\r
- vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\r
-fp_optionString\r
- .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest"\r
- .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\r
- .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest"\r
- .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\r
- fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\r
- fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\r
- fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\r
- .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow"\r
- .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;\r
-vp_optionString\r
- "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\r
-fp_ARB_fog_exp\r
- .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp";\r
-fp_ARB_fog_exp2\r
- .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2";\r
-fp_ARB_fog_linear\r
- .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear";\r
-\r
-/*\r
- <statementSequence> ::= <statementSequence> <statement>\r
- | ""\r
-*/\r
-fp_statementSequence\r
- .loop fp_statement;\r
-vp_statementSequence\r
- .loop vp_statement;\r
-\r
-/*\r
- <statement> ::= <instruction> ";"\r
- | <namingStatement> ";"\r
-\r
-NOTE: ".emit $" in the definitions below means that we output instruction position (offset of\r
- the first character of instruction) for program debugging purposes.\r
-*/\r
-fp_statement\r
- fp_statement_1 .or fp_statement_2;\r
-vp_statement\r
- vp_statement_1 .or vp_statement_2;\r
-fp_statement_1\r
- fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\r
-fp_statement_2\r
- fp_namingStatement .emit DECLARATION .and semicolon;\r
-vp_statement_1\r
- vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\r
-vp_statement_2\r
- vp_namingStatement .emit DECLARATION .and semicolon;\r
-\r
-/*\r
-fragment program\r
- <instruction> ::= <ALUInstruction>\r
- | <TexInstruction>\r
-\r
-vertex program\r
- <instruction> ::= <ARL_instruction>\r
- | <VECTORop_instruction>\r
- | <SCALARop_instruction>\r
- | <BINSCop_instruction>\r
- | <BINop_instruction>\r
- | <TRIop_instruction>\r
- | <SWZ_instruction>\r
-*/\r
-fp_instruction\r
- ALUInstruction .emit OP_ALU_INST .or\r
- TexInstruction .emit OP_TEX_INST;\r
-vp_instruction\r
- ARL_instruction .emit OP_ALU_ARL .or\r
- vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\r
- vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\r
- vp_BINSCop_instruction .emit OP_ALU_BINSC .or\r
- vp_BINop_instruction .emit OP_ALU_BIN .or\r
- vp_TRIop_instruction .emit OP_ALU_TRI .or\r
- vp_SWZ_instruction .emit OP_ALU_SWZ;\r
-\r
-/*\r
-fragment program\r
- <ALUInstruction> ::= <VECTORop_instruction>\r
- | <SCALARop_instruction>\r
- | <BINSCop_instruction>\r
- | <BINop_instruction>\r
- | <TRIop_instruction>\r
- | <SWZ_instruction>\r
-*/\r
-ALUInstruction\r
- fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\r
- fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\r
- fp_BINSCop_instruction .emit OP_ALU_BINSC .or\r
- fp_BINop_instruction .emit OP_ALU_BIN .or\r
- fp_TRIop_instruction .emit OP_ALU_TRI .or\r
- fp_SWZ_instruction .emit OP_ALU_SWZ;\r
-\r
-/*\r
-fragment program\r
- <TexInstruction> ::= <SAMPLE_instruction>\r
- | <KIL_instruction>\r
-*/\r
-TexInstruction\r
- SAMPLE_instruction .emit OP_TEX_SAMPLE .or\r
- KIL_instruction .emit OP_TEX_KIL;\r
-\r
-/*\r
-vertex program\r
- <ARL_instruction> ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>\r
-*/\r
-ARL_instruction\r
- "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\r
-\r
-/*\r
-fragment program\r
- <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," \r
- <vectorSrcReg>\r
-\r
-vertex program\r
- <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>\r
-*/\r
-fp_VECTORop_instruction\r
- fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\r
-vp_VECTORop_instruction\r
- vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\r
-\r
-/*\r
-fragment program\r
- <VECTORop> ::= "ABS" | "ABS_SAT"\r
- | "FLR" | "FLR_SAT"\r
- | "FRC" | "FRC_SAT"\r
- | "LIT" | "LIT_SAT"\r
- | "MOV" | "MOV_SAT"\r
-\r
-vertex program\r
- <VECTORop> ::= "ABS"\r
- | "FLR"\r
- | "FRC"\r
- | "LIT"\r
- | "MOV"\r
-*/\r
-fp_VECTORop\r
- "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or\r
- "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or\r
- "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or\r
- "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or\r
- "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT;\r
-vp_VECTORop\r
- "ABS" .emit OP_ABS .or\r
- "FLR" .emit OP_FLR .or\r
- "FRC" .emit OP_FRC .or\r
- "LIT" .emit OP_LIT .or\r
- "MOV" .emit OP_MOV;\r
-\r
-/*\r
- <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>\r
-*/\r
-fp_SCALARop_instruction\r
- fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\r
-vp_SCALARop_instruction\r
- vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\r
-\r
-/*\r
-fragment program\r
- <SCALARop> ::= "COS" | "COS_SAT"\r
- | "EX2" | "EX2_SAT"\r
- | "LG2" | "LG2_SAT"\r
- | "RCP" | "RCP_SAT"\r
- | "RSQ" | "RSQ_SAT"\r
- | "SIN" | "SIN_SAT"\r
- | "SCS" | "SCS_SAT"\r
-\r
-vertex program\r
- <SCALARop> ::= "EX2"\r
- | "EXP"\r
- | "LG2"\r
- | "LOG"\r
- | "RCP"\r
- | "RSQ"\r
-*/\r
-fp_SCALARop\r
- "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or\r
- "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or\r
- "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or\r
- "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or\r
- "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or\r
- "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or\r
- "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT;\r
-vp_SCALARop\r
- "EX2" .emit OP_EX2 .or\r
- "EXP" .emit OP_EXP .or\r
- "LG2" .emit OP_LG2 .or\r
- "LOG" .emit OP_LOG .or\r
- "RCP" .emit OP_RCP .or\r
- "RSQ" .emit OP_RSQ;\r
-\r
-/*\r
- <BINSCop_instruction> ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","\r
- <scalarSrcReg>\r
-*/\r
-fp_BINSCop_instruction\r
- fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\r
- fp_scalarSrcReg;\r
-vp_BINSCop_instruction\r
- vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\r
- vp_scalarSrcReg;\r
-\r
-/*\r
-fragment program\r
- <BINSCop> ::= "POW" | "POW_SAT"\r
-\r
-vertex program\r
- <BINSCop> ::= "POW"\r
-*/\r
-fp_BINSCop\r
- "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT;\r
-vp_BINSCop\r
- "POW" .emit OP_POW;\r
-\r
-/*\r
-fragment program\r
- <BINop_instruction> ::= <BINop> <maskedDstReg> ","\r
- <vectorSrcReg> "," <vectorSrcReg>\r
-\r
-vertex program\r
- <BINop_instruction> ::= <BINop> <maskedDstReg> ","\r
- <swizzleSrcReg> "," <swizzleSrcReg>\r
-*/\r
-fp_BINop_instruction\r
- fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\r
- vectorSrcReg;\r
-vp_BINop_instruction\r
- vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\r
- swizzleSrcReg;\r
-\r
-/*\r
-fragment program\r
- <BINop> ::= "ADD" | "ADD_SAT"\r
- | "DP3" | "DP3_SAT"\r
- | "DP4" | "DP4_SAT"\r
- | "DPH" | "DPH_SAT"\r
- | "DST" | "DST_SAT"\r
- | "MAX" | "MAX_SAT"\r
- | "MIN" | "MIN_SAT"\r
- | "MUL" | "MUL_SAT"\r
- | "SGE" | "SGE_SAT"\r
- | "SLT" | "SLT_SAT"\r
- | "SUB" | "SUB_SAT"\r
- | "XPD" | "XPD_SAT"\r
-\r
-vertex program\r
- <BINop> ::= "ADD"\r
- | "DP3"\r
- | "DP4"\r
- | "DPH"\r
- | "DST"\r
- | "MAX"\r
- | "MIN"\r
- | "MUL"\r
- | "SGE"\r
- | "SLT"\r
- | "SUB"\r
- | "XPD"\r
-*/\r
-fp_BINop\r
- "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or\r
- "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or\r
- "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or\r
- "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or\r
- "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or\r
- "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or\r
- "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or\r
- "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or\r
- "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or\r
- "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or\r
- "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or\r
- "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT;\r
-vp_BINop\r
- "ADD" .emit OP_ADD .or\r
- "DP3" .emit OP_DP3 .or\r
- "DP4" .emit OP_DP4 .or\r
- "DPH" .emit OP_DPH .or\r
- "DST" .emit OP_DST .or\r
- "MAX" .emit OP_MAX .or\r
- "MIN" .emit OP_MIN .or\r
- "MUL" .emit OP_MUL .or\r
- "SGE" .emit OP_SGE .or\r
- "SLT" .emit OP_SLT .or\r
- "SUB" .emit OP_SUB .or\r
- "XPD" .emit OP_XPD;\r
-\r
-/*\r
-fragment program\r
- <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","\r
- <vectorSrcReg> "," <vectorSrcReg> ","\r
- <vectorSrcReg>\r
-\r
-vertex program\r
- <TRIop_instruction> ::= <TRIop> <maskedDstReg> ","\r
- <swizzleSrcReg> "," <swizzleSrcReg> ","\r
- <swizzleSrcReg>\r
-*/\r
-fp_TRIop_instruction\r
- fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\r
- vectorSrcReg .and comma .and vectorSrcReg;\r
-vp_TRIop_instruction\r
- vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\r
- swizzleSrcReg .and comma .and swizzleSrcReg;\r
-\r
-/*\r
-fragment program\r
- <TRIop> ::= "CMP" | "CMP_SAT"\r
- | "LRP" | "LRP_SAT"\r
- | "MAD" | "MAD_SAT"\r
-\r
-vertex program\r
- <TRIop> ::= "MAD"\r
-*/\r
-fp_TRIop\r
- "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or\r
- "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or\r
- "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT;\r
-vp_TRIop\r
- "MAD" .emit OP_MAD;\r
-\r
-/*\r
-fragment program\r
- <SWZ_instruction> ::= <SWZop> <maskedDstReg> "," \r
- <srcReg> "," <extendedSwizzle>\r
-\r
-vertex program\r
- <SWZ_instruction> ::= "SWZ" <maskedDstReg> "," <srcReg> "," \r
- <extendedSwizzle>\r
-*/\r
-fp_SWZ_instruction\r
- SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\r
- fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\r
-vp_SWZ_instruction\r
- "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\r
- vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <SWZop> ::= "SWZ" | "SWZ_SAT"\r
-*/\r
-SWZop\r
- "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT;\r
-\r
-/*\r
-fragment program\r
- <SAMPLE_instruction> ::= <SAMPLEop> <maskedDstReg> ","\r
- <vectorSrcReg> "," <texImageUnit> "," \r
- <texTarget>\r
-*/\r
-SAMPLE_instruction\r
- SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\r
- texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <SAMPLEop> ::= "TEX" | "TEX_SAT"\r
- | "TXP" | "TXP_SAT"\r
- | "TXB" | "TXB_SAT"\r
-*/\r
-SAMPLEop\r
- "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or\r
- "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or\r
- "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT;\r
-\r
-/*\r
-fragment program\r
- <KIL_instruction> ::= "KIL" <vectorSrcReg>\r
-*/\r
-KIL_instruction\r
- "KIL" .emit OP_KIL .and space_src .and vectorSrcReg;\r
-\r
-/*\r
-fragment program\r
- <texImageUnit> ::= "texture" <optTexImageUnitNum>\r
-*/\r
-texImageUnit\r
- "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\r
-\r
-/*\r
-fragment program\r
- <texTarget> ::= "1D"\r
- | "2D"\r
- | "3D"\r
- | "CUBE"\r
- | "RECT"\r
- | <shadowTarget> (if option ARB_fragment_program_shadow present)\r
-*/\r
-texTarget\r
- "1D" .emit TEXTARGET_1D .or\r
- "2D" .emit TEXTARGET_2D .or\r
- "3D" .emit TEXTARGET_3D .or\r
- .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or\r
- "CUBE" .emit TEXTARGET_CUBE .or\r
- .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\r
-\r
-/*\r
-GL_ARB_fragment_program_shadow\r
- <shadowTarget> ::= "SHADOW1D"\r
- | "SHADOW2D"\r
- | "SHADOWRECT"\r
-*/\r
-shadowTarget\r
- "SHADOW1D" .emit TEXTARGET_SHADOW1D .or\r
- "SHADOW2D" .emit TEXTARGET_SHADOW2D .or\r
- .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT;\r
-\r
-/*\r
-fragment program\r
- <optTexImageUnitNum> ::= ""\r
- | "[" <texImageUnitNum> "]"\r
-*/\r
-optTexImageUnitNum\r
- optTexImageUnitNum_1 .or .true .emit 0x00;\r
-optTexImageUnitNum_1\r
- lbracket_ne .and texImageUnitNum .and rbracket;\r
-\r
-/*\r
-fragment program\r
- <texImageUnitNum> ::= <integer> from 0 to \r
- MAX_TEXTURE_IMAGE_UNITS_ARB-1\r
-*/\r
-texImageUnitNum\r
- integer;\r
-\r
-/*\r
- <scalarSrcReg> ::= <optionalSign> <srcReg> <scalarSuffix>\r
-*/\r
-fp_scalarSrcReg\r
- optionalSign .and fp_srcReg .and fp_scalarSuffix;\r
-vp_scalarSrcReg\r
- optionalSign .and vp_srcReg .and vp_scalarSuffix;\r
-\r
-/*\r
-vertex program\r
- <swizzleSrcReg> ::= <optionalSign> <srcReg> <swizzleSuffix>\r
-*/\r
-swizzleSrcReg\r
- optionalSign .and vp_srcReg .and swizzleSuffix;\r
-\r
-/*\r
-fragment program\r
- <vectorSrcReg> ::= <optionalSign> <srcReg> <optionalSuffix> \r
-*/\r
-vectorSrcReg\r
- optionalSign .and fp_srcReg .and optionalSuffix;\r
-\r
-/*\r
- <maskedDstReg> ::= <dstReg> <optionalMask>\r
-*/\r
-fp_maskedDstReg\r
- fp_dstReg .and fp_optionalMask;\r
-vp_maskedDstReg\r
- vp_dstReg .and vp_optionalMask;\r
-\r
-/*\r
-vertex program\r
- <maskedAddrReg> ::= <addrReg> <addrWriteMask>\r
-*/\r
-maskedAddrReg\r
- addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\r
-\r
-/*\r
-fragment program\r
- <extendedSwizzle> ::= <xyzwExtendedSwizzle>\r
- | <rgbaExtendedSwizzle>\r
-\r
-vertex program\r
- <extendedSwizzle> ::= <extSwizComp> "," <extSwizComp> "," \r
- <extSwizComp> "," <extSwizComp>\r
-\r
-NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez\r
-*/\r
-fp_extendedSwizzle\r
- rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\r
-vp_extendedSwizzle\r
- extSwizComp .and comma .and\r
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <xyzwExtendedSwizzle> ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> "," \r
- <xyzwExtSwizComp> "," <xyzwExtSwizComp>\r
-*/\r
-xyzwExtendedSwizzle\r
- xyzwExtSwizComp .and comma .and\r
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <rgbaExtendedSwizzle> ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> "," \r
- <rgbaExtSwizComp> "," <rgbaExtSwizComp>\r
-*/\r
-rgbaExtendedSwizzle\r
- rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\r
- rgbaExtendedSwizzle_4;\r
-rgbaExtendedSwizzle_1\r
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\r
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\r
-rgbaExtendedSwizzle_2\r
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\r
- rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\r
-rgbaExtendedSwizzle_3\r
- rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\r
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\r
-rgbaExtendedSwizzle_4\r
- rgbaExtSwizComp_alpha .and comma .and \r
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\r
- rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <xyzwExtSwizComp> ::= <optionalSign> <xyzwExtSwizSel>\r
-*/\r
-xyzwExtSwizComp\r
- optionalSign .and xyzwExtSwizSel;\r
-\r
-/*\r
-fragment program\r
- <rgbaExtSwizComp> ::= <optionalSign> <rgbaExtSwizSel>\r
-*/\r
-rgbaExtSwizComp\r
- optionalSign .and rgbaExtSwizSel;\r
-rgbaExtSwizComp_digit\r
- optionalSign .and rgbaExtSwizSel_digit;\r
-rgbaExtSwizComp_alpha\r
- optionalSign .and rgbaExtSwizSel_alpha;\r
-\r
-/*\r
-vertex program\r
- <extSwizComp> ::= <optionalSign> <extSwizSel>\r
-*/\r
-extSwizComp\r
- optionalSign .and extSwizSel;\r
-\r
-/*\r
-fragment program\r
- <xyzwExtSwizSel> ::= "0" \r
- | "1" \r
- | <xyzwComponent>\r
-*/\r
-xyzwExtSwizSel\r
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single;\r
-\r
-/*\r
-fragment program\r
- <rgbaExtSwizSel> ::= "0" \r
- | "1" \r
- | <rgbaComponent>\r
-*/\r
-rgbaExtSwizSel\r
- rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\r
-rgbaExtSwizSel_digit\r
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1;\r
-rgbaExtSwizSel_alpha\r
- rgbaComponent_single;\r
-\r
-/*\r
-vertex program\r
- <extSwizSel> ::= "0" \r
- | "1" \r
- | <component>\r
-*/\r
-extSwizSel\r
- "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single;\r
-\r
-/*\r
-fragment program\r
- <srcReg> ::= <fragmentAttribReg>\r
- | <temporaryReg>\r
- | <progParamReg>\r
-\r
-vertex program\r
- <srcReg> ::= <vertexAttribReg>\r
- | <temporaryReg>\r
- | <progParamReg>\r
-*/\r
-fp_srcReg\r
- fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\r
-vp_srcReg\r
- vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\r
-fp_srcReg_1\r
- fragmentAttribReg .emit REGISTER_ATTRIB .or\r
- fp_progParamReg .emit REGISTER_PARAM .or\r
- fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\r
-vp_srcReg_1\r
- vertexAttribReg .emit REGISTER_ATTRIB .or\r
- vp_progParamReg .emit REGISTER_PARAM .or\r
- vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\r
-\r
-/*\r
-fragment program\r
- <dstReg> ::= <temporaryReg>\r
- | <fragmentResultReg>\r
-\r
-vertex program\r
- <dstReg> ::= <temporaryReg>\r
- | <vertexResultReg>\r
-*/\r
-fp_dstReg\r
- fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\r
-vp_dstReg\r
- vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\r
-fp_dstReg_1\r
- fragmentResultReg .emit REGISTER_RESULT .or\r
- fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\r
-vp_dstReg_1\r
- vertexResultReg .emit REGISTER_RESULT .or\r
- vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\r
-\r
-/*\r
-fragment program\r
- <fragmentAttribReg> ::= <establishedName>\r
- | <fragAttribBinding>\r
-\r
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>\r
-*/\r
-fragmentAttribReg\r
- /*fp_establishedName .or */fragAttribBinding;\r
-\r
-/*\r
-vertex program\r
- <vertexAttribReg> ::= <establishedName>\r
- | <vtxAttribBinding>\r
-\r
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>\r
-*/\r
-vertexAttribReg\r
- vtxAttribBinding;\r
-\r
-/*\r
- <temporaryReg> ::= <establishedName>\r
-*/\r
-fp_temporaryReg\r
- fp_establishedName_no_error_on_identifier;\r
-vp_temporaryReg\r
- vp_establishedName_no_error_on_identifier;\r
-\r
-/*\r
-fragment program\r
- <progParamReg> ::= <progParamSingle>\r
- | <progParamArray> "[" <progParamArrayAbs> "]"\r
- | <paramSingleItemUse>\r
-\r
-vertex program\r
- <progParamReg> ::= <progParamSingle>\r
- | <progParamArray> "[" <progParamArrayMem> "]"\r
- | <paramSingleItemUse>\r
-*/\r
-fp_progParamReg\r
- fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\r
-vp_progParamReg\r
- vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\r
-fp_progParamReg_1\r
- fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\r
- rbracket;\r
-vp_progParamReg_1\r
- vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\r
- rbracket;\r
-\r
-/*\r
- <progParamSingle> ::= <establishedName>\r
-\r
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>\r
-*/\r
-fp_progParamSingle\r
- .false;\r
-vp_progParamSingle\r
- .false;\r
-\r
-/*\r
- <progParamArray> ::= <establishedName>\r
-*/\r
-fp_progParamArray\r
- fp_establishedName_no_error_on_identifier;\r
-vp_progParamArray\r
- vp_establishedName_no_error_on_identifier;\r
-\r
-/*\r
-vertex program\r
- <progParamArrayMem> ::= <progParamArrayAbs>\r
- | <progParamArrayRel>\r
-*/\r
-progParamArrayMem\r
- progParamArrayAbs .or progParamArrayRel;\r
-\r
-/*\r
- <progParamArrayAbs> ::= <integer>\r
-*/\r
-progParamArrayAbs\r
- integer_ne .emit ARRAY_INDEX_ABSOLUTE;\r
-\r
-/*\r
-vertex program\r
- <progParamArrayRel> ::= <addrReg> <addrComponent> <addrRegRelOffset>\r
-*/\r
-progParamArrayRel\r
- addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\r
- addrComponent .and addrRegRelOffset;\r
-\r
-/*\r
-vertex program\r
- <addrRegRelOffset> ::= ""\r
- | "+" <addrRegPosOffset>\r
- | "-" <addrRegNegOffset>\r
-*/\r
-addrRegRelOffset\r
- addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\r
-addrRegRelOffset_1\r
- plus_ne .and addrRegPosOffset;\r
-addrRegRelOffset_2\r
- minus_ne .and addrRegNegOffset;\r
-\r
-/*\r
-vertex program\r
- <addrRegPosOffset> ::= <integer> from 0 to 63\r
-*/\r
-addrRegPosOffset\r
- integer_0_63;\r
-\r
-/*\r
-vertex program\r
- <addrRegNegOffset> ::= <integer> from 0 to 64\r
-*/\r
-addrRegNegOffset\r
- integer_0_64;\r
-\r
-/*\r
-fragment program\r
- <fragmentResultReg> ::= <establishedName>\r
- | <resultBinding>\r
-\r
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>\r
-*/\r
-fragmentResultReg\r
- fp_resultBinding;\r
-\r
-/*\r
-vertex program\r
- <vertexResultReg> ::= <establishedName>\r
- | <resultBinding>\r
-\r
-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>\r
-*/\r
-vertexResultReg\r
- vp_resultBinding;\r
-\r
-/*\r
-vertex program\r
- <addrReg> ::= <establishedName>\r
-*/\r
-addrReg\r
- vp_establishedName_no_error_on_identifier;\r
-\r
-/*\r
-vertex program\r
- <addrComponent> ::= "." "x"\r
-*/\r
-addrComponent\r
- dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\r
- .emit COMPONENT_X .emit COMPONENT_X;\r
-\r
-/*\r
-vertex program\r
- <addrWriteMask> ::= "." "x"\r
-*/\r
-addrWriteMask\r
- dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\r
-\r
-/*\r
- <scalarSuffix> ::= "." <component>\r
-*/\r
-fp_scalarSuffix\r
- dot .and fp_component_single .error INVALID_COMPONENT;\r
-vp_scalarSuffix\r
- dot .and vp_component_single .error INVALID_COMPONENT;\r
-\r
-/*\r
-vertex program\r
- <swizzleSuffix> ::= ""\r
- | "." <component>\r
- | "." <component> <component>\r
- <component> <component>\r
-*/\r
-swizzleSuffix\r
- swizzleSuffix_1 .or\r
- .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\r
-swizzleSuffix_1\r
- dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\r
-swizzleSuffix_2\r
- swizzleSuffix_3 .or swizzleSuffix_4;\r
-swizzleSuffix_3\r
- vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\r
- vp_component_multi .error INVALID_COMPONENT;\r
-swizzleSuffix_4\r
- "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\r
- "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\r
- "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\r
- "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\r
-\r
-/*\r
-fragment program\r
- <optionalSuffix> ::= "" \r
- | "." <component> \r
- | "." <xyzwComponent> <xyzwComponent>\r
- <xyzwComponent> <xyzwComponent>\r
- | "." <rgbaComponent> <rgbaComponent>\r
- <rgbaComponent> <rgbaComponent>\r
-*/\r
-optionalSuffix\r
- optionalSuffix_1 .or\r
- .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\r
-optionalSuffix_1\r
- dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\r
-optionalSuffix_2\r
- optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\r
-optionalSuffix_3\r
- xyzwComponent_multi .and xyzwComponent_multi .and\r
- xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\r
-optionalSuffix_4\r
- rgbaComponent_multi .and rgbaComponent_multi .and\r
- rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\r
-optionalSuffix_5\r
- "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\r
- "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\r
- "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\r
- "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\r
- "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\r
- "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\r
- "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\r
- "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\r
-\r
-/*\r
-fragment program\r
- <component> ::= <xyzwComponent>\r
- | <rgbaComponent>\r
-\r
-vertex program\r
- <component> ::= "x"\r
- | "y"\r
- | "z"\r
- | "w"\r
-*/\r
-fp_component_single\r
- xyzwComponent_single .or rgbaComponent_single;\r
-vp_component_multi\r
- 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\r
- 'w' .emit COMPONENT_W;\r
-vp_component_single\r
- "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or\r
- "w" .emit COMPONENT_W;\r
-\r
-/*\r
-fragment program\r
- <xyzwComponent> ::= "x" | "y" | "z" | "w"\r
-*/\r
-xyzwComponent_multi\r
- 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\r
- 'w' .emit COMPONENT_W;\r
-xyzwComponent_single\r
- "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or\r
- "w" .emit COMPONENT_W;\r
-\r
-/*\r
-fragment program\r
- <rgbaComponent> ::= "r" | "g" | "b" | "a"\r
-*/\r
-rgbaComponent_multi\r
- 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\r
- 'a' .emit COMPONENT_W;\r
-rgbaComponent_single\r
- "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or\r
- "a" .emit COMPONENT_W;\r
-\r
-/*\r
-fragment program\r
- <optionalMask> ::= ""\r
- | <xyzwMask>\r
- | <rgbaMask>\r
-\r
-vertex program\r
- <optionalMask> ::= ""\r
- | "." "x"\r
- | "." "y"\r
- | "." "xy"\r
- | "." "z"\r
- | "." "xz"\r
- | "." "yz"\r
- | "." "xyz"\r
- | "." "w"\r
- | "." "xw"\r
- | "." "yw"\r
- | "." "xyw"\r
- | "." "zw"\r
- | "." "xzw"\r
- | "." "yzw"\r
- | "." "xyzw"\r
-\r
-NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez\r
-*/\r
-fp_optionalMask\r
- rgbaMask .or xyzwMask .or .true .emit 0x0F;\r
-vp_optionalMask\r
- xyzwMask .or .true .emit 0x0F;\r
-\r
-/*\r
-fragment program\r
- <xyzwMask> ::= "." "x"\r
- | "." "y"\r
- | "." "xy"\r
- | "." "z"\r
- | "." "xz"\r
- | "." "yz"\r
- | "." "xyz"\r
- | "." "w"\r
- | "." "xw"\r
- | "." "yw"\r
- | "." "xyw"\r
- | "." "zw"\r
- | "." "xzw"\r
- | "." "yzw"\r
- | "." "xyzw"\r
-\r
-NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>.\r
-*/\r
-xyzwMask\r
- dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\r
-xyzwMask_1\r
- "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or\r
- "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or\r
- "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or\r
- "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01;\r
-\r
-/*\r
-fragment program\r
- <rgbaMask> ::= "." "r"\r
- | "." "g"\r
- | "." "rg"\r
- | "." "b"\r
- | "." "rb"\r
- | "." "gb"\r
- | "." "rgb"\r
- | "." "a"\r
- | "." "ra"\r
- | "." "ga"\r
- | "." "rga"\r
- | "." "ba"\r
- | "." "rba"\r
- | "." "gba"\r
- | "." "rgba"\r
-*/\r
-rgbaMask\r
- dot_ne .and rgbaMask_1;\r
-rgbaMask_1\r
- "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or\r
- "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or\r
- "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or\r
- "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01;\r
-\r
-/*\r
-fragment program\r
- <namingStatement> ::= <ATTRIB_statement>\r
- | <PARAM_statement>\r
- | <TEMP_statement>\r
- | <OUTPUT_statement>\r
- | <ALIAS_statement>\r
-\r
-vertex program\r
- <namingStatement> ::= <ATTRIB_statement>\r
- | <PARAM_statement>\r
- | <TEMP_statement>\r
- | <ADDRESS_statement>\r
- | <OUTPUT_statement>\r
- | <ALIAS_statement>\r
-*/\r
-fp_namingStatement\r
- fp_ATTRIB_statement .emit ATTRIB .or\r
- fp_PARAM_statement .emit PARAM .or\r
- fp_TEMP_statement .emit TEMP .or\r
- fp_OUTPUT_statement .emit OUTPUT .or\r
- fp_ALIAS_statement .emit ALIAS;\r
-vp_namingStatement\r
- vp_ATTRIB_statement .emit ATTRIB .or\r
- vp_PARAM_statement .emit PARAM .or\r
- vp_TEMP_statement .emit TEMP .or\r
- ADDRESS_statement .emit ADDRESS .or\r
- vp_OUTPUT_statement .emit OUTPUT .or\r
- vp_ALIAS_statement .emit ALIAS;\r
-\r
-/*\r
-fragment program\r
- <ATTRIB_statement> ::= "ATTRIB" <establishName> "="\r
- <fragAttribBinding>\r
-\r
-vertex program\r
- <ATTRIB_statement> ::= "ATTRIB" <establishName> "="\r
- <vtxAttribBinding>\r
-*/\r
-fp_ATTRIB_statement\r
- "ATTRIB" .and space .and fp_establishName .and equal .and\r
- fragAttribBinding .error FRAGMENT_EXPECTED;\r
-vp_ATTRIB_statement\r
- "ATTRIB" .and space .and vp_establishName .and equal .and\r
- vtxAttribBinding .error VERTEX_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <fragAttribBinding> ::= "fragment" "." <fragAttribItem>\r
-*/\r
-fragAttribBinding\r
- "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\r
-\r
-/*\r
-vertex program\r
- <vtxAttribBinding> ::= "vertex" "." <vtxAttribItem>\r
-*/\r
-vtxAttribBinding\r
- "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\r
-\r
-/*\r
-fragment program\r
- <fragAttribItem> ::= "color" <optColorType>\r
- | "texcoord" <optTexCoordNum>\r
- | "fogcoord"\r
- | "position"\r
-*/\r
-fragAttribItem\r
- fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\r
- fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\r
- .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or\r
- "position" .emit FRAGMENT_ATTRIB_POSITION;\r
-fragAttribItem_1\r
- "color" .and optColorType;\r
-fragAttribItem_2\r
- "texcoord" .and optTexCoordNum;\r
-\r
-/*\r
-vertex program\r
- <vtxAttribItem> ::= "position"\r
- | "weight" <vtxOptWeightNum>\r
- | "normal"\r
- | "color" <optColorType>\r
- | "fogcoord"\r
- | "texcoord" <optTexCoordNum>\r
- | "matrixindex" "[" <vtxWeightNum> "]"\r
- | "attrib" "[" <vtxAttribNum> "]"\r
-*/\r
-vtxAttribItem\r
- "position" .emit VERTEX_ATTRIB_POSITION .or\r
- .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\r
- "normal" .emit VERTEX_ATTRIB_NORMAL .or\r
- vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\r
- "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or\r
- vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\r
- .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\r
- vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\r
-vtxAttribItem_1\r
- "weight" .and vtxOptWeightNum;\r
-vtxAttribItem_2\r
- "color" .and optColorType;\r
-vtxAttribItem_3\r
- "texcoord" .and optTexCoordNum;\r
-vtxAttribItem_4\r
- "matrixindex" .and lbracket .and vtxWeightNum .and rbracket;\r
-vtxAttribItem_5\r
- "attrib" .and lbracket .and vtxAttribNum .and rbracket;\r
-\r
-/*\r
-vertex program\r
- <vtxAttribNum> ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1\r
-*/\r
-vtxAttribNum\r
- integer;\r
-\r
-/*\r
-vertex program\r
- <vtxOptWeightNum> ::= ""\r
- | "[" <vtxWeightNum> "]"\r
-*/\r
-vtxOptWeightNum\r
- vtxOptWeightNum_1 .or .true .emit 0x00;\r
-vtxOptWeightNum_1\r
- lbracket_ne .and vtxWeightNum .and rbracket;\r
-\r
-/*\r
-vertex program\r
- <vtxWeightNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,\r
- must be divisible by four\r
-*/\r
-vtxWeightNum\r
- integer;\r
-\r
-/*\r
- <PARAM_statement> ::= <PARAM_singleStmt>\r
- | <PARAM_multipleStmt>\r
-*/\r
-fp_PARAM_statement\r
- fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\r
-vp_PARAM_statement\r
- vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\r
-\r
-/*\r
- <PARAM_singleStmt> ::= "PARAM" <establishName> <paramSingleInit>\r
-*/\r
-fp_PARAM_singleStmt\r
- "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\r
- .true .emit PARAM_NULL;\r
-vp_PARAM_singleStmt\r
- "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\r
- .true .emit PARAM_NULL;\r
-\r
-/*\r
- <PARAM_multipleStmt> ::= "PARAM" <establishName> "[" <optArraySize> "]"\r
- <paramMultipleInit>\r
-*/\r
-fp_PARAM_multipleStmt\r
- "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\r
- fp_paramMultipleInit .and .true .emit PARAM_NULL;\r
-vp_PARAM_multipleStmt\r
- "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\r
- vp_paramMultipleInit .and .true .emit PARAM_NULL;\r
-\r
-/*\r
- <optArraySize> ::= ""\r
- | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB\r
- (maximum number of allowed program \r
- parameter bindings)\r
-*/\r
-optArraySize\r
- optional_integer;\r
-\r
-/*\r
- <paramSingleInit> ::= "=" <paramSingleItemDecl>\r
-*/\r
-fp_paramSingleInit\r
- equal .and fp_paramSingleItemDecl;\r
-vp_paramSingleInit\r
- equal .and vp_paramSingleItemDecl;\r
-\r
-/*\r
- <paramMultipleInit> ::= "=" "{" <paramMultInitList> "}"\r
-*/\r
-fp_paramMultipleInit\r
- equal .and lbrace .and fp_paramMultInitList .and rbrace;\r
-vp_paramMultipleInit\r
- equal .and lbrace .and vp_paramMultInitList .and rbrace;\r
-\r
-/*\r
- <paramMultInitList> ::= <paramMultipleItem>\r
- | <paramMultipleItem> "," <paramMultiInitList>\r
-*/\r
-fp_paramMultInitList\r
- fp_paramMultInitList_1 .or fp_paramMultipleItem;\r
-vp_paramMultInitList\r
- vp_paramMultInitList_1 .or vp_paramMultipleItem;\r
-fp_paramMultInitList_1\r
- fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\r
-vp_paramMultInitList_1\r
- vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\r
-\r
-/*\r
- <paramSingleItemDecl> ::= <stateSingleItem>\r
- | <programSingleItem>\r
- | <paramConstDecl>\r
-*/\r
-fp_paramSingleItemDecl\r
- fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\r
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\r
- paramConstDecl .emit PARAM_CONSTANT;\r
-vp_paramSingleItemDecl\r
- vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\r
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\r
- paramConstDecl .emit PARAM_CONSTANT;\r
-\r
-/*\r
- <paramSingleItemUse> ::= <stateSingleItem>\r
- | <programSingleItem>\r
- | <paramConstUse>\r
-*/\r
-fp_paramSingleItemUse\r
- fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\r
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\r
- paramConstUse .emit PARAM_CONSTANT;\r
-vp_paramSingleItemUse\r
- vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\r
- programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\r
- paramConstUse .emit PARAM_CONSTANT;\r
-\r
-/*\r
- <paramMultipleItem> ::= <stateMultipleItem>\r
- | <programMultipleItem>\r
- | <paramConstDecl>\r
-*/\r
-fp_paramMultipleItem\r
- fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\r
- programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\r
- paramConstDecl .emit PARAM_CONSTANT;\r
-vp_paramMultipleItem\r
- vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\r
- programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\r
- paramConstDecl .emit PARAM_CONSTANT;\r
-\r
-/*\r
- <stateMultipleItem> ::= <stateSingleItem>\r
- | "state" "." <stateMatrixRows>\r
-*/\r
-fp_stateMultipleItem\r
- stateMultipleItem_1 .or fp_stateSingleItem;\r
-vp_stateMultipleItem\r
- stateMultipleItem_1 .or vp_stateSingleItem;\r
-stateMultipleItem_1\r
- "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\r
-\r
-/*\r
-fragment program\r
- <stateSingleItem> ::= "state" "." <stateMaterialItem>\r
- | "state" "." <stateLightItem>\r
- | "state" "." <stateLightModelItem>\r
- | "state" "." <stateLightProdItem>\r
- | "state" "." <stateTexEnvItem>\r
- | "state" "." <stateFogItem>\r
- | "state" "." <stateDepthItem>\r
- | "state" "." <stateMatrixRow>\r
-\r
-vertex program\r
- <stateSingleItem> ::= "state" "." <stateMaterialItem>\r
- | "state" "." <stateLightItem>\r
- | "state" "." <stateLightModelItem>\r
- | "state" "." <stateLightProdItem>\r
- | "state" "." <stateTexGenItem>\r
- | "state" "." <stateFogItem>\r
- | "state" "." <stateClipPlaneItem>\r
- | "state" "." <statePointItem>\r
- | "state" "." <stateMatrixRow>\r
-*/\r
-fp_stateSingleItem\r
- "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\r
-vp_stateSingleItem\r
- "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\r
-fp_stateSingleItem_1\r
- stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\r
- stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\r
-vp_stateSingleItem_1\r
- stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\r
- stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\r
- stateSingleItem_11;\r
-stateSingleItem_1\r
- stateMaterialItem .emit STATE_MATERIAL;\r
-stateSingleItem_2\r
- stateLightItem .emit STATE_LIGHT;\r
-stateSingleItem_3\r
- stateLightModelItem .emit STATE_LIGHT_MODEL;\r
-stateSingleItem_4\r
- stateLightProdItem .emit STATE_LIGHT_PROD;\r
-stateSingleItem_5\r
- stateTexEnvItem .emit STATE_TEX_ENV;\r
-stateSingleItem_6\r
- stateTexGenItem .emit STATE_TEX_GEN;\r
-stateSingleItem_7\r
- stateFogItem .emit STATE_FOG;\r
-stateSingleItem_8\r
- stateDepthItem .emit STATE_DEPTH;\r
-stateSingleItem_9\r
- stateClipPlaneItem .emit STATE_CLIP_PLANE;\r
-stateSingleItem_10\r
- statePointItem .emit STATE_POINT;\r
-stateSingleItem_11\r
- stateMatrixRow .emit STATE_MATRIX_ROWS;\r
-\r
-/*\r
- <stateMaterialItem> ::= "material" <optFaceType> "." <stateMatProperty>\r
-*/\r
-stateMaterialItem\r
- "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\r
-\r
-/*\r
- <stateMatProperty> ::= "ambient"\r
- | "diffuse"\r
- | "specular"\r
- | "emission"\r
- | "shininess"\r
-*/\r
-stateMatProperty\r
- "ambient" .emit MATERIAL_AMBIENT .or\r
- "diffuse" .emit MATERIAL_DIFFUSE .or\r
- "specular" .emit MATERIAL_SPECULAR .or\r
- "emission" .emit MATERIAL_EMISSION .or\r
- "shininess" .emit MATERIAL_SHININESS;\r
-\r
-/*\r
- <stateLightItem> ::= "light" "[" <stateLightNumber> "]" "." \r
- <stateLightProperty>\r
-*/\r
-stateLightItem\r
- "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and\r
- stateLightProperty .error INVALID_LIGHT_PROPERTY;\r
-\r
-/*\r
- <stateLightProperty> ::= "ambient"\r
- | "diffuse" \r
- | "specular"\r
- | "position"\r
- | "attenuation"\r
- | "spot" "." <stateSpotProperty>\r
- | "half"\r
-*/\r
-stateLightProperty\r
- "ambient" .emit LIGHT_AMBIENT .or\r
- "diffuse" .emit LIGHT_DIFFUSE .or\r
- "specular" .emit LIGHT_SPECULAR .or\r
- "position" .emit LIGHT_POSITION .or\r
- "attenuation" .emit LIGHT_ATTENUATION .or\r
- stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\r
- "half" .emit LIGHT_HALF;\r
-stateLightProperty_1\r
- "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\r
-\r
-/*\r
- <stateSpotProperty> ::= "direction" \r
-*/\r
-stateSpotProperty\r
- "direction";\r
-\r
-/*\r
- <stateLightModelItem> ::= "lightmodel" <stateLModProperty>\r
-*/\r
-stateLightModelItem\r
- "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\r
-\r
-/*\r
- <stateLModProperty> ::= "." "ambient"\r
- | <optFaceType> "." "scenecolor"\r
-*/\r
-stateLModProperty\r
- stateLModProperty_1 .or stateLModProperty_2;\r
-stateLModProperty_1\r
- dot .and "ambient" .emit LIGHT_MODEL_AMBIENT;\r
-stateLModProperty_2\r
- stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\r
-stateLModProperty_3\r
- optFaceType .and dot .and "scenecolor";\r
-\r
-/*\r
- <stateLightProdItem> ::= "lightprod" "[" <stateLightNumber> "]"\r
- <optFaceType> "." <stateLProdProperty>\r
-*/\r
-stateLightProdItem\r
- "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\r
- stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\r
-\r
-/*\r
- <stateLProdProperty> ::= "ambient"\r
- | "diffuse"\r
- | "specular"\r
-*/\r
-stateLProdProperty\r
- "ambient" .emit LIGHT_PROD_AMBIENT .or\r
- "diffuse" .emit LIGHT_PROD_DIFFUSE .or\r
- "specular" .emit LIGHT_PROD_SPECULAR;\r
-\r
-/*\r
- <stateLightNumber> ::= <integer> from 0 to MAX_LIGHTS-1\r
-*/\r
-stateLightNumber\r
- integer;\r
-\r
-/*\r
-fragment program\r
- <stateTexEnvItem> ::= "texenv" <optLegacyTexUnitNum> "." \r
- <stateTexEnvProperty>\r
-*/\r
-stateTexEnvItem\r
- "texenv" .and optLegacyTexUnitNum .and dot .and\r
- stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\r
-\r
-/*\r
-fragment program\r
- <stateTexEnvProperty> ::= "color"\r
-*/\r
-stateTexEnvProperty\r
- "color" .emit TEX_ENV_COLOR;\r
-\r
-/*\r
-fragment program\r
- <optLegacyTexUnitNum> ::= ""\r
- | "[" <legacyTexUnitNum> "]"\r
-\r
-NOTE: <optLegaceTexUnitNum> is not optional.\r
-*/\r
-optLegacyTexUnitNum\r
- lbracket_ne .and legacyTexUnitNum .and rbracket;\r
-\r
-/*\r
-fragment program\r
- <legacyTexUnitNum> ::= <integer> from 0 to MAX_TEXTURE_UNITS-1\r
-*/\r
-legacyTexUnitNum\r
- integer;\r
-\r
-/*\r
-vertex program\r
- <stateTexGenItem> ::= "texgen" <optTexCoordNum> "."\r
- <stateTexGenType> "." <stateTexGenCoord>\r
-*/\r
-stateTexGenItem\r
- "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\r
- dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\r
-\r
-/*\r
-vertex program\r
- <stateTexGenType> ::= "eye"\r
- | "object"\r
-*/\r
-stateTexGenType\r
- "eye" .emit TEX_GEN_EYE .or\r
- "object" .emit TEX_GEN_OBJECT;\r
-\r
-/*\r
-vertex program\r
- <stateTexGenCoord> ::= "s"\r
- | "t"\r
- | "r"\r
- | "q"\r
-*/\r
-stateTexGenCoord\r
- "s" .emit COMPONENT_X .or\r
- "t" .emit COMPONENT_Y .or\r
- "r" .emit COMPONENT_Z .or\r
- "q" .emit COMPONENT_W;\r
-\r
-/*\r
- <stateFogItem> ::= "fog" "." <stateFogProperty>\r
-*/\r
-stateFogItem\r
- "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\r
-\r
-/*\r
- <stateFogProperty> ::= "color"\r
- | "params"\r
-*/\r
-stateFogProperty\r
- "color" .emit FOG_COLOR .or\r
- "params" .emit FOG_PARAMS;\r
-\r
-/*\r
-fragment program\r
- <stateDepthItem> ::= "depth" "." <stateDepthProperty>\r
-*/\r
-stateDepthItem\r
- "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\r
-\r
-/*\r
-fragment program\r
- <stateDepthProperty> ::= "range"\r
-*/\r
-stateDepthProperty\r
- "range" .emit DEPTH_RANGE;\r
-\r
-/*\r
-vertex program\r
- <stateClipPlaneItem> ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"\r
-*/\r
-stateClipPlaneItem\r
- "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\r
- "plane" .error INVALID_CLIPPLANE_PROPERTY;\r
-\r
-/*\r
-vertex program\r
- <stateClipPlaneNum> ::= <integer> from 0 to MAX_CLIP_PLANES-1\r
-*/\r
-stateClipPlaneNum\r
- integer;\r
-\r
-/*\r
-vertex program\r
- <statePointItem> ::= "point" . <statePointProperty>\r
-*/\r
-statePointItem\r
- "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\r
-\r
-/*\r
-vertex program\r
- <statePointProperty> ::= "size"\r
- | "attenuation"\r
-*/\r
-statePointProperty\r
- "size" .emit POINT_SIZE .or\r
- .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION;\r
-\r
-/*\r
- <stateMatrixRow> ::= <stateMatrixItem> "." "row" "[" \r
- <stateMatrixRowNum> "]"\r
-*/\r
-stateMatrixRow\r
- stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\r
- lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\r
-\r
-/*\r
- <stateMatrixRows> ::= <stateMatrixItem> <optMatrixRows>\r
-*/\r
-stateMatrixRows\r
- stateMatrixItem .and optMatrixRows;\r
-\r
-/*\r
- <optMatrixRows> ::= ""\r
- | "." "row" "[" <stateMatrixRowNum> ".." \r
- <stateMatrixRowNum> "]"\r
-*/\r
-optMatrixRows\r
- optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\r
-optMatrixRows_1\r
- dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\r
- stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\r
-\r
-/*\r
- <stateMatrixItem> ::= "matrix" . <stateMatrixName> \r
- <stateOptMatModifier>\r
-*/\r
-stateMatrixItem\r
- "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\r
-\r
-/*\r
- <stateOptMatModifier> ::= ""\r
- | "." <stateMatModifier>\r
-*/\r
-stateOptMatModifier\r
- stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\r
-stateOptMatModifier_1\r
- dot_ne .and stateMatModifier;\r
-\r
-/*\r
- <stateMatModifier> ::= "inverse" \r
- | "transpose" \r
- | "invtrans"\r
-*/\r
-stateMatModifier\r
- "inverse" .emit MATRIX_MODIFIER_INVERSE .or\r
- "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or\r
- "invtrans" .emit MATRIX_MODIFIER_INVTRANS;\r
-\r
-/*\r
- <stateMatrixRowNum> ::= <integer> from 0 to 3\r
-*/\r
-stateMatrixRowNum\r
- integer_0_3;\r
-\r
-/*\r
- <stateMatrixName> ::= "modelview" <stateOptModMatNum>\r
- | "projection"\r
- | "mvp"\r
- | "texture" <optTexCoordNum>\r
- | "palette" "[" <statePaletteMatNum> "]"\r
- | "program" "[" <stateProgramMatNum> "]"\r
-*/\r
-stateMatrixName\r
- stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\r
- "projection" .emit MATRIX_PROJECTION .or\r
- "mvp" .emit MATRIX_MVP .or\r
- stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\r
- .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\r
- stateMatrixName_1_4 .emit MATRIX_PROGRAM;\r
-stateMatrixName_1_1\r
- "modelview" .and stateOptModMatNum;\r
-stateMatrixName_1_2\r
- "texture" .and optTexCoordNum;\r
-stateMatrixName_1_3\r
- "palette" .and lbracket .and statePaletteMatNum .and rbracket;\r
-stateMatrixName_1_4\r
- "program" .and lbracket .and stateProgramMatNum .and rbracket;\r
-\r
-/*\r
- <stateOptModMatNum> ::= ""\r
- | "[" <stateModMatNum> "]"\r
-*/\r
-stateOptModMatNum\r
- .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\r
- .true .emit 0x00;\r
-stateOptModMatNum_1\r
- lbracket_ne .and stateModMatNum .and rbracket;\r
-\r
-/*\r
- <stateModMatNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1\r
-*/\r
-stateModMatNum\r
- integer;\r
-\r
-/*\r
- <optTexCoordNum> ::= ""\r
- | "[" <texCoordNum> "]"\r
-*/\r
-optTexCoordNum\r
- optTexCoordNum_1 .or .true .emit 0x00;\r
-optTexCoordNum_1\r
- lbracket_ne .and texCoordNum .and rbracket;\r
-\r
-/*\r
- <texCoordNum> ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1\r
-*/\r
-texCoordNum\r
- integer;\r
-\r
-/*\r
- <statePaletteMatNum> ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1\r
-*/\r
-statePaletteMatNum\r
- integer;\r
-\r
-/*\r
- <stateProgramMatNum> ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1\r
-*/\r
-stateProgramMatNum\r
- integer;\r
-\r
-/*\r
- <programSingleItem> ::= <progEnvParam>\r
- | <progLocalParam>\r
-\r
-NOTE: <programSingleItem> has been modified for correct error handling. If program property\r
- is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.\r
-*/\r
-programSingleItem\r
- "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\r
-programSingleItem_1\r
- progEnvParam .or progLocalParam;\r
-\r
-/*\r
- <programMultipleItem> ::= <progEnvParams>\r
- | <progLocalParams>\r
-\r
-NOTE: <programMultipleItem> has been modified for correct error handling. If program property\r
- is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.\r
-*/\r
-programMultipleItem\r
- "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\r
-programMultipleItem_1\r
- progEnvParams .or progLocalParams;\r
-\r
-/*\r
- <progEnvParams> ::= "program" "." "env" \r
- "[" <progEnvParamNums> "]"\r
-\r
-NOTE: "program" "." has been moved to <programMultipleItem>.\r
-*/\r
-progEnvParams\r
- "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\r
-\r
-/*\r
- <progEnvParamNums> ::= <progEnvParamNum>\r
- | <progEnvParamNum> ".." <progEnvParamNum>\r
-*/\r
-progEnvParamNums\r
- progEnvParamNums_1 .or progEnvParamNums_2;\r
-progEnvParamNums_1\r
- progEnvParamNum .and dotdot_ne .and progEnvParamNum;\r
-progEnvParamNums_2\r
- progEnvParamNum .and .true .emit 0x00;\r
-\r
-/*\r
- <progEnvParam> ::= "program" "." "env" \r
- "[" <progEnvParamNum> "]"\r
-\r
-NOTE: "program" "." has been moved to <programSingleItem>.\r
-*/\r
-progEnvParam\r
- "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\r
-\r
-/*\r
- <progLocalParams> ::= "program" "." "local" \r
- "[" <progLocalParamNums> "]"\r
-\r
-NOTE: "program" "." has been moved to <programMultipleItem>.\r
-*/\r
-progLocalParams\r
- "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\r
-\r
-/*\r
- <progLocalParamNums> ::= <progLocalParamNum>\r
- | <progLocalParamNum> ".." <progLocalParamNum>\r
-*/\r
-progLocalParamNums\r
- progLocalParamNums_1 .or progLocalParamNums_2;\r
-progLocalParamNums_1\r
- progLocalParamNum .and dotdot_ne .and progLocalParamNum;\r
-progLocalParamNums_2\r
- progLocalParamNum .and .true .emit 0x00;\r
-\r
-/*\r
- <progLocalParam> ::= "program" "." "local" \r
- "[" <progLocalParamNum> "]"\r
-\r
-NOTE: "program" "." has been moved to <programSingleItem>.\r
-*/\r
-progLocalParam\r
- "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\r
-\r
-/*\r
- <progEnvParamNum> ::= <integer> from 0 to\r
- MAX_PROGRAM_ENV_PARAMETERS_ARB - 1\r
-*/\r
-progEnvParamNum\r
- integer;\r
-\r
-/*\r
- <progLocalParamNum> ::= <integer> from 0 to\r
- MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1\r
-*/\r
-progLocalParamNum\r
- integer;\r
-\r
-/*\r
- <paramConstDecl> ::= <paramConstScalarDecl>\r
- | <paramConstVector>\r
-*/\r
-paramConstDecl\r
- paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\r
-\r
-/*\r
- <paramConstUse> ::= <paramConstScalarUse>\r
- | <paramConstVector>\r
-*/\r
-paramConstUse\r
- paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\r
-\r
-/*\r
- <paramConstScalarDecl> ::= <signedFloatConstant>\r
-*/\r
-paramConstScalarDecl\r
- signedFloatConstant;\r
-\r
-/*\r
- <paramConstScalarUse> ::= <floatConstant>\r
-*/\r
-paramConstScalarUse\r
- floatConstant;\r
-\r
-/*\r
- <paramConstVector> ::= "{" <signedFloatConstant> "}"\r
- | "{" <signedFloatConstant> "," \r
- <signedFloatConstant> "}"\r
- | "{" <signedFloatConstant> "," \r
- <signedFloatConstant> ","\r
- <signedFloatConstant> "}"\r
- | "{" <signedFloatConstant> "," \r
- <signedFloatConstant> ","\r
- <signedFloatConstant> "," \r
- <signedFloatConstant> "}"\r
-*/\r
-paramConstVector\r
- paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\r
- paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\r
-paramConstVector_1\r
- lbrace_ne .and signedFloatConstant .and rbrace;\r
-paramConstVector_2\r
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\r
-paramConstVector_3\r
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\r
- signedFloatConstant .and rbrace;\r
-paramConstVector_4\r
- lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\r
- signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\r
-\r
-/*\r
- <signedFloatConstant> ::= <optionalSign> <floatConstant>\r
-*/\r
-signedFloatConstant\r
- optionalSign .and floatConstant;\r
-\r
-/*\r
- <floatConstant> ::= see text\r
- The <floatConstant> rule matches a floating-point constant consisting\r
- of an integer part, a decimal point, a fraction part, an "e" or\r
- "E", and an optionally signed integer exponent. The integer and\r
- fraction parts both consist of a sequence of one or more digits ("0"\r
- through "9"). Either the integer part or the fraction parts (not\r
- both) may be missing; either the decimal point or the "e" (or "E")\r
- and the exponent (not both) may be missing.\r
-*/\r
-floatConstant\r
- float;\r
-\r
-/*\r
- <optionalSign> ::= ""\r
- | "-"\r
- | "+"\r
-*/\r
-optionalSign\r
- optional_sign_ne;\r
-\r
-/*\r
- <TEMP_statement> ::= "TEMP" <varNameList>\r
-*/\r
-fp_TEMP_statement\r
- "TEMP" .and space .and fp_varNameList .and .true .emit 0x00;\r
-vp_TEMP_statement\r
- "TEMP" .and space .and vp_varNameList .and .true .emit 0x00;\r
-\r
-/*\r
-vertex program\r
- <ADDRESS_statement> ::= "ADDRESS" <varNameList>\r
-*/\r
-ADDRESS_statement\r
- "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00;\r
-\r
-/*\r
- <varNameList> ::= <establishName>\r
- | <establishName> "," <varNameList>\r
-*/\r
-fp_varNameList\r
- fp_varNameList_1 .or fp_establishName;\r
-vp_varNameList\r
- vp_varNameList_1 .or vp_establishName;\r
-fp_varNameList_1\r
- fp_establishName .and comma_ne .and fp_varNameList;\r
-vp_varNameList_1\r
- vp_establishName .and comma_ne .and vp_varNameList;\r
-\r
-/*\r
- <OUTPUT_statement> ::= "OUTPUT" <establishName> "="\r
- <resultBinding>\r
-*/\r
-fp_OUTPUT_statement\r
- "OUTPUT" .and space .and fp_establishName .and equal .and\r
- fp_resultBinding .error RESULT_EXPECTED;\r
-vp_OUTPUT_statement\r
- "OUTPUT" .and space .and vp_establishName .and equal .and\r
- vp_resultBinding .error RESULT_EXPECTED;\r
-\r
-/*\r
-fragment program\r
- <resultBinding> ::= "result" "." "color"\r
- | "result" "." "depth"\r
-\r
-vertex program\r
- <resultBinding> ::= "result" "." "position"\r
- | "result" "." <resultColBinding>\r
- | "result" "." "fogcoord"\r
- | "result" "." "pointsize"\r
- | "result" "." "texcoord" <optTexCoordNum>\r
-*/\r
-fp_resultBinding\r
- "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\r
-vp_resultBinding\r
- "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\r
-fp_resultBinding_1\r
- "color" .emit FRAGMENT_RESULT_COLOR .or\r
- "depth" .emit FRAGMENT_RESULT_DEPTH;\r
-vp_resultBinding_1\r
- .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or\r
- resultColBinding .emit VERTEX_RESULT_COLOR .or\r
- "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or\r
- "pointsize" .emit VERTEX_RESULT_POINTSIZE .or\r
- vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\r
-vp_resultBinding_2\r
- "texcoord" .and optTexCoordNum;\r
-\r
-/*\r
-vertex program\r
- <resultColBinding> ::= "color" <optFaceType> <optColorType>\r
-*/\r
-resultColBinding\r
- "color" .and optFaceType .and optColorType;\r
-\r
-/*\r
- <optFaceType> ::= ""\r
- | "." "front"\r
- | "." "back"\r
-*/\r
-optFaceType\r
- FaceType .or .true .emit FACE_FRONT;\r
-FaceType\r
- dot_ne .and FaceProperty;\r
-FaceProperty\r
- "front" .emit FACE_FRONT .or "back" .emit FACE_BACK;\r
-\r
-/*\r
- <optColorType> ::= ""\r
- | "." "primary"\r
- | "." "secondary"\r
-*/\r
-optColorType\r
- ColorType .or .true .emit COLOR_PRIMARY;\r
-ColorType\r
- dot_ne .and ColorProperty;\r
-ColorProperty\r
- "primary" .emit COLOR_PRIMARY .or\r
- .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY;\r
-\r
-/*\r
- <ALIAS_statement> ::= "ALIAS" <establishName> "="\r
- <establishedName>\r
-*/\r
-fp_ALIAS_statement\r
- "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\r
-vp_ALIAS_statement\r
- "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\r
-fp_ALIAS_statement_1\r
- space .and fp_establishName;\r
-vp_ALIAS_statement_1\r
- space .and vp_establishName;\r
-\r
-/*\r
- <establishName> ::= <identifier>\r
-*/\r
-fp_establishName\r
- fp_identifier;\r
-vp_establishName\r
- vp_identifier;\r
-\r
-/*\r
- <establishedName> ::= <identifier>\r
-*/\r
-fp_establishedName\r
- fp_identifier;\r
-vp_establishedName\r
- vp_identifier;\r
-fp_establishedName_no_error_on_identifier\r
- fp_identifier_ne;\r
-vp_establishedName_no_error_on_identifier\r
- vp_identifier_ne;\r
-\r
-/*\r
-fragment program\r
- <identifier> ::= see text\r
- The <identifier> rule matches a sequence of one or more letters ("A"\r
- through "Z", "a" through "z"), digits ("0" through "9), underscores \r
- ("_"), or dollar signs ("$"); the first character must not be a \r
- number. Upper and lower case letters are considered different \r
- (names are case-sensitive). The following strings are reserved \r
- keywords and may not be used as identifiers:\r
-\r
- ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,\r
- COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT, \r
- END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2, \r
- LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT, \r
- MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM, \r
- POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS, \r
- SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT, \r
- TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT, \r
- fragment, program, result, state, and texture.\r
-\r
-vertex program\r
- <identifier> ::= see text\r
- The <identifier> rule matches a sequence of one or more letters ("A"\r
- through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),\r
- or dollar signs ("$"); the first character must not be a number. Upper\r
- and lower case letters are considered different (names are\r
- case-sensitive). The following strings are reserved keywords and may not\r
- be used as identifiers:\r
-\r
- ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,\r
- EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,\r
- PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,\r
- state, and vertex.\r
-*/\r
-fp_identifier\r
- fp_identifier_ne .error IDENTIFIER_EXPECTED;\r
-vp_identifier\r
- vp_identifier_ne .error IDENTIFIER_EXPECTED;\r
-fp_identifier_ne\r
- fp_not_reserved_identifier .and identifier_ne;\r
-vp_identifier_ne\r
- vp_not_reserved_identifier .and identifier_ne;\r
-\r
-fp_not_reserved_identifier\r
- fp_not_reserved_identifier_1 .or .true;\r
-fp_not_reserved_identifier_1\r
- fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\r
-vp_not_reserved_identifier\r
- vp_not_reserved_identifier_1 .or .true;\r
-vp_not_reserved_identifier_1\r
- vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\r
-\r
-fp_reserved_identifier\r
- "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or\r
- "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or\r
- "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or\r
- "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or\r
- "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or\r
- "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or\r
- "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or\r
- "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or\r
- "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or\r
- "fragment" .or "program" .or "result" .or "state" .or "texture";\r
-vp_reserved_identifier\r
- "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or\r
- "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or\r
- "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or\r
- "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or\r
- "XPD" .or "program" .or "result" .or "state" .or "vertex";\r
-\r
-/*\r
- The <integer> rule matches an integer constant. The integer consists\r
- of a sequence of one or more digits ("0" through "9").\r
-*/\r
-integer\r
- integer_ne .error INTEGER_EXPECTED;\r
-\r
-zero\r
- '0';\r
-\r
-leading_zeroes\r
- .loop zero;\r
-\r
-no_digit\r
- no_digit_1 .or .true;\r
-no_digit_1\r
- digit10 .and .false .error INTEGER_OUT_OF_RANGE;\r
-\r
-all_zeroes\r
- all_zeroes_1 .or no_digit_1;\r
-all_zeroes_1\r
- '0' .and .loop zero .and no_digit;\r
-\r
-integer_0_3\r
- integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\r
-integer_0_3_1\r
- integer_0_3_2 .or all_zeroes .emit '0';\r
-integer_0_3_2 /* [1, 3] */\r
- leading_zeroes .and '1'-'3' .emit * .and no_digit;\r
-\r
-integer_0_63\r
- integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\r
-integer_0_63_1\r
- integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\r
- all_zeroes .emit '0';\r
-integer_0_63_2 /* [7, 9] */\r
- leading_zeroes .and '7'-'9' .emit * .and no_digit;\r
-integer_0_63_3 /* [10, 59] */\r
- leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\r
-integer_0_63_4 /* [60, 63] */\r
- leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\r
-integer_0_63_5 /* [1, 6] */\r
- leading_zeroes .and '1'-'6' .emit * .and no_digit;\r
-\r
-integer_0_64\r
- integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\r
-integer_0_64_1\r
- integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\r
- all_zeroes .emit '0';\r
-integer_0_64_2 /* [7, 9] */\r
- leading_zeroes .and '7'-'9' .emit * .and no_digit;\r
-integer_0_64_3 /* [10, 59] */\r
- leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\r
-integer_0_64_4 /* [60, 64] */\r
- leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\r
-integer_0_64_5 /* [1, 6] */\r
- leading_zeroes .and '1'-'6' .emit * .and no_digit;\r
-\r
-optional_space\r
- space .or .true;\r
-\r
-space_dst\r
- space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\r
-\r
-space_src\r
- space .error OPERATION_NEEDS_SOURCE_VARIABLE;\r
-\r
-space\r
- single_space .and .loop single_space;\r
-\r
-single_space\r
- white_char .or comment_block;\r
-\r
-white_char\r
- ' ' .or '\t' .or '\n' .or '\r';\r
-\r
-comment_block\r
- '#' .and .loop comment_char .and new_line;\r
-\r
-/* All ASCII characters except '\r', '\n' and '\0' */\r
-comment_char\r
- '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';\r
-\r
-new_line\r
- '\n' .or crlf .or '\0';\r
-\r
-crlf\r
- '\r' .and '\n';\r
-\r
-semicolon\r
- optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\r
-\r
-comma\r
- optional_space .and ',' .error MISSING_COMMA .and optional_space;\r
-\r
-comma_ne\r
- optional_space .and ',' .and optional_space;\r
-\r
-lbracket\r
- optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\r
-\r
-lbracket_ne\r
- optional_space .and '[' .and optional_space;\r
-\r
-rbracket\r
- optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\r
-\r
-dot\r
- optional_space .and '.' .error MISSING_DOT .and optional_space;\r
-\r
-dot_ne\r
- optional_space .and '.' .and optional_space;\r
-\r
-equal\r
- optional_space .and '=' .error MISSING_EQUAL .and optional_space;\r
-\r
-lbrace\r
- optional_space .and '{' .error MISSING_LBRACE .and optional_space;\r
-\r
-lbrace_ne\r
- optional_space .and '{' .and optional_space;\r
-\r
-rbrace\r
- optional_space .and '}' .error MISSING_RBRACE .and optional_space;\r
-\r
-dotdot\r
- optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\r
-\r
-dotdot_ne\r
- optional_space .and '.' .and '.' .and optional_space;\r
-\r
-/*\r
- The definition below accepts the following floating point number formats:\r
- .99 .99e99 99. 99.99 99.99e99 99.e99 99e99\r
- Also 99 format was considered and accepted because of a large number of existing program\r
- strings with such a format.\r
-*/\r
-float\r
- float_1 .or float_2 .or float_legacy;\r
-float_1\r
- '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\r
-float_2\r
- integer_ne .and float_3;\r
-float_3\r
- float_4 .or float_5;\r
-float_4\r
- '.' .and optional_integer .and optional_exponent;\r
-float_5\r
- exponent .emit 0x00;\r
-float_legacy\r
- integer_ne .and .true .emit 0x00 .emit 0x00;\r
-\r
-/*\r
- Below is a correct version of <float> definiton.\r
-*/\r
-/*\r
-float\r
- float_1 .or float_2;\r
-float_1\r
- '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\r
-float_2\r
- integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT;\r
-float_3\r
- float_4 .or float_5;\r
-float_4\r
- '.' .and optional_integer .and optional_exponent;\r
-float_5\r
- exponent .emit 0x00;\r
-*/\r
-\r
-integer_ne\r
- integer_ne_1 .and .true .emit 0x00 .emit $;\r
-integer_ne_1\r
- digit10 .emit * .and .loop digit10 .emit *;\r
-\r
-optional_integer\r
- integer_ne .or .true .emit 0x00;\r
-\r
-/*\r
-NOTE: If exponent part is omited we treat it as if it was "E+1".\r
-*/\r
-optional_exponent\r
- exponent .or .true .emit 0x00;\r
-\r
-exponent\r
- exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\r
-exponent_1\r
- 'e' .or 'E';\r
-\r
-optional_sign_ne\r
- minus_ne .or plus_ne .or .true;\r
-\r
-plus_ne\r
- optional_space .and '+' .and optional_space;\r
-\r
-minus_ne\r
- optional_space .and '-' .emit '-' .and optional_space;\r
-\r
-identifier_ne\r
- first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\r
-\r
-follow_idchar\r
- first_idchar .or digit10;\r
-\r
-first_idchar\r
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\r
-\r
-digit10\r
- '0'-'9';\r
-\r
-/*\r
- string filtering - if a string is encountered in grammar ("blabla"), the symbol below is\r
- executed to create the string. The symbol must not throw any errors and emit bytes - it should\r
- stop if it encounters invalid character. After this the resulting string (from starting\r
- position up to the invalid character (but without it) is compared with the grammar string.\r
-*/\r
-.string __string_filter;\r
-\r
-__string_filter\r
- .loop __identifier_char;\r
-\r
-__identifier_char\r
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\r
-\r
-/*\r
- error token filtering\r
-*/\r
-e_signature\r
- e_signature_char .and .loop e_signature_char;\r
-e_signature_char\r
- '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\r
-\r
-e_statement\r
- .loop e_statement_not_term;\r
-/* All ASCII characters to one of '\r', '\n', '\0' and ';' */\r
-e_statement_not_term\r
- '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C';\r
-\r
-e_identifier\r
- e_identifier_first .and .loop e_identifier_next;\r
-e_identifier_first\r
- 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\r
-e_identifier_next\r
- e_identifier_first .or '0'-'9';\r
-\r
-e_token\r
- e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\r
- '-' .or ',' .or ';';\r
-e_token_number\r
- e_token_digit .and .loop e_token_digit;\r
-e_token_digit\r
- '0'-'9';\r
-\r
-e_charordigit\r
- 'A'-'Z' .or 'a'-'z' .or '0'-'9';\r
-\r
+.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';
+
-".syntax program;\n"\r
-".emtcode REVISION 0x07\n"\r
-".emtcode FRAGMENT_PROGRAM 0x01\n"\r
-".emtcode VERTEX_PROGRAM 0x02\n"\r
-".emtcode OPTION 0x01\n"\r
-".emtcode INSTRUCTION 0x02\n"\r
-".emtcode DECLARATION 0x03\n"\r
-".emtcode END 0x04\n"\r
-".emtcode ARB_PRECISION_HINT_FASTEST 0x01\n"\r
-".emtcode ARB_PRECISION_HINT_NICEST 0x02\n"\r
-".emtcode ARB_FOG_EXP 0x04\n"\r
-".emtcode ARB_FOG_EXP2 0x08\n"\r
-".emtcode ARB_FOG_LINEAR 0x10\n"\r
-".emtcode ARB_POSITION_INVARIANT 0x20\n"\r
-".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40\n"\r
-".emtcode OP_ALU_INST 0x00\n"\r
-".emtcode OP_TEX_INST 0x01\n"\r
-".emtcode OP_ALU_VECTOR 0x00\n"\r
-".emtcode OP_ALU_SCALAR 0x01\n"\r
-".emtcode OP_ALU_BINSC 0x02\n"\r
-".emtcode OP_ALU_BIN 0x03\n"\r
-".emtcode OP_ALU_TRI 0x04\n"\r
-".emtcode OP_ALU_SWZ 0x05\n"\r
-".emtcode OP_TEX_SAMPLE 0x06\n"\r
-".emtcode OP_TEX_KIL 0x07\n"\r
-".emtcode OP_ALU_ARL 0x08\n"\r
-".emtcode OP_ABS 0x00\n"\r
-".emtcode OP_ABS_SAT 0x1B\n"\r
-".emtcode OP_FLR 0x09\n"\r
-".emtcode OP_FLR_SAT 0x26\n"\r
-".emtcode OP_FRC 0x0A\n"\r
-".emtcode OP_FRC_SAT 0x27\n"\r
-".emtcode OP_LIT 0x0C\n"\r
-".emtcode OP_LIT_SAT 0x2A\n"\r
-".emtcode OP_MOV 0x11\n"\r
-".emtcode OP_MOV_SAT 0x30\n"\r
-".emtcode OP_COS 0x1F\n"\r
-".emtcode OP_COS_SAT 0x20\n"\r
-".emtcode OP_EX2 0x07\n"\r
-".emtcode OP_EX2_SAT 0x25\n"\r
-".emtcode OP_LG2 0x0B\n"\r
-".emtcode OP_LG2_SAT 0x29\n"\r
-".emtcode OP_RCP 0x14\n"\r
-".emtcode OP_RCP_SAT 0x33\n"\r
-".emtcode OP_RSQ 0x15\n"\r
-".emtcode OP_RSQ_SAT 0x34\n"\r
-".emtcode OP_SIN 0x38\n"\r
-".emtcode OP_SIN_SAT 0x39\n"\r
-".emtcode OP_SCS 0x35\n"\r
-".emtcode OP_SCS_SAT 0x36\n"\r
-".emtcode OP_POW 0x13\n"\r
-".emtcode OP_POW_SAT 0x32\n"\r
-".emtcode OP_ADD 0x01\n"\r
-".emtcode OP_ADD_SAT 0x1C\n"\r
-".emtcode OP_DP3 0x03\n"\r
-".emtcode OP_DP3_SAT 0x21\n"\r
-".emtcode OP_DP4 0x04\n"\r
-".emtcode OP_DP4_SAT 0x22\n"\r
-".emtcode OP_DPH 0x05\n"\r
-".emtcode OP_DPH_SAT 0x23\n"\r
-".emtcode OP_DST 0x06\n"\r
-".emtcode OP_DST_SAT 0x24\n"\r
-".emtcode OP_MAX 0x0F\n"\r
-".emtcode OP_MAX_SAT 0x2E\n"\r
-".emtcode OP_MIN 0x10\n"\r
-".emtcode OP_MIN_SAT 0x2F\n"\r
-".emtcode OP_MUL 0x12\n"\r
-".emtcode OP_MUL_SAT 0x31\n"\r
-".emtcode OP_SGE 0x16\n"\r
-".emtcode OP_SGE_SAT 0x37\n"\r
-".emtcode OP_SLT 0x17\n"\r
-".emtcode OP_SLT_SAT 0x3A\n"\r
-".emtcode OP_SUB 0x18\n"\r
-".emtcode OP_SUB_SAT 0x3B\n"\r
-".emtcode OP_XPD 0x1A\n"\r
-".emtcode OP_XPD_SAT 0x43\n"\r
-".emtcode OP_CMP 0x1D\n"\r
-".emtcode OP_CMP_SAT 0x1E\n"\r
-".emtcode OP_LRP 0x2B\n"\r
-".emtcode OP_LRP_SAT 0x2C\n"\r
-".emtcode OP_MAD 0x0E\n"\r
-".emtcode OP_MAD_SAT 0x2D\n"\r
-".emtcode OP_SWZ 0x19\n"\r
-".emtcode OP_SWZ_SAT 0x3C\n"\r
-".emtcode OP_TEX 0x3D\n"\r
-".emtcode OP_TEX_SAT 0x3E\n"\r
-".emtcode OP_TXB 0x3F\n"\r
-".emtcode OP_TXB_SAT 0x40\n"\r
-".emtcode OP_TXP 0x41\n"\r
-".emtcode OP_TXP_SAT 0x42\n"\r
-".emtcode OP_KIL 0x28\n"\r
-".emtcode OP_ARL 0x02\n"\r
-".emtcode OP_EXP 0x08\n"\r
-".emtcode OP_LOG 0x0D\n"\r
-".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n"\r
-".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n"\r
-".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n"\r
-".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n"\r
-".emtcode VERTEX_ATTRIB_POSITION 0x01\n"\r
-".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n"\r
-".emtcode VERTEX_ATTRIB_NORMAL 0x03\n"\r
-".emtcode VERTEX_ATTRIB_COLOR 0x04\n"\r
-".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n"\r
-".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n"\r
-".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n"\r
-".emtcode VERTEX_ATTRIB_GENERIC 0x08\n"\r
-".emtcode FRAGMENT_RESULT_COLOR 0x01\n"\r
-".emtcode FRAGMENT_RESULT_DEPTH 0x02\n"\r
-".emtcode VERTEX_RESULT_POSITION 0x01\n"\r
-".emtcode VERTEX_RESULT_COLOR 0x02\n"\r
-".emtcode VERTEX_RESULT_FOGCOORD 0x03\n"\r
-".emtcode VERTEX_RESULT_POINTSIZE 0x04\n"\r
-".emtcode VERTEX_RESULT_TEXCOORD 0x05\n"\r
-".emtcode TEXTARGET_1D 0x01\n"\r
-".emtcode TEXTARGET_2D 0x02\n"\r
-".emtcode TEXTARGET_3D 0x03\n"\r
-".emtcode TEXTARGET_RECT 0x04\n"\r
-".emtcode TEXTARGET_CUBE 0x05\n"\r
-".emtcode TEXTARGET_SHADOW1D 0x06\n"\r
-".emtcode TEXTARGET_SHADOW2D 0x07\n"\r
-".emtcode TEXTARGET_SHADOWRECT 0x08\n"\r
-".emtcode FACE_FRONT 0x00\n"\r
-".emtcode FACE_BACK 0x01\n"\r
-".emtcode COLOR_PRIMARY 0x00\n"\r
-".emtcode COLOR_SECONDARY 0x01\n"\r
-".emtcode COMPONENT_X 0x00\n"\r
-".emtcode COMPONENT_Y 0x01\n"\r
-".emtcode COMPONENT_Z 0x02\n"\r
-".emtcode COMPONENT_W 0x03\n"\r
-".emtcode COMPONENT_0 0x04\n"\r
-".emtcode COMPONENT_1 0x05\n"\r
-".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n"\r
-".emtcode ARRAY_INDEX_RELATIVE 0x01\n"\r
-".emtcode MATRIX_MODELVIEW 0x01\n"\r
-".emtcode MATRIX_PROJECTION 0x02\n"\r
-".emtcode MATRIX_MVP 0x03\n"\r
-".emtcode MATRIX_TEXTURE 0x04\n"\r
-".emtcode MATRIX_PALETTE 0x05\n"\r
-".emtcode MATRIX_PROGRAM 0x06\n"\r
-".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n"\r
-".emtcode MATRIX_MODIFIER_INVERSE 0x01\n"\r
-".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n"\r
-".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n"\r
-".emtcode CONSTANT_SCALAR 0x01\n"\r
-".emtcode CONSTANT_VECTOR 0x02\n"\r
-".emtcode PROGRAM_PARAM_ENV 0x01\n"\r
-".emtcode PROGRAM_PARAM_LOCAL 0x02\n"\r
-".emtcode REGISTER_ATTRIB 0x01\n"\r
-".emtcode REGISTER_PARAM 0x02\n"\r
-".emtcode REGISTER_RESULT 0x03\n"\r
-".emtcode REGISTER_ESTABLISHED_NAME 0x04\n"\r
-".emtcode PARAM_NULL 0x00\n"\r
-".emtcode PARAM_ARRAY_ELEMENT 0x01\n"\r
-".emtcode PARAM_STATE_ELEMENT 0x02\n"\r
-".emtcode PARAM_PROGRAM_ELEMENT 0x03\n"\r
-".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n"\r
-".emtcode PARAM_CONSTANT 0x05\n"\r
-".emtcode STATE_MATERIAL 0x01\n"\r
-".emtcode STATE_LIGHT 0x02\n"\r
-".emtcode STATE_LIGHT_MODEL 0x03\n"\r
-".emtcode STATE_LIGHT_PROD 0x04\n"\r
-".emtcode STATE_FOG 0x05\n"\r
-".emtcode STATE_MATRIX_ROWS 0x06\n"\r
-".emtcode STATE_TEX_ENV 0x07\n"\r
-".emtcode STATE_DEPTH 0x08\n"\r
-".emtcode STATE_TEX_GEN 0x09\n"\r
-".emtcode STATE_CLIP_PLANE 0x0A\n"\r
-".emtcode STATE_POINT 0x0B\n"\r
-".emtcode MATERIAL_AMBIENT 0x01\n"\r
-".emtcode MATERIAL_DIFFUSE 0x02\n"\r
-".emtcode MATERIAL_SPECULAR 0x03\n"\r
-".emtcode MATERIAL_EMISSION 0x04\n"\r
-".emtcode MATERIAL_SHININESS 0x05\n"\r
-".emtcode LIGHT_AMBIENT 0x01\n"\r
-".emtcode LIGHT_DIFFUSE 0x02\n"\r
-".emtcode LIGHT_SPECULAR 0x03\n"\r
-".emtcode LIGHT_POSITION 0x04\n"\r
-".emtcode LIGHT_ATTENUATION 0x05\n"\r
-".emtcode LIGHT_HALF 0x06\n"\r
-".emtcode LIGHT_SPOT_DIRECTION 0x07\n"\r
-".emtcode LIGHT_MODEL_AMBIENT 0x01\n"\r
-".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n"\r
-".emtcode LIGHT_PROD_AMBIENT 0x01\n"\r
-".emtcode LIGHT_PROD_DIFFUSE 0x02\n"\r
-".emtcode LIGHT_PROD_SPECULAR 0x03\n"\r
-".emtcode TEX_ENV_COLOR 0x01\n"\r
-".emtcode TEX_GEN_EYE 0x01\n"\r
-".emtcode TEX_GEN_OBJECT 0x02\n"\r
-".emtcode FOG_COLOR 0x01\n"\r
-".emtcode FOG_PARAMS 0x02\n"\r
-".emtcode DEPTH_RANGE 0x01\n"\r
-".emtcode POINT_SIZE 0x01\n"\r
-".emtcode POINT_ATTENUATION 0x02\n"\r
-".emtcode ATTRIB 0x01\n"\r
-".emtcode PARAM 0x02\n"\r
-".emtcode TEMP 0x03\n"\r
-".emtcode OUTPUT 0x04\n"\r
-".emtcode ALIAS 0x05\n"\r
-".emtcode ADDRESS 0x06\n"\r
-".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n"\r
-".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n"\r
-".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n"\r
-".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n"\r
-".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n"\r
-".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n"\r
-".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n"\r
-".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n"\r
-".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n"\r
-".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n"\r
-".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n"\r
-".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n"\r
-".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n"\r
-".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n"\r
-".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n"\r
-".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n"\r
-".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n"\r
-".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n"\r
-".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n"\r
-".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n"\r
-".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n"\r
-".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n"\r
-".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n"\r
-".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n"\r
-".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n"\r
-".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n"\r
-".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n"\r
-".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n"\r
-".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n"\r
-".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n"\r
-".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n"\r
-".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n"\r
-".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n"\r
-".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n"\r
-".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n"\r
-".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n"\r
-".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n"\r
-".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n"\r
-".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n"\r
-".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n"\r
-".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n"\r
-".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n"\r
-".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n"\r
-".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n"\r
-".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n"\r
-".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n"\r
-".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n"\r
-".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n"\r
-".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n"\r
-".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n"\r
-".regbyte vertex_blend 0x00\n"\r
-".regbyte matrix_palette 0x00\n"\r
-".regbyte point_parameters 0x01\n"\r
-".regbyte secondary_color 0x01\n"\r
-".regbyte fog_coord 0x01\n"\r
-".regbyte texture_rectangle 0x01\n"\r
-".regbyte fragment_program_shadow 0x00\n"\r
-".regbyte ARB_precision_hint_fastest 0x00\n"\r
-".regbyte ARB_precision_hint_nicest 0x00\n"\r
-".regbyte ARB_fog_exp 0x00\n"\r
-".regbyte ARB_fog_exp2 0x00\n"\r
-".regbyte ARB_fog_linear 0x00\n"\r
-".regbyte ARB_position_invariant 0x00\n"\r
-".regbyte ARB_fragment_program_shadow 0x00\n"\r
-".regbyte program_target 0x00\n"\r
-"program\n"\r
-" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n"\r
-"programs\n"\r
-" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n"\r
-" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n"\r
-"frag_program_1_0\n"\r
-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n"\r
-" optional_space .and fp_optionSequence .and fp_statementSequence .and\n"\r
-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"\r
-" '\\0' .error CODE_AFTER_END;\n"\r
-"vert_program_1_0\n"\r
-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n"\r
-" optional_space .and vp_optionSequence .and vp_statementSequence .and\n"\r
-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"\r
-" '\\0' .error CODE_AFTER_END;\n"\r
-"fp_optionSequence\n"\r
-" .loop fp_option;\n"\r
-"vp_optionSequence\n"\r
-" .loop vp_option;\n"\r
-"fp_option\n"\r
-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"\r
-" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"\r
-"vp_option\n"\r
-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"\r
-" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"\r
-"fp_optionString\n"\r
-" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n"\r
-" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n"\r
-" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n"\r
-" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n"\r
-" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n"\r
-" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n"\r
-" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n"\r
-" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n"\r
-" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;\n"\r
-"vp_optionString\n"\r
-" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n"\r
-"fp_ARB_fog_exp\n"\r
-" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n"\r
-"fp_ARB_fog_exp2\n"\r
-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n"\r
-"fp_ARB_fog_linear\n"\r
-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n"\r
-"fp_statementSequence\n"\r
-" .loop fp_statement;\n"\r
-"vp_statementSequence\n"\r
-" .loop vp_statement;\n"\r
-"fp_statement\n"\r
-" fp_statement_1 .or fp_statement_2;\n"\r
-"vp_statement\n"\r
-" vp_statement_1 .or vp_statement_2;\n"\r
-"fp_statement_1\n"\r
-" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"\r
-"fp_statement_2\n"\r
-" fp_namingStatement .emit DECLARATION .and semicolon;\n"\r
-"vp_statement_1\n"\r
-" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"\r
-"vp_statement_2\n"\r
-" vp_namingStatement .emit DECLARATION .and semicolon;\n"\r
-"fp_instruction\n"\r
-" ALUInstruction .emit OP_ALU_INST .or\n"\r
-" TexInstruction .emit OP_TEX_INST;\n"\r
-"vp_instruction\n"\r
-" ARL_instruction .emit OP_ALU_ARL .or\n"\r
-" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"\r
-" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"\r
-" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"\r
-" vp_BINop_instruction .emit OP_ALU_BIN .or\n"\r
-" vp_TRIop_instruction .emit OP_ALU_TRI .or\n"\r
-" vp_SWZ_instruction .emit OP_ALU_SWZ;\n"\r
-"ALUInstruction\n"\r
-" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"\r
-" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"\r
-" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"\r
-" fp_BINop_instruction .emit OP_ALU_BIN .or\n"\r
-" fp_TRIop_instruction .emit OP_ALU_TRI .or\n"\r
-" fp_SWZ_instruction .emit OP_ALU_SWZ;\n"\r
-"TexInstruction\n"\r
-" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n"\r
-" KIL_instruction .emit OP_TEX_KIL;\n"\r
-"ARL_instruction\n"\r
-" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n"\r
-"fp_VECTORop_instruction\n"\r
-" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n"\r
-"vp_VECTORop_instruction\n"\r
-" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n"\r
-"fp_VECTORop\n"\r
-" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n"\r
-" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n"\r
-" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n"\r
-" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n"\r
-" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n"\r
-"vp_VECTORop\n"\r
-" \"ABS\" .emit OP_ABS .or\n"\r
-" \"FLR\" .emit OP_FLR .or\n"\r
-" \"FRC\" .emit OP_FRC .or\n"\r
-" \"LIT\" .emit OP_LIT .or\n"\r
-" \"MOV\" .emit OP_MOV;\n"\r
-"fp_SCALARop_instruction\n"\r
-" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n"\r
-"vp_SCALARop_instruction\n"\r
-" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n"\r
-"fp_SCALARop\n"\r
-" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n"\r
-" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n"\r
-" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n"\r
-" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n"\r
-" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n"\r
-" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n"\r
-" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n"\r
-"vp_SCALARop\n"\r
-" \"EX2\" .emit OP_EX2 .or\n"\r
-" \"EXP\" .emit OP_EXP .or\n"\r
-" \"LG2\" .emit OP_LG2 .or\n"\r
-" \"LOG\" .emit OP_LOG .or\n"\r
-" \"RCP\" .emit OP_RCP .or\n"\r
-" \"RSQ\" .emit OP_RSQ;\n"\r
-"fp_BINSCop_instruction\n"\r
-" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n"\r
-" fp_scalarSrcReg;\n"\r
-"vp_BINSCop_instruction\n"\r
-" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n"\r
-" vp_scalarSrcReg;\n"\r
-"fp_BINSCop\n"\r
-" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n"\r
-"vp_BINSCop\n"\r
-" \"POW\" .emit OP_POW;\n"\r
-"fp_BINop_instruction\n"\r
-" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"\r
-" vectorSrcReg;\n"\r
-"vp_BINop_instruction\n"\r
-" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"\r
-" swizzleSrcReg;\n"\r
-"fp_BINop\n"\r
-" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n"\r
-" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n"\r
-" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n"\r
-" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n"\r
-" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n"\r
-" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n"\r
-" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n"\r
-" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n"\r
-" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n"\r
-" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n"\r
-" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n"\r
-" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n"\r
-"vp_BINop\n"\r
-" \"ADD\" .emit OP_ADD .or\n"\r
-" \"DP3\" .emit OP_DP3 .or\n"\r
-" \"DP4\" .emit OP_DP4 .or\n"\r
-" \"DPH\" .emit OP_DPH .or\n"\r
-" \"DST\" .emit OP_DST .or\n"\r
-" \"MAX\" .emit OP_MAX .or\n"\r
-" \"MIN\" .emit OP_MIN .or\n"\r
-" \"MUL\" .emit OP_MUL .or\n"\r
-" \"SGE\" .emit OP_SGE .or\n"\r
-" \"SLT\" .emit OP_SLT .or\n"\r
-" \"SUB\" .emit OP_SUB .or\n"\r
-" \"XPD\" .emit OP_XPD;\n"\r
-"fp_TRIop_instruction\n"\r
-" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"\r
-" vectorSrcReg .and comma .and vectorSrcReg;\n"\r
-"vp_TRIop_instruction\n"\r
-" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"\r
-" swizzleSrcReg .and comma .and swizzleSrcReg;\n"\r
-"fp_TRIop\n"\r
-" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n"\r
-" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n"\r
-" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n"\r
-"vp_TRIop\n"\r
-" \"MAD\" .emit OP_MAD;\n"\r
-"fp_SWZ_instruction\n"\r
-" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n"\r
-" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"vp_SWZ_instruction\n"\r
-" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n"\r
-" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"SWZop\n"\r
-" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n"\r
-"SAMPLE_instruction\n"\r
-" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"\r
-" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n"\r
-"SAMPLEop\n"\r
-" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n"\r
-" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n"\r
-" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n"\r
-"KIL_instruction\n"\r
-" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n"\r
-"texImageUnit\n"\r
-" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n"\r
-"texTarget\n"\r
-" \"1D\" .emit TEXTARGET_1D .or\n"\r
-" \"2D\" .emit TEXTARGET_2D .or\n"\r
-" \"3D\" .emit TEXTARGET_3D .or\n"\r
-" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n"\r
-" \"CUBE\" .emit TEXTARGET_CUBE .or\n"\r
-" .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\n"\r
-"shadowTarget\n"\r
-" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n"\r
-" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n"\r
-" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT;\n"\r
-"optTexImageUnitNum\n"\r
-" optTexImageUnitNum_1 .or .true .emit 0x00;\n"\r
-"optTexImageUnitNum_1\n"\r
-" lbracket_ne .and texImageUnitNum .and rbracket;\n"\r
-"texImageUnitNum\n"\r
-" integer;\n"\r
-"fp_scalarSrcReg\n"\r
-" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n"\r
-"vp_scalarSrcReg\n"\r
-" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n"\r
-"swizzleSrcReg\n"\r
-" optionalSign .and vp_srcReg .and swizzleSuffix;\n"\r
-"vectorSrcReg\n"\r
-" optionalSign .and fp_srcReg .and optionalSuffix;\n"\r
-"fp_maskedDstReg\n"\r
-" fp_dstReg .and fp_optionalMask;\n"\r
-"vp_maskedDstReg\n"\r
-" vp_dstReg .and vp_optionalMask;\n"\r
-"maskedAddrReg\n"\r
-" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n"\r
-"fp_extendedSwizzle\n"\r
-" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n"\r
-"vp_extendedSwizzle\n"\r
-" extSwizComp .and comma .and\n"\r
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"xyzwExtendedSwizzle\n"\r
-" xyzwExtSwizComp .and comma .and\n"\r
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"rgbaExtendedSwizzle\n"\r
-" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n"\r
-" rgbaExtendedSwizzle_4;\n"\r
-"rgbaExtendedSwizzle_1\n"\r
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"\r
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n"\r
-"rgbaExtendedSwizzle_2\n"\r
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"\r
-" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"rgbaExtendedSwizzle_3\n"\r
-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n"\r
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"rgbaExtendedSwizzle_4\n"\r
-" rgbaExtSwizComp_alpha .and comma .and \n"\r
-"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"\r
-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"\r
-"xyzwExtSwizComp\n"\r
-" optionalSign .and xyzwExtSwizSel;\n"\r
-"rgbaExtSwizComp\n"\r
-" optionalSign .and rgbaExtSwizSel;\n"\r
-"rgbaExtSwizComp_digit\n"\r
-" optionalSign .and rgbaExtSwizSel_digit;\n"\r
-"rgbaExtSwizComp_alpha\n"\r
-" optionalSign .and rgbaExtSwizSel_alpha;\n"\r
-"extSwizComp\n"\r
-" optionalSign .and extSwizSel;\n"\r
-"xyzwExtSwizSel\n"\r
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n"\r
-"rgbaExtSwizSel\n"\r
-" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n"\r
-"rgbaExtSwizSel_digit\n"\r
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n"\r
-"rgbaExtSwizSel_alpha\n"\r
-" rgbaComponent_single;\n"\r
-"extSwizSel\n"\r
-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n"\r
-"fp_srcReg\n"\r
-" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"\r
-"vp_srcReg\n"\r
-" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"\r
-"fp_srcReg_1\n"\r
-" fragmentAttribReg .emit REGISTER_ATTRIB .or\n"\r
-" fp_progParamReg .emit REGISTER_PARAM .or\n"\r
-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"\r
-"vp_srcReg_1\n"\r
-" vertexAttribReg .emit REGISTER_ATTRIB .or\n"\r
-" vp_progParamReg .emit REGISTER_PARAM .or\n"\r
-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"\r
-"fp_dstReg\n"\r
-" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"\r
-"vp_dstReg\n"\r
-" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"\r
-"fp_dstReg_1\n"\r
-" fragmentResultReg .emit REGISTER_RESULT .or\n"\r
-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"\r
-"vp_dstReg_1\n"\r
-" vertexResultReg .emit REGISTER_RESULT .or\n"\r
-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"\r
-"fragmentAttribReg\n"\r
-" fragAttribBinding;\n"\r
-"vertexAttribReg\n"\r
-" vtxAttribBinding;\n"\r
-"fp_temporaryReg\n"\r
-" fp_establishedName_no_error_on_identifier;\n"\r
-"vp_temporaryReg\n"\r
-" vp_establishedName_no_error_on_identifier;\n"\r
-"fp_progParamReg\n"\r
-" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n"\r
-"vp_progParamReg\n"\r
-" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n"\r
-"fp_progParamReg_1\n"\r
-" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n"\r
-" rbracket;\n"\r
-"vp_progParamReg_1\n"\r
-" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n"\r
-" rbracket;\n"\r
-"fp_progParamSingle\n"\r
-" .false;\n"\r
-"vp_progParamSingle\n"\r
-" .false;\n"\r
-"fp_progParamArray\n"\r
-" fp_establishedName_no_error_on_identifier;\n"\r
-"vp_progParamArray\n"\r
-" vp_establishedName_no_error_on_identifier;\n"\r
-"progParamArrayMem\n"\r
-" progParamArrayAbs .or progParamArrayRel;\n"\r
-"progParamArrayAbs\n"\r
-" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n"\r
-"progParamArrayRel\n"\r
-" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n"\r
-" addrComponent .and addrRegRelOffset;\n"\r
-"addrRegRelOffset\n"\r
-" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n"\r
-"addrRegRelOffset_1\n"\r
-" plus_ne .and addrRegPosOffset;\n"\r
-"addrRegRelOffset_2\n"\r
-" minus_ne .and addrRegNegOffset;\n"\r
-"addrRegPosOffset\n"\r
-" integer_0_63;\n"\r
-"addrRegNegOffset\n"\r
-" integer_0_64;\n"\r
-"fragmentResultReg\n"\r
-" fp_resultBinding;\n"\r
-"vertexResultReg\n"\r
-" vp_resultBinding;\n"\r
-"addrReg\n"\r
-" vp_establishedName_no_error_on_identifier;\n"\r
-"addrComponent\n"\r
-" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n"\r
-" .emit COMPONENT_X .emit COMPONENT_X;\n"\r
-"addrWriteMask\n"\r
-" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n"\r
-"fp_scalarSuffix\n"\r
-" dot .and fp_component_single .error INVALID_COMPONENT;\n"\r
-"vp_scalarSuffix\n"\r
-" dot .and vp_component_single .error INVALID_COMPONENT;\n"\r
-"swizzleSuffix\n"\r
-" swizzleSuffix_1 .or\n"\r
-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"\r
-"swizzleSuffix_1\n"\r
-" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n"\r
-"swizzleSuffix_2\n"\r
-" swizzleSuffix_3 .or swizzleSuffix_4;\n"\r
-"swizzleSuffix_3\n"\r
-" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n"\r
-" vp_component_multi .error INVALID_COMPONENT;\n"\r
-"swizzleSuffix_4\n"\r
-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"\r
-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"\r
-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"\r
-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"\r
-"optionalSuffix\n"\r
-" optionalSuffix_1 .or\n"\r
-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"\r
-"optionalSuffix_1\n"\r
-" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n"\r
-"optionalSuffix_2\n"\r
-" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n"\r
-"optionalSuffix_3\n"\r
-" xyzwComponent_multi .and xyzwComponent_multi .and\n"\r
-" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n"\r
-"optionalSuffix_4\n"\r
-" rgbaComponent_multi .and rgbaComponent_multi .and\n"\r
-" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n"\r
-"optionalSuffix_5\n"\r
-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"\r
-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"\r
-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"\r
-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n"\r
-" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"\r
-" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"\r
-" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"\r
-" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"\r
-"fp_component_single\n"\r
-" xyzwComponent_single .or rgbaComponent_single;\n"\r
-"vp_component_multi\n"\r
-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"\r
-" 'w' .emit COMPONENT_W;\n"\r
-"vp_component_single\n"\r
-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"\r
-" \"w\" .emit COMPONENT_W;\n"\r
-"xyzwComponent_multi\n"\r
-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"\r
-" 'w' .emit COMPONENT_W;\n"\r
-"xyzwComponent_single\n"\r
-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"\r
-" \"w\" .emit COMPONENT_W;\n"\r
-"rgbaComponent_multi\n"\r
-" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n"\r
-" 'a' .emit COMPONENT_W;\n"\r
-"rgbaComponent_single\n"\r
-" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n"\r
-" \"a\" .emit COMPONENT_W;\n"\r
-"fp_optionalMask\n"\r
-" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n"\r
-"vp_optionalMask\n"\r
-" xyzwMask .or .true .emit 0x0F;\n"\r
-"xyzwMask\n"\r
-" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n"\r
-"xyzwMask_1\n"\r
-" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n"\r
-" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n"\r
-" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n"\r
-" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n"\r
-"rgbaMask\n"\r
-" dot_ne .and rgbaMask_1;\n"\r
-"rgbaMask_1\n"\r
-" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n"\r
-" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n"\r
-" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n"\r
-" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n"\r
-"fp_namingStatement\n"\r
-" fp_ATTRIB_statement .emit ATTRIB .or\n"\r
-" fp_PARAM_statement .emit PARAM .or\n"\r
-" fp_TEMP_statement .emit TEMP .or\n"\r
-" fp_OUTPUT_statement .emit OUTPUT .or\n"\r
-" fp_ALIAS_statement .emit ALIAS;\n"\r
-"vp_namingStatement\n"\r
-" vp_ATTRIB_statement .emit ATTRIB .or\n"\r
-" vp_PARAM_statement .emit PARAM .or\n"\r
-" vp_TEMP_statement .emit TEMP .or\n"\r
-" ADDRESS_statement .emit ADDRESS .or\n"\r
-" vp_OUTPUT_statement .emit OUTPUT .or\n"\r
-" vp_ALIAS_statement .emit ALIAS;\n"\r
-"fp_ATTRIB_statement\n"\r
-" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n"\r
-" fragAttribBinding .error FRAGMENT_EXPECTED;\n"\r
-"vp_ATTRIB_statement\n"\r
-" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n"\r
-" vtxAttribBinding .error VERTEX_EXPECTED;\n"\r
-"fragAttribBinding\n"\r
-" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n"\r
-"vtxAttribBinding\n"\r
-" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n"\r
-"fragAttribItem\n"\r
-" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n"\r
-" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n"\r
-" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n"\r
-" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n"\r
-"fragAttribItem_1\n"\r
-" \"color\" .and optColorType;\n"\r
-"fragAttribItem_2\n"\r
-" \"texcoord\" .and optTexCoordNum;\n"\r
-"vtxAttribItem\n"\r
-" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n"\r
-" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n"\r
-" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n"\r
-" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n"\r
-" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n"\r
-" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n"\r
-" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n"\r
-" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n"\r
-"vtxAttribItem_1\n"\r
-" \"weight\" .and vtxOptWeightNum;\n"\r
-"vtxAttribItem_2\n"\r
-" \"color\" .and optColorType;\n"\r
-"vtxAttribItem_3\n"\r
-" \"texcoord\" .and optTexCoordNum;\n"\r
-"vtxAttribItem_4\n"\r
-" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n"\r
-"vtxAttribItem_5\n"\r
-" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n"\r
-"vtxAttribNum\n"\r
-" integer;\n"\r
-"vtxOptWeightNum\n"\r
-" vtxOptWeightNum_1 .or .true .emit 0x00;\n"\r
-"vtxOptWeightNum_1\n"\r
-" lbracket_ne .and vtxWeightNum .and rbracket;\n"\r
-"vtxWeightNum\n"\r
-" integer;\n"\r
-"fp_PARAM_statement\n"\r
-" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n"\r
-"vp_PARAM_statement\n"\r
-" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n"\r
-"fp_PARAM_singleStmt\n"\r
-" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n"\r
-" .true .emit PARAM_NULL;\n"\r
-"vp_PARAM_singleStmt\n"\r
-" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n"\r
-" .true .emit PARAM_NULL;\n"\r
-"fp_PARAM_multipleStmt\n"\r
-" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"\r
-" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n"\r
-"vp_PARAM_multipleStmt\n"\r
-" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"\r
-" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n"\r
-"optArraySize\n"\r
-" optional_integer;\n"\r
-"fp_paramSingleInit\n"\r
-" equal .and fp_paramSingleItemDecl;\n"\r
-"vp_paramSingleInit\n"\r
-" equal .and vp_paramSingleItemDecl;\n"\r
-"fp_paramMultipleInit\n"\r
-" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n"\r
-"vp_paramMultipleInit\n"\r
-" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n"\r
-"fp_paramMultInitList\n"\r
-" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n"\r
-"vp_paramMultInitList\n"\r
-" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n"\r
-"fp_paramMultInitList_1\n"\r
-" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n"\r
-"vp_paramMultInitList_1\n"\r
-" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n"\r
-"fp_paramSingleItemDecl\n"\r
-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"\r
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"\r
-" paramConstDecl .emit PARAM_CONSTANT;\n"\r
-"vp_paramSingleItemDecl\n"\r
-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"\r
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"\r
-" paramConstDecl .emit PARAM_CONSTANT;\n"\r
-"fp_paramSingleItemUse\n"\r
-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"\r
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"\r
-" paramConstUse .emit PARAM_CONSTANT;\n"\r
-"vp_paramSingleItemUse\n"\r
-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"\r
-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"\r
-" paramConstUse .emit PARAM_CONSTANT;\n"\r
-"fp_paramMultipleItem\n"\r
-" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"\r
-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"\r
-" paramConstDecl .emit PARAM_CONSTANT;\n"\r
-"vp_paramMultipleItem\n"\r
-" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"\r
-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"\r
-" paramConstDecl .emit PARAM_CONSTANT;\n"\r
-"fp_stateMultipleItem\n"\r
-" stateMultipleItem_1 .or fp_stateSingleItem;\n"\r
-"vp_stateMultipleItem\n"\r
-" stateMultipleItem_1 .or vp_stateSingleItem;\n"\r
-"stateMultipleItem_1\n"\r
-" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n"\r
-"fp_stateSingleItem\n"\r
-" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"\r
-"vp_stateSingleItem\n"\r
-" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"\r
-"fp_stateSingleItem_1\n"\r
-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"\r
-" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n"\r
-"vp_stateSingleItem_1\n"\r
-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"\r
-" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n"\r
-" stateSingleItem_11;\n"\r
-"stateSingleItem_1\n"\r
-" stateMaterialItem .emit STATE_MATERIAL;\n"\r
-"stateSingleItem_2\n"\r
-" stateLightItem .emit STATE_LIGHT;\n"\r
-"stateSingleItem_3\n"\r
-" stateLightModelItem .emit STATE_LIGHT_MODEL;\n"\r
-"stateSingleItem_4\n"\r
-" stateLightProdItem .emit STATE_LIGHT_PROD;\n"\r
-"stateSingleItem_5\n"\r
-" stateTexEnvItem .emit STATE_TEX_ENV;\n"\r
-"stateSingleItem_6\n"\r
-" stateTexGenItem .emit STATE_TEX_GEN;\n"\r
-"stateSingleItem_7\n"\r
-" stateFogItem .emit STATE_FOG;\n"\r
-"stateSingleItem_8\n"\r
-" stateDepthItem .emit STATE_DEPTH;\n"\r
-"stateSingleItem_9\n"\r
-" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n"\r
-"stateSingleItem_10\n"\r
-" statePointItem .emit STATE_POINT;\n"\r
-"stateSingleItem_11\n"\r
-" stateMatrixRow .emit STATE_MATRIX_ROWS;\n"\r
-"stateMaterialItem\n"\r
-" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n"\r
-"stateMatProperty\n"\r
-" \"ambient\" .emit MATERIAL_AMBIENT .or\n"\r
-" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n"\r
-" \"specular\" .emit MATERIAL_SPECULAR .or\n"\r
-" \"emission\" .emit MATERIAL_EMISSION .or\n"\r
-" \"shininess\" .emit MATERIAL_SHININESS;\n"\r
-"stateLightItem\n"\r
-" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n"\r
-" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n"\r
-"stateLightProperty\n"\r
-" \"ambient\" .emit LIGHT_AMBIENT .or\n"\r
-" \"diffuse\" .emit LIGHT_DIFFUSE .or\n"\r
-" \"specular\" .emit LIGHT_SPECULAR .or\n"\r
-" \"position\" .emit LIGHT_POSITION .or\n"\r
-" \"attenuation\" .emit LIGHT_ATTENUATION .or\n"\r
-" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n"\r
-" \"half\" .emit LIGHT_HALF;\n"\r
-"stateLightProperty_1\n"\r
-" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n"\r
-"stateSpotProperty\n"\r
-" \"direction\";\n"\r
-"stateLightModelItem\n"\r
-" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n"\r
-"stateLModProperty\n"\r
-" stateLModProperty_1 .or stateLModProperty_2;\n"\r
-"stateLModProperty_1\n"\r
-" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n"\r
-"stateLModProperty_2\n"\r
-" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n"\r
-"stateLModProperty_3\n"\r
-" optFaceType .and dot .and \"scenecolor\";\n"\r
-"stateLightProdItem\n"\r
-" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n"\r
-" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n"\r
-"stateLProdProperty\n"\r
-" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n"\r
-" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n"\r
-" \"specular\" .emit LIGHT_PROD_SPECULAR;\n"\r
-"stateLightNumber\n"\r
-" integer;\n"\r
-"stateTexEnvItem\n"\r
-" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n"\r
-" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n"\r
-"stateTexEnvProperty\n"\r
-" \"color\" .emit TEX_ENV_COLOR;\n"\r
-"optLegacyTexUnitNum\n"\r
-" lbracket_ne .and legacyTexUnitNum .and rbracket;\n"\r
-"legacyTexUnitNum\n"\r
-" integer;\n"\r
-"stateTexGenItem\n"\r
-" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n"\r
-" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n"\r
-"stateTexGenType\n"\r
-" \"eye\" .emit TEX_GEN_EYE .or\n"\r
-" \"object\" .emit TEX_GEN_OBJECT;\n"\r
-"stateTexGenCoord\n"\r
-" \"s\" .emit COMPONENT_X .or\n"\r
-" \"t\" .emit COMPONENT_Y .or\n"\r
-" \"r\" .emit COMPONENT_Z .or\n"\r
-" \"q\" .emit COMPONENT_W;\n"\r
-"stateFogItem\n"\r
-" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n"\r
-"stateFogProperty\n"\r
-" \"color\" .emit FOG_COLOR .or\n"\r
-" \"params\" .emit FOG_PARAMS;\n"\r
-"stateDepthItem\n"\r
-" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n"\r
-"stateDepthProperty\n"\r
-" \"range\" .emit DEPTH_RANGE;\n"\r
-"stateClipPlaneItem\n"\r
-" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n"\r
-" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n"\r
-"stateClipPlaneNum\n"\r
-" integer;\n"\r
-"statePointItem\n"\r
-" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n"\r
-"statePointProperty\n"\r
-" \"size\" .emit POINT_SIZE .or\n"\r
-" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n"\r
-"stateMatrixRow\n"\r
-" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n"\r
-" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n"\r
-"stateMatrixRows\n"\r
-" stateMatrixItem .and optMatrixRows;\n"\r
-"optMatrixRows\n"\r
-" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n"\r
-"optMatrixRows_1\n"\r
-" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n"\r
-" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n"\r
-"stateMatrixItem\n"\r
-" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n"\r
-"stateOptMatModifier\n"\r
-" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n"\r
-"stateOptMatModifier_1\n"\r
-" dot_ne .and stateMatModifier;\n"\r
-"stateMatModifier\n"\r
-" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n"\r
-" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n"\r
-" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n"\r
-"stateMatrixRowNum\n"\r
-" integer_0_3;\n"\r
-"stateMatrixName\n"\r
-" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n"\r
-" \"projection\" .emit MATRIX_PROJECTION .or\n"\r
-" \"mvp\" .emit MATRIX_MVP .or\n"\r
-" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n"\r
-" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n"\r
-" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n"\r
-"stateMatrixName_1_1\n"\r
-" \"modelview\" .and stateOptModMatNum;\n"\r
-"stateMatrixName_1_2\n"\r
-" \"texture\" .and optTexCoordNum;\n"\r
-"stateMatrixName_1_3\n"\r
-" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n"\r
-"stateMatrixName_1_4\n"\r
-" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n"\r
-"stateOptModMatNum\n"\r
-" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n"\r
-" .true .emit 0x00;\n"\r
-"stateOptModMatNum_1\n"\r
-" lbracket_ne .and stateModMatNum .and rbracket;\n"\r
-"stateModMatNum\n"\r
-" integer;\n"\r
-"optTexCoordNum\n"\r
-" optTexCoordNum_1 .or .true .emit 0x00;\n"\r
-"optTexCoordNum_1\n"\r
-" lbracket_ne .and texCoordNum .and rbracket;\n"\r
-"texCoordNum\n"\r
-" integer;\n"\r
-"statePaletteMatNum\n"\r
-" integer;\n"\r
-"stateProgramMatNum\n"\r
-" integer;\n"\r
-"programSingleItem\n"\r
-" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"\r
-"programSingleItem_1\n"\r
-" progEnvParam .or progLocalParam;\n"\r
-"programMultipleItem\n"\r
-" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"\r
-"programMultipleItem_1\n"\r
-" progEnvParams .or progLocalParams;\n"\r
-"progEnvParams\n"\r
-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n"\r
-"progEnvParamNums\n"\r
-" progEnvParamNums_1 .or progEnvParamNums_2;\n"\r
-"progEnvParamNums_1\n"\r
-" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n"\r
-"progEnvParamNums_2\n"\r
-" progEnvParamNum .and .true .emit 0x00;\n"\r
-"progEnvParam\n"\r
-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n"\r
-"progLocalParams\n"\r
-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n"\r
-"progLocalParamNums\n"\r
-" progLocalParamNums_1 .or progLocalParamNums_2;\n"\r
-"progLocalParamNums_1\n"\r
-" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n"\r
-"progLocalParamNums_2\n"\r
-" progLocalParamNum .and .true .emit 0x00;\n"\r
-"progLocalParam\n"\r
-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n"\r
-"progEnvParamNum\n"\r
-" integer;\n"\r
-"progLocalParamNum\n"\r
-" integer;\n"\r
-"paramConstDecl\n"\r
-" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"\r
-"paramConstUse\n"\r
-" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"\r
-"paramConstScalarDecl\n"\r
-" signedFloatConstant;\n"\r
-"paramConstScalarUse\n"\r
-" floatConstant;\n"\r
-"paramConstVector\n"\r
-" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n"\r
-" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n"\r
-"paramConstVector_1\n"\r
-" lbrace_ne .and signedFloatConstant .and rbrace;\n"\r
-"paramConstVector_2\n"\r
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"\r
-"paramConstVector_3\n"\r
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"\r
-" signedFloatConstant .and rbrace;\n"\r
-"paramConstVector_4\n"\r
-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"\r
-" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"\r
-"signedFloatConstant\n"\r
-" optionalSign .and floatConstant;\n"\r
-"floatConstant\n"\r
-" float;\n"\r
-"optionalSign\n"\r
-" optional_sign_ne;\n"\r
-"fp_TEMP_statement\n"\r
-" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n"\r
-"vp_TEMP_statement\n"\r
-" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n"\r
-"ADDRESS_statement\n"\r
-" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n"\r
-"fp_varNameList\n"\r
-" fp_varNameList_1 .or fp_establishName;\n"\r
-"vp_varNameList\n"\r
-" vp_varNameList_1 .or vp_establishName;\n"\r
-"fp_varNameList_1\n"\r
-" fp_establishName .and comma_ne .and fp_varNameList;\n"\r
-"vp_varNameList_1\n"\r
-" vp_establishName .and comma_ne .and vp_varNameList;\n"\r
-"fp_OUTPUT_statement\n"\r
-" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n"\r
-" fp_resultBinding .error RESULT_EXPECTED;\n"\r
-"vp_OUTPUT_statement\n"\r
-" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n"\r
-" vp_resultBinding .error RESULT_EXPECTED;\n"\r
-"fp_resultBinding\n"\r
-" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"\r
-"vp_resultBinding\n"\r
-" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"\r
-"fp_resultBinding_1\n"\r
-" \"color\" .emit FRAGMENT_RESULT_COLOR .or\n"\r
-" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n"\r
-"vp_resultBinding_1\n"\r
-" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n"\r
-" resultColBinding .emit VERTEX_RESULT_COLOR .or\n"\r
-" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n"\r
-" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n"\r
-" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n"\r
-"vp_resultBinding_2\n"\r
-" \"texcoord\" .and optTexCoordNum;\n"\r
-"resultColBinding\n"\r
-" \"color\" .and optFaceType .and optColorType;\n"\r
-"optFaceType\n"\r
-" FaceType .or .true .emit FACE_FRONT;\n"\r
-"FaceType\n"\r
-" dot_ne .and FaceProperty;\n"\r
-"FaceProperty\n"\r
-" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n"\r
-"optColorType\n"\r
-" ColorType .or .true .emit COLOR_PRIMARY;\n"\r
-"ColorType\n"\r
-" dot_ne .and ColorProperty;\n"\r
-"ColorProperty\n"\r
-" \"primary\" .emit COLOR_PRIMARY .or\n"\r
-" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n"\r
-"fp_ALIAS_statement\n"\r
-" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n"\r
-"vp_ALIAS_statement\n"\r
-" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n"\r
-"fp_ALIAS_statement_1\n"\r
-" space .and fp_establishName;\n"\r
-"vp_ALIAS_statement_1\n"\r
-" space .and vp_establishName;\n"\r
-"fp_establishName\n"\r
-" fp_identifier;\n"\r
-"vp_establishName\n"\r
-" vp_identifier;\n"\r
-"fp_establishedName\n"\r
-" fp_identifier;\n"\r
-"vp_establishedName\n"\r
-" vp_identifier;\n"\r
-"fp_establishedName_no_error_on_identifier\n"\r
-" fp_identifier_ne;\n"\r
-"vp_establishedName_no_error_on_identifier\n"\r
-" vp_identifier_ne;\n"\r
-"fp_identifier\n"\r
-" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n"\r
-"vp_identifier\n"\r
-" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n"\r
-"fp_identifier_ne\n"\r
-" fp_not_reserved_identifier .and identifier_ne;\n"\r
-"vp_identifier_ne\n"\r
-" vp_not_reserved_identifier .and identifier_ne;\n"\r
-"fp_not_reserved_identifier\n"\r
-" fp_not_reserved_identifier_1 .or .true;\n"\r
-"fp_not_reserved_identifier_1\n"\r
-" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"\r
-"vp_not_reserved_identifier\n"\r
-" vp_not_reserved_identifier_1 .or .true;\n"\r
-"vp_not_reserved_identifier_1\n"\r
-" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"\r
-"fp_reserved_identifier\n"\r
-" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n"\r
-" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n"\r
-" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n"\r
-" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n"\r
-" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n"\r
-" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n"\r
-" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n"\r
-" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n"\r
-" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n"\r
-" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n"\r
-"vp_reserved_identifier\n"\r
-" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n"\r
-" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n"\r
-" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n"\r
-" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n"\r
-" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n"\r
-"integer\n"\r
-" integer_ne .error INTEGER_EXPECTED;\n"\r
-"zero\n"\r
-" '0';\n"\r
-"leading_zeroes\n"\r
-" .loop zero;\n"\r
-"no_digit\n"\r
-" no_digit_1 .or .true;\n"\r
-"no_digit_1\n"\r
-" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n"\r
-"all_zeroes\n"\r
-" all_zeroes_1 .or no_digit_1;\n"\r
-"all_zeroes_1\n"\r
-" '0' .and .loop zero .and no_digit;\n"\r
-"integer_0_3\n"\r
-" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"\r
-"integer_0_3_1\n"\r
-" integer_0_3_2 .or all_zeroes .emit '0';\n"\r
-"integer_0_3_2 \n"\r
-" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n"\r
-"integer_0_63\n"\r
-" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"\r
-"integer_0_63_1\n"\r
-" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n"\r
-" all_zeroes .emit '0';\n"\r
-"integer_0_63_2 \n"\r
-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"\r
-"integer_0_63_3 \n"\r
-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"\r
-"integer_0_63_4 \n"\r
-" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n"\r
-"integer_0_63_5 \n"\r
-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"\r
-"integer_0_64\n"\r
-" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"\r
-"integer_0_64_1\n"\r
-" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n"\r
-" all_zeroes .emit '0';\n"\r
-"integer_0_64_2 \n"\r
-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"\r
-"integer_0_64_3 \n"\r
-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"\r
-"integer_0_64_4 \n"\r
-" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n"\r
-"integer_0_64_5 \n"\r
-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"\r
-"optional_space\n"\r
-" space .or .true;\n"\r
-"space_dst\n"\r
-" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n"\r
-"space_src\n"\r
-" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n"\r
-"space\n"\r
-" single_space .and .loop single_space;\n"\r
-"single_space\n"\r
-" white_char .or comment_block;\n"\r
-"white_char\n"\r
-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"\r
-"comment_block\n"\r
-" '#' .and .loop comment_char .and new_line;\n"\r
-"comment_char\n"\r
-" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"\r
-"new_line\n"\r
-" '\\n' .or crlf .or '\\0';\n"\r
-"crlf\n"\r
-" '\\r' .and '\\n';\n"\r
-"semicolon\n"\r
-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"\r
-"comma\n"\r
-" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n"\r
-"comma_ne\n"\r
-" optional_space .and ',' .and optional_space;\n"\r
-"lbracket\n"\r
-" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n"\r
-"lbracket_ne\n"\r
-" optional_space .and '[' .and optional_space;\n"\r
-"rbracket\n"\r
-" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n"\r
-"dot\n"\r
-" optional_space .and '.' .error MISSING_DOT .and optional_space;\n"\r
-"dot_ne\n"\r
-" optional_space .and '.' .and optional_space;\n"\r
-"equal\n"\r
-" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n"\r
-"lbrace\n"\r
-" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n"\r
-"lbrace_ne\n"\r
-" optional_space .and '{' .and optional_space;\n"\r
-"rbrace\n"\r
-" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n"\r
-"dotdot\n"\r
-" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n"\r
-"dotdot_ne\n"\r
-" optional_space .and '.' .and '.' .and optional_space;\n"\r
-"float\n"\r
-" float_1 .or float_2 .or float_legacy;\n"\r
-"float_1\n"\r
-" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n"\r
-"float_2\n"\r
-" integer_ne .and float_3;\n"\r
-"float_3\n"\r
-" float_4 .or float_5;\n"\r
-"float_4\n"\r
-" '.' .and optional_integer .and optional_exponent;\n"\r
-"float_5\n"\r
-" exponent .emit 0x00;\n"\r
-"float_legacy\n"\r
-" integer_ne .and .true .emit 0x00 .emit 0x00;\n"\r
-"integer_ne\n"\r
-" integer_ne_1 .and .true .emit 0x00 .emit $;\n"\r
-"integer_ne_1\n"\r
-" digit10 .emit * .and .loop digit10 .emit *;\n"\r
-"optional_integer\n"\r
-" integer_ne .or .true .emit 0x00;\n"\r
-"optional_exponent\n"\r
-" exponent .or .true .emit 0x00;\n"\r
-"exponent\n"\r
-" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n"\r
-"exponent_1\n"\r
-" 'e' .or 'E';\n"\r
-"optional_sign_ne\n"\r
-" minus_ne .or plus_ne .or .true;\n"\r
-"plus_ne\n"\r
-" optional_space .and '+' .and optional_space;\n"\r
-"minus_ne\n"\r
-" optional_space .and '-' .emit '-' .and optional_space;\n"\r
-"identifier_ne\n"\r
-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n"\r
-"follow_idchar\n"\r
-" first_idchar .or digit10;\n"\r
-"first_idchar\n"\r
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"\r
-"digit10\n"\r
-" '0'-'9';\n"\r
-".string __string_filter;\n"\r
-"__string_filter\n"\r
-" .loop __identifier_char;\n"\r
-"__identifier_char\n"\r
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n"\r
-"e_signature\n"\r
-" e_signature_char .and .loop e_signature_char;\n"\r
-"e_signature_char\n"\r
-" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"\r
-"e_statement\n"\r
-" .loop e_statement_not_term;\n"\r
-"e_statement_not_term\n"\r
-" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"\r
-"e_identifier\n"\r
-" e_identifier_first .and .loop e_identifier_next;\n"\r
-"e_identifier_first\n"\r
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"\r
-"e_identifier_next\n"\r
-" e_identifier_first .or '0'-'9';\n"\r
-"e_token\n"\r
-" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n"\r
-" '-' .or ',' .or ';';\n"\r
-"e_token_number\n"\r
-" e_token_digit .and .loop e_token_digit;\n"\r
-"e_token_digit\n"\r
-" '0'-'9';\n"\r
-"e_charordigit\n"\r
-" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"\r
-""
\ 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"
+""
-#ifndef GRAMMAR_PORT_BUILD\r
-#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file\r
-#endif\r
-\r
-/*\r
- Last Modified: 2004-II-8\r
-*/\r
-\r
-/*\r
- INTRODUCTION\r
- ------------\r
-\r
- The task is to check the syntax of an input string. Input string is a stream of ASCII\r
- characters terminated with a null-character ('\0'). Checking it using C language is\r
- difficult and hard to implement without bugs. It is hard to maintain and make changes when\r
- the syntax changes.\r
-\r
- This is because of a high redundancy of the C code. Large blocks of code are duplicated with\r
- only small changes. Even use of macros does not solve the problem because macros cannot\r
- erase the complexity of the problem.\r
-\r
- The resolution is to create a new language that will be highly oriented to our task. Once\r
- we describe a particular syntax, we are done. We can then focus on the code that implements\r
- the language. The size and complexity of it is relatively small than the code that directly\r
- checks the syntax.\r
-\r
- First, we must implement our new language. Here, the language is implemented in C, but it\r
- could also be implemented in any other language. The code is listed below. We must take\r
- a good care that it is bug free. This is simple because the code is simple and clean.\r
-\r
- Next, we must describe the syntax of our new language in itself. Once created and checked\r
- manually that it is correct, we can use it to check another scripts.\r
-\r
- Note that our new language loading code does not have to check the syntax. It is because we\r
- assume that the script describing itself is correct, and other scripts can be syntactically\r
- checked by the former script. The loading code must only do semantic checking which leads us to\r
- simple resolving references.\r
-\r
- THE LANGUAGE\r
- ------------\r
-\r
- Here I will describe the syntax of the new language (further called "Synek"). It is mainly a\r
- sequence of declarations terminated by a semicolon. The declaration consists of a symbol,\r
- which is an identifier, and its definition. A definition is in turn a sequence of specifiers\r
- connected with ".and" or ".or" operator. These operators cannot be mixed together in a one\r
- definition. Specifier can be a symbol, string, character, character range or a special\r
- keyword ".true" or ".false".\r
-\r
- On the very beginning of the script there is a declaration of a root symbol and is in the form:\r
- .syntax <root_symbol>;\r
- The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if\r
- the root symbol evaluates to true. A symbol evaluates to true if the definition associated with\r
- the symbol evaluates to true. Definition evaluation depends on the operator used to connect\r
- specifiers in the definition. If ".and" operator is used, definition evaluates to true if and\r
- only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to\r
- true if any of the specifiers evaluates to true. If definition contains only one specifier,\r
- it is evaluated as if it was connected with ".true" keyword by ".and" operator.\r
-\r
- If specifier is a ".true" keyword, it always evaluates to true.\r
-\r
- If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false\r
- when it does not evaluate to true.\r
-\r
- Character range specifier is in the form:\r
- '<first_character>' - '<second_character>'\r
- If specifier is a character range, it evaluates to true if character in the stream is greater\r
- or equal to <first_character> and less or equal to <second_character>. In that situation \r
- the stream pointer is advanced to point to next character in the stream. All C-style escape\r
- sequences are supported although trigraph sequences are not. The comparisions are performed\r
- on 8-bit unsigned integers.\r
-\r
- Character specifier is in the form:\r
- '<single_character>'\r
- It evaluates to true if the following character range specifier evaluates to true:\r
- '<single_character>' - '<single_character>'\r
-\r
- String specifier is in the form:\r
- "<string>"\r
- Let N be the number of characters in <string>. Let <string>[i] designate i-th character in\r
- <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)\r
- the following character specifier evaluates to true:\r
- '<string>[i]'\r
- If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.\r
-\r
- Symbol specifier can be optionally preceded by a ".loop" keyword in the form:\r
- .loop <symbol> (1)\r
- where <symbol> is defined as follows:\r
- <symbol> <definition>; (2)\r
- Construction (1) is replaced by the following code:\r
- <symbol$1>\r
- and declaration (2) is replaced by the following:\r
- <symbol$1> <symbol$2> .or .true;\r
- <symbol$2> <symbol> .and <symbol$1>;\r
- <symbol> <definition>;\r
-\r
- ESCAPE SEQUENCES\r
- ----------------\r
-\r
- Synek supports all escape sequences in character specifiers. The mapping table is listed below.\r
- All occurences of the characters in the first column are replaced with the corresponding\r
- character in the second column.\r
-\r
- Escape sequence Represents\r
- ------------------------------------------------------------------------------------------------\r
- \a Bell (alert)\r
- \b Backspace\r
- \f Formfeed\r
- \n New line\r
- \r Carriage return\r
- \t Horizontal tab\r
- \v Vertical tab\r
- \' Single quotation mark\r
- \" Double quotation mark\r
- \\ Backslash\r
- \? Literal question mark\r
- \ooo ASCII character in octal notation\r
- \xhhh ASCII character in hexadecimal notation\r
- ------------------------------------------------------------------------------------------------\r
-\r
- RAISING ERRORS\r
- --------------\r
-\r
- Any specifier can be followed by a special construction that is executed when the specifier\r
- evaluates to false. The construction is in the form:\r
- .error <ERROR_TEXT>\r
- <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is\r
- in the form:\r
- .errtext <ERROR_TEXT> "<error_desc>"\r
- When specifier evaluates to false and this construction is present, parsing is stopped\r
- immediately and <error_desc> is returned as a result of parsing. The error position is also\r
- returned and it is meant as an offset from the beggining of the stream to the character that\r
- was valid so far. Example:\r
-\r
- (**** syntax script ****)\r
-\r
- .syntax program;\r
- .errtext MISSING_SEMICOLON "missing ';'"\r
- program declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and\r
- .loop space .and '\0';\r
- declaration "declare" .and .loop space .and identifier;\r
- space ' ';\r
-\r
- (**** sample code ****)\r
-\r
- declare foo ,\r
-\r
- In the example above checking the sample code will result in error message "missing ';'" and\r
- error position 12. The sample code is not correct. Note the presence of '\0' specifier to\r
- assure that there is no code after semicolon - only spaces.\r
- <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,\r
- the identifier and dollar signs are replaced by a string retrieved by invoking symbol with\r
- the identifier name. The starting position is the error position. The lenght of the resulting\r
- string is the position after invoking the symbol.\r
-\r
- PRODUCTION\r
- ----------\r
-\r
- Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers\r
- that evaluate to true. That is, every specifier and optional error construction can be followed\r
- by a number of emit constructions that are in the form:\r
- .emit <parameter>\r
- <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by\r
- 0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration\r
- in the form:\r
- .emtcode <identifier> <hex_number>\r
-\r
- When given specifier evaluates to true, all emits associated with the specifier are output\r
- in order they were declared. A star means that last-read character should be output instead\r
- of constant value. Example:\r
-\r
- (**** syntax script ****)\r
-\r
- .syntax foobar;\r
- .emtcode WORD_FOO 0x01\r
- .emtcode WORD_BAR 0x02\r
- foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;\r
- FOO "foo" .and SPACE;\r
- BAR "bar" .and SPACE;\r
- SPACE ' ' .or '\0';\r
-\r
- (**** sample text 1 ****)\r
-\r
- foo\r
-\r
- (**** sample text 2 ****)\r
-\r
- foobar\r
-\r
- For both samples the result will be one-element array. For first sample text it will be\r
- value 1, for second - 0. Note that every text will be accepted because of presence of\r
- .true as an alternative.\r
-\r
- Another example:\r
-\r
- (**** syntax script ****)\r
-\r
- .syntax declaration;\r
- .emtcode VARIABLE 0x01\r
- declaration "declare" .and .loop space .and\r
- identifier .emit VARIABLE .and (1)\r
- .true .emit 0x00 .and (2)\r
- .loop space .and ';';\r
- space ' ' .or '\t';\r
- identifier .loop id_char .emit *; (3)\r
- id_char 'a'-'z' .or 'A'-'Z' .or '_';\r
-\r
- (**** sample code ****)\r
-\r
- declare fubar;\r
-\r
- In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to\r
- true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used\r
- to terminate the string with null to signal when the string ends. Specifier (3) outputs\r
- all characters that make declared identifier. The result of sample code will be the\r
- following array:\r
- { 1, 'f', 'u', 'b', 'a', 'r', 0 }\r
-\r
- If .emit is followed by dollar $, it means that current position should be output. Current\r
- position is a 32-bit unsigned integer distance from the very beginning of the parsed string to\r
- first character consumed by the specifier associated with the .emit instruction. Current\r
- position is stored in the output buffer in Little-Endian convention (the lowest byte comes\r
- first).\r
-*/\r
-\r
-static void mem_free (void **);\r
-\r
-/*\r
- internal error messages\r
-*/\r
-static const byte *OUT_OF_MEMORY = (byte *) "internal error 1001: out of physical memory";\r
-static const byte *UNRESOLVED_REFERENCE = (byte *) "internal error 1002: unresolved reference '$'";\r
-static const byte *INVALID_GRAMMAR_ID = (byte *) "internal error 1003: invalid grammar object";\r
-static const byte *INVALID_REGISTER_NAME = (byte *) "internal error 1004: invalid register name: '$'";\r
-\r
-static const byte *error_message = NULL;\r
-static byte *error_param = NULL; /* this is inserted into error_message in place of $ */\r
-static int error_position = -1;\r
-\r
-static byte *unknown = (byte *) "???";\r
-\r
-static void clear_last_error ()\r
-{\r
- /* reset error message */\r
- error_message = NULL;\r
-\r
- /* free error parameter - if error_param is a "???" don't free it - it's static */\r
- if (error_param != unknown)\r
- mem_free ((void **) &error_param);\r
- else\r
- error_param = NULL;\r
-\r
- /* reset error position */\r
- error_position = -1;\r
-}\r
-\r
-static void set_last_error (const byte *msg, byte *param, int pos)\r
-{\r
- /* error message can only be set only once */\r
- if (error_message != NULL)\r
- {\r
- mem_free (¶m);\r
- return;\r
- }\r
-\r
- error_message = msg;\r
-\r
- if (param != NULL)\r
- error_param = param;\r
- else\r
- error_param = unknown;\r
-\r
- error_position = pos;\r
-}\r
-\r
-/*\r
- memory management routines\r
-*/\r
-static void *mem_alloc (size_t size)\r
-{\r
- void *ptr = grammar_alloc_malloc (size);\r
- if (ptr == NULL)\r
- set_last_error (OUT_OF_MEMORY, NULL, -1);\r
- return ptr;\r
-}\r
-\r
-static void *mem_copy (void *dst, const void *src, size_t size)\r
-{\r
- return grammar_memory_copy (dst, src, size);\r
-}\r
-\r
-static void mem_free (void **ptr)\r
-{\r
- grammar_alloc_free (*ptr);\r
- *ptr = NULL;\r
-}\r
-\r
-static void *mem_realloc (void *ptr, size_t old_size, size_t new_size)\r
-{\r
- void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size);\r
- if (ptr2 == NULL)\r
- set_last_error (OUT_OF_MEMORY, NULL, -1);\r
- return ptr2;\r
-}\r
-\r
-static byte *str_copy_n (byte *dst, const byte *src, size_t max_len)\r
-{\r
- return grammar_string_copy_n (dst, src, max_len);\r
-}\r
-\r
-static byte *str_duplicate (const byte *str)\r
-{\r
- byte *new_str = grammar_string_duplicate (str);\r
- if (new_str == NULL)\r
- set_last_error (OUT_OF_MEMORY, NULL, -1);\r
- return new_str;\r
-}\r
-\r
-static int str_equal (const byte *str1, const byte *str2)\r
-{\r
- return grammar_string_compare (str1, str2) == 0;\r
-}\r
-\r
-static int str_equal_n (const byte *str1, const byte *str2, unsigned int n)\r
-{\r
- return grammar_string_compare_n (str1, str2, n) == 0;\r
-}\r
-\r
-static unsigned int str_length (const byte *str)\r
-{\r
- return grammar_string_length (str);\r
-}\r
-\r
-/*\r
- string to byte map typedef\r
-*/\r
-typedef struct map_byte_\r
-{\r
- byte *key;\r
- byte data;\r
- struct map_byte_ *next;\r
-} map_byte;\r
-\r
-static void map_byte_create (map_byte **ma)\r
-{\r
- *ma = mem_alloc (sizeof (map_byte));\r
- if (*ma)\r
- {\r
- (**ma).key = NULL;\r
- (**ma).data = '\0';\r
- (**ma).next = NULL;\r
- }\r
-}\r
-\r
-/* XXX unfold the recursion */\r
-static void map_byte_destroy (map_byte **ma)\r
-{\r
- if (*ma)\r
- {\r
- map_byte_destroy (&(**ma).next);\r
- mem_free ((void **) &(**ma).key);\r
- mem_free ((void **) ma);\r
- }\r
-}\r
-\r
-static void map_byte_append (map_byte **ma, map_byte **nm)\r
-{\r
- while (*ma)\r
- ma = &(**ma).next;\r
- *ma = *nm;\r
-}\r
-\r
-/*\r
- searches the map for the specified key,\r
- returns pointer to the element with the specified key if it exists\r
- returns NULL otherwise\r
-*/\r
-map_byte *map_byte_locate (map_byte **ma, const byte *key)\r
-{\r
- while (*ma)\r
- {\r
- if (str_equal ((**ma).key, key))\r
- return *ma;\r
-\r
- ma = &(**ma).next;\r
- }\r
-\r
- set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);\r
- return NULL;\r
-}\r
-\r
-/*\r
- searches the map for specified key,\r
- if the key is matched, *data is filled with data associated with the key,\r
- returns 0 if the key is matched,\r
- returns 1 otherwise\r
-*/\r
-static int map_byte_find (map_byte **ma, const byte *key, byte *data)\r
-{\r
- map_byte *found = map_byte_locate (ma, key);\r
- if (found != NULL)\r
- {\r
- *data = found->data;\r
-\r
- return 0;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-/*\r
- regbyte context typedef\r
-\r
- Each regbyte consists of its name and a default value. These are static and created at\r
- grammar script compile-time, for example the following line:\r
- .regbyte vertex_blend 0x00\r
- adds a new regbyte named "vertex_blend" to the static list and initializes it to 0.\r
- When the script is executed, this regbyte can be accessed by name for read and write. When a\r
- particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx\r
- stack. The new entry contains information abot which regbyte it references and its new value.\r
- When a given regbyte is accessed for read, the stack is searched top-down to find an\r
- entry that references the regbyte. The first matching entry is used to return the current\r
- value it holds. If no entry is found, the default value is returned.\r
-*/\r
-typedef struct regbyte_ctx_\r
-{\r
- map_byte *m_regbyte;\r
- byte m_current_value;\r
- struct regbyte_ctx_ *m_prev;\r
-} regbyte_ctx;\r
-\r
-static void regbyte_ctx_create (regbyte_ctx **re)\r
-{\r
- *re = mem_alloc (sizeof (regbyte_ctx));\r
- if (*re)\r
- {\r
- (**re).m_regbyte = NULL;\r
- (**re).m_prev = NULL;\r
- }\r
-}\r
-\r
-static void regbyte_ctx_destroy (regbyte_ctx **re)\r
-{\r
- if (*re)\r
- {\r
- mem_free ((void **) re);\r
- }\r
-}\r
-\r
-static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg)\r
-{\r
- /* first lookup in the register stack */\r
- while (*re != NULL)\r
- {\r
- if ((**re).m_regbyte == reg)\r
- return (**re).m_current_value;\r
-\r
- re = &(**re).m_prev;\r
- }\r
-\r
- /* if not found - return the default value */\r
- return reg->data;\r
-}\r
-\r
-/*\r
- emit type typedef\r
-*/\r
-typedef enum emit_type_\r
-{\r
- et_byte, /* explicit number */\r
- et_stream, /* eaten character */\r
- et_position /* current position */\r
-} emit_type;\r
-\r
-/*\r
- emit destination typedef\r
-*/\r
-typedef enum emit_dest_\r
-{\r
- ed_output, /* write to the output buffer */\r
- ed_regbyte /* write a particular regbyte */\r
-} emit_dest;\r
-\r
-/*\r
- emit typedef\r
-*/\r
-typedef struct emit_\r
-{\r
- emit_dest m_emit_dest;\r
- emit_type m_emit_type; /* ed_output */\r
- byte m_byte; /* et_byte */\r
- map_byte *m_regbyte; /* ed_regbyte */\r
- byte *m_regname; /* ed_regbyte - temporary */\r
- struct emit_ *m_next;\r
-} emit;\r
-\r
-static void emit_create (emit **em)\r
-{\r
- *em = mem_alloc (sizeof (emit));\r
- if (*em)\r
- {\r
- (**em).m_emit_dest = ed_output;\r
- (**em).m_emit_type = et_byte;\r
- (**em).m_byte = '\0';\r
- (**em).m_regbyte = NULL;\r
- (**em).m_regname = NULL;\r
- (**em).m_next = NULL;\r
- }\r
-}\r
-\r
-static void emit_destroy (emit **em)\r
-{\r
- if (*em)\r
- {\r
- emit_destroy (&(**em).m_next);\r
- mem_free ((void **) &(**em).m_regname);\r
- mem_free ((void **) em);\r
- }\r
-}\r
-\r
-/*\r
- error typedef\r
-*/\r
-typedef struct error_\r
-{\r
- byte *m_text;\r
- byte *m_token_name;\r
- struct rule_ *m_token;\r
-} error;\r
-\r
-static void error_create (error **er)\r
-{\r
- *er = mem_alloc (sizeof (error));\r
- if (*er)\r
- {\r
- (**er).m_text = NULL;\r
- (**er).m_token_name = NULL;\r
- (**er).m_token = NULL;\r
- }\r
-}\r
-\r
-static void error_destroy (error **er)\r
-{\r
- if (*er)\r
- {\r
- mem_free ((void **) &(**er).m_text);\r
- mem_free ((void **) &(**er).m_token_name);\r
- mem_free ((void **) er);\r
- }\r
-}\r
-\r
-struct dict_;\r
-static byte *error_get_token (error *, struct dict_ *, const byte *, unsigned int);\r
-\r
-/*\r
- condition operand type typedef\r
-*/\r
-typedef enum cond_oper_type_\r
-{\r
- cot_byte, /* constant 8-bit unsigned integer */\r
- cot_regbyte /* pointer to byte register containing the current value */\r
-} cond_oper_type;\r
-\r
-/*\r
- condition operand typedef\r
-*/\r
-typedef struct cond_oper_\r
-{\r
- cond_oper_type m_type;\r
- byte m_byte; /* cot_byte */\r
- map_byte *m_regbyte; /* cot_regbyte */\r
- byte *m_regname; /* cot_regbyte - temporary */\r
-} cond_oper;\r
-\r
-/*\r
- condition type typedef\r
-*/\r
-typedef enum cond_type_\r
-{\r
- ct_equal,\r
- ct_not_equal\r
-} cond_type;\r
-\r
-/*\r
- condition typedef\r
-*/\r
-typedef struct cond_\r
-{\r
- cond_type m_type;\r
- cond_oper m_operands[2];\r
-} cond;\r
-\r
-static void cond_create (cond **co)\r
-{\r
- *co = mem_alloc (sizeof (cond));\r
- if (*co)\r
- {\r
- (**co).m_operands[0].m_regname = NULL;\r
- (**co).m_operands[1].m_regname = NULL;\r
- }\r
-}\r
-\r
-static void cond_destroy (cond **co)\r
-{\r
- if (*co)\r
- {\r
- mem_free ((void **) &(**co).m_operands[0].m_regname);\r
- mem_free ((void **) &(**co).m_operands[1].m_regname);\r
- mem_free ((void **) co);\r
- }\r
-}\r
-\r
-/*\r
- specifier type typedef\r
-*/\r
-typedef enum spec_type_\r
-{\r
- st_false,\r
- st_true,\r
- st_byte,\r
- st_byte_range,\r
- st_string,\r
- st_identifier,\r
- st_identifier_loop,\r
- st_debug\r
-} spec_type;\r
-\r
-/*\r
- specifier typedef\r
-*/\r
-typedef struct spec_\r
-{\r
- spec_type m_spec_type;\r
- byte m_byte[2]; /* st_byte, st_byte_range */\r
- byte *m_string; /* st_string */\r
- struct rule_ *m_rule; /* st_identifier, st_identifier_loop */\r
- emit *m_emits;\r
- error *m_errtext;\r
- cond *m_cond;\r
- struct spec_ *m_next;\r
-} spec;\r
-\r
-static void spec_create (spec **sp)\r
-{\r
- *sp = mem_alloc (sizeof (spec));\r
- if (*sp)\r
- {\r
- (**sp).m_spec_type = st_false;\r
- (**sp).m_byte[0] = '\0';\r
- (**sp).m_byte[1] = '\0';\r
- (**sp).m_string = NULL;\r
- (**sp).m_rule = NULL;\r
- (**sp).m_emits = NULL;\r
- (**sp).m_errtext = NULL;\r
- (**sp).m_cond = NULL;\r
- (**sp).m_next = NULL;\r
- }\r
-}\r
-\r
-static void spec_destroy (spec **sp)\r
-{\r
- if (*sp)\r
- {\r
- spec_destroy (&(**sp).m_next);\r
- emit_destroy (&(**sp).m_emits);\r
- error_destroy (&(**sp).m_errtext);\r
- mem_free ((void **) &(**sp).m_string);\r
- cond_destroy (&(**sp).m_cond);\r
- mem_free ((void **) sp);\r
- }\r
-}\r
-\r
-static void spec_append (spec **sp, spec **ns)\r
-{\r
- while (*sp)\r
- sp = &(**sp).m_next;\r
- *sp = *ns;\r
-}\r
-\r
-/*\r
- operator typedef\r
-*/\r
-typedef enum oper_\r
-{\r
- op_none,\r
- op_and,\r
- op_or\r
-} oper;\r
-\r
-/*\r
- rule typedef\r
-*/\r
-typedef struct rule_\r
-{\r
- oper m_oper;\r
- spec *m_specs;\r
- struct rule_ *m_next;\r
-/* int m_referenced; */ /* for debugging purposes */\r
-} rule;\r
-\r
-static void rule_create (rule **ru)\r
-{\r
- *ru = mem_alloc (sizeof (rule));\r
- if (*ru)\r
- {\r
- (**ru).m_oper = op_none;\r
- (**ru).m_specs = NULL;\r
- (**ru).m_next = NULL;\r
-/* (**ru).m_referenced = 0; */\r
- }\r
-}\r
-\r
-static void rule_destroy (rule **ru)\r
-{\r
- if (*ru)\r
- {\r
- rule_destroy (&(**ru).m_next);\r
- spec_destroy (&(**ru).m_specs);\r
- mem_free ((void **) ru);\r
- }\r
-}\r
-\r
-static void rule_append (rule **ru, rule **nr)\r
-{\r
- while (*ru)\r
- ru = &(**ru).m_next;\r
- *ru = *nr;\r
-}\r
-\r
-/*\r
- returns unique grammar id\r
-*/\r
-static grammar next_valid_grammar_id ()\r
-{\r
- static grammar id = 0;\r
-\r
- return ++id;\r
-}\r
-\r
-/*\r
- dictionary typedef\r
-*/\r
-typedef struct dict_\r
-{\r
- rule *m_rulez;\r
- rule *m_syntax;\r
- rule *m_string;\r
- map_byte *m_regbytes;\r
- grammar m_id;\r
- struct dict_ *m_next;\r
-} dict;\r
-\r
-static void dict_create (dict **di)\r
-{\r
- *di = mem_alloc (sizeof (dict));\r
- if (*di)\r
- {\r
- (**di).m_rulez = NULL;\r
- (**di).m_syntax = NULL;\r
- (**di).m_string = NULL;\r
- (**di).m_regbytes = NULL;\r
- (**di).m_id = next_valid_grammar_id ();\r
- (**di).m_next = NULL;\r
- }\r
-}\r
-\r
-static void dict_destroy (dict **di)\r
-{\r
- if (*di)\r
- {\r
- rule_destroy (&(**di).m_rulez);\r
- map_byte_destroy (&(**di).m_regbytes);\r
- mem_free ((void **) di);\r
- }\r
-}\r
-\r
-static void dict_append (dict **di, dict **nd)\r
-{\r
- while (*di)\r
- di = &(**di).m_next;\r
- *di = *nd;\r
-}\r
-\r
-static void dict_find (dict **di, grammar key, dict **data)\r
-{\r
- while (*di)\r
- {\r
- if ((**di).m_id == key)\r
- {\r
- *data = *di;\r
- return;\r
- }\r
-\r
- di = &(**di).m_next;\r
- }\r
-\r
- *data = NULL;\r
-}\r
-\r
-static dict *g_dicts = NULL;\r
-\r
-/*\r
- byte array typedef\r
-\r
- XXX this class is going to be replaced by a faster one, soon\r
-*/\r
-typedef struct barray_\r
-{\r
- byte *data;\r
- unsigned int len;\r
-} barray;\r
-\r
-static void barray_create (barray **ba)\r
-{\r
- *ba = mem_alloc (sizeof (barray));\r
- if (*ba)\r
- {\r
- (**ba).data = NULL;\r
- (**ba).len = 0;\r
- }\r
-}\r
-\r
-static void barray_destroy (barray **ba)\r
-{\r
- if (*ba)\r
- {\r
- mem_free ((void **) &(**ba).data);\r
- mem_free ((void **) ba);\r
- }\r
-}\r
-\r
-/*\r
- reallocates byte array to requested size,\r
- returns 0 on success,\r
- returns 1 otherwise\r
-*/\r
-static int barray_resize (barray **ba, unsigned int nlen)\r
-{\r
- byte *new_pointer;\r
-\r
- if (nlen == 0)\r
- {\r
- mem_free ((void **) &(**ba).data);\r
- (**ba).data = NULL;\r
- (**ba).len = 0;\r
-\r
- return 0;\r
- }\r
- else\r
- {\r
- new_pointer = mem_realloc ((**ba).data, (**ba).len * sizeof (byte), nlen * sizeof (byte));\r
- if (new_pointer)\r
- {\r
- (**ba).data = new_pointer;\r
- (**ba).len = nlen;\r
-\r
- return 0;\r
- }\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-/*\r
- adds byte array pointed by *nb to the end of array pointed by *ba,\r
- returns 0 on success,\r
- returns 1 otherwise\r
-*/\r
-static int barray_append (barray **ba, barray **nb)\r
-{\r
- const unsigned int len = (**ba).len;\r
-\r
- if (barray_resize (ba, (**ba).len + (**nb).len))\r
- return 1;\r
-\r
- mem_copy ((**ba).data + len, (**nb).data, (**nb).len);\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- adds emit chain pointed by em to the end of array pointed by *ba,\r
- returns 0 on success,\r
- returns 1 otherwise\r
-*/\r
-static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc)\r
-{\r
- emit *temp = em;\r
- unsigned int count = 0;\r
-\r
- while (temp)\r
- {\r
- if (temp->m_emit_dest == ed_output)\r
- if (temp->m_emit_type == et_position)\r
- count += 4; /* position is a 32-bit unsigned integer */\r
- else\r
- count++;\r
-\r
- temp = temp->m_next;\r
- }\r
-\r
- if (barray_resize (ba, (**ba).len + count))\r
- return 1;\r
-\r
- while (em)\r
- {\r
- if (em->m_emit_dest == ed_output)\r
- {\r
- if (em->m_emit_type == et_byte)\r
- (**ba).data[(**ba).len - count--] = em->m_byte;\r
- else if (em->m_emit_type == et_stream)\r
- (**ba).data[(**ba).len - count--] = c;\r
- else // em->type == et_position\r
- (**ba).data[(**ba).len - count--] = (byte) pos,\r
- (**ba).data[(**ba).len - count--] = (byte) (pos >> 8),\r
- (**ba).data[(**ba).len - count--] = (byte) (pos >> 16),\r
- (**ba).data[(**ba).len - count--] = (byte) (pos >> 24);\r
- }\r
- else\r
- {\r
- regbyte_ctx *new_rbc;\r
- regbyte_ctx_create (&new_rbc);\r
- if (new_rbc == NULL)\r
- return 1;\r
-\r
- new_rbc->m_prev = *rbc;\r
- new_rbc->m_regbyte = em->m_regbyte;\r
- *rbc = new_rbc;\r
-\r
- if (em->m_emit_type == et_byte)\r
- new_rbc->m_current_value = em->m_byte;\r
- else if (em->m_emit_type == et_stream)\r
- new_rbc->m_current_value = c;\r
- }\r
-\r
- em = em->m_next;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- string to string map typedef\r
-*/\r
-typedef struct map_str_\r
-{\r
- byte *key;\r
- byte *data;\r
- struct map_str_ *next;\r
-} map_str;\r
-\r
-static void map_str_create (map_str **ma)\r
-{\r
- *ma = mem_alloc (sizeof (map_str));\r
- if (*ma)\r
- {\r
- (**ma).key = NULL;\r
- (**ma).data = NULL;\r
- (**ma).next = NULL;\r
- }\r
-}\r
-\r
-static void map_str_destroy (map_str **ma)\r
-{\r
- if (*ma)\r
- {\r
- map_str_destroy (&(**ma).next);\r
- mem_free ((void **) &(**ma).key);\r
- mem_free ((void **) &(**ma).data);\r
- mem_free ((void **) ma);\r
- }\r
-}\r
-\r
-static void map_str_append (map_str **ma, map_str **nm)\r
-{\r
- while (*ma)\r
- ma = &(**ma).next;\r
- *ma = *nm;\r
-}\r
-\r
-/*\r
- searches the map for specified key,\r
- if the key is matched, *data is filled with data associated with the key,\r
- returns 0 if the key is matched,\r
- returns 1 otherwise\r
-*/\r
-static int map_str_find (map_str **ma, const byte *key, byte **data)\r
-{\r
- while (*ma)\r
- {\r
- if (str_equal ((**ma).key, key))\r
- {\r
- *data = str_duplicate ((**ma).data);\r
- if (*data == NULL)\r
- return 1;\r
-\r
- return 0;\r
- }\r
-\r
- ma = &(**ma).next;\r
- }\r
-\r
- set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);\r
- return 1;\r
-}\r
-\r
-/*\r
- string to rule map typedef\r
-*/\r
-typedef struct map_rule_\r
-{\r
- byte *key;\r
- rule *data;\r
- struct map_rule_ *next;\r
-} map_rule;\r
-\r
-static void map_rule_create (map_rule **ma)\r
-{\r
- *ma = mem_alloc (sizeof (map_rule));\r
- if (*ma)\r
- {\r
- (**ma).key = NULL;\r
- (**ma).data = NULL;\r
- (**ma).next = NULL;\r
- }\r
-}\r
-\r
-static void map_rule_destroy (map_rule **ma)\r
-{\r
- if (*ma)\r
- {\r
- map_rule_destroy (&(**ma).next);\r
- mem_free ((void **) &(**ma).key);\r
- mem_free ((void **) ma);\r
- }\r
-}\r
-\r
-static void map_rule_append (map_rule **ma, map_rule **nm)\r
-{\r
- while (*ma)\r
- ma = &(**ma).next;\r
- *ma = *nm;\r
-}\r
-\r
-/*\r
- searches the map for specified key,\r
- if the key is matched, *data is filled with data associated with the key,\r
- returns 0 if the is matched,\r
- returns 1 otherwise\r
-*/\r
-static int map_rule_find (map_rule **ma, const byte *key, rule **data)\r
-{\r
- while (*ma)\r
- {\r
- if (str_equal ((**ma).key, key))\r
- {\r
- *data = (**ma).data;\r
-\r
- return 0;\r
- }\r
-\r
- ma = &(**ma).next;\r
- }\r
-\r
- set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);\r
- return 1;\r
-}\r
-\r
-/*\r
- returns 1 if given character is a white space,\r
- returns 0 otherwise\r
-*/\r
-static int is_space (byte c)\r
-{\r
- return c == ' ' || c == '\t' || c == '\n' || c == '\r';\r
-}\r
-\r
-/*\r
- advances text pointer by 1 if character pointed by *text is a space,\r
- returns 1 if a space has been eaten,\r
- returns 0 otherwise\r
-*/\r
-static int eat_space (const byte **text)\r
-{\r
- if (is_space (**text))\r
- {\r
- (*text)++;\r
-\r
- return 1;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 1 if text points to C-style comment start string "/*",\r
- returns 0 otherwise\r
-*/\r
-static int is_comment_start (const byte *text)\r
-{\r
- return text[0] == '/' && text[1] == '*';\r
-}\r
-\r
-/*\r
- advances text pointer to first character after C-style comment block - if any,\r
- returns 1 if C-style comment block has been encountered and eaten,\r
- returns 0 otherwise\r
-*/\r
-static int eat_comment (const byte **text)\r
-{\r
- if (is_comment_start (*text))\r
- {\r
- /* *text points to comment block - skip two characters to enter comment body */\r
- *text += 2;\r
- /* skip any character except consecutive '*' and '/' */\r
- while (!((*text)[0] == '*' && (*text)[1] == '/'))\r
- (*text)++;\r
- /* skip those two terminating characters */\r
- *text += 2;\r
-\r
- return 1;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- advances text pointer to first character that is neither space nor C-style comment block\r
-*/\r
-static void eat_spaces (const byte **text)\r
-{\r
- while (eat_space (text) || eat_comment (text))\r
- ;\r
-}\r
-\r
-/*\r
- resizes string pointed by *ptr to successfully add character c to the end of the string,\r
- returns 0 on success,\r
- returns 1 otherwise\r
-*/\r
-static int string_grow (byte **ptr, unsigned int *len, byte c)\r
-{\r
- /* reallocate the string in 16-byte increments */\r
- if ((*len & 0x0F) == 0x0F || *ptr == NULL)\r
- {\r
- byte *tmp = mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),\r
- ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));\r
- if (tmp == NULL)\r
- return 1;\r
-\r
- *ptr = tmp;\r
- }\r
-\r
- if (c)\r
- {\r
- /* append given character */\r
- (*ptr)[*len] = c;\r
- (*len)++;\r
- }\r
- (*ptr)[*len] = '\0';\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _\r
- returns 0 otherwise\r
-*/\r
-static int is_identifier (byte c)\r
-{\r
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';\r
-}\r
-\r
-/*\r
- copies characters from *text to *id until non-identifier character is encountered,\r
- assumes that *id points to NULL object - caller is responsible for later freeing the string,\r
- text pointer is advanced to point past the copied identifier,\r
- returns 0 if identifier was successfully copied,\r
- returns 1 otherwise\r
-*/\r
-static int get_identifier (const byte **text, byte **id)\r
-{\r
- const byte *t = *text;\r
- byte *p = NULL;\r
- unsigned int len = 0;\r
-\r
- if (string_grow (&p, &len, '\0'))\r
- return 1;\r
-\r
- /* loop while next character in buffer is valid for identifiers */\r
- while (is_identifier (*t))\r
- {\r
- if (string_grow (&p, &len, *t++))\r
- {\r
- mem_free ((void **) &p);\r
- return 1;\r
- }\r
- }\r
-\r
- *text = t;\r
- *id = p;\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 1 if given character is HEX digit 0-9, A-F or a-f,\r
- returns 0 otherwise\r
-*/\r
-static int is_hex (byte c)\r
-{\r
- return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');\r
-}\r
-\r
-/*\r
- returns value of passed character as if it was HEX digit\r
-*/\r
-static unsigned int hex2dec (byte c)\r
-{\r
- if (c >= '0' && c <= '9')\r
- return c - '0';\r
- if (c >= 'A' && c <= 'F')\r
- return c - 'A' + 10;\r
- return c - 'a' + 10;\r
-}\r
-\r
-/*\r
- converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,\r
- advances text pointer past the converted sequence,\r
- returns the converted value\r
-*/\r
-static unsigned int hex_convert (const byte **text)\r
-{\r
- unsigned int value = 0;\r
-\r
- while (is_hex (**text))\r
- {\r
- value = value * 0x10 + hex2dec (**text);\r
- (*text)++;\r
- }\r
-\r
- return value;\r
-}\r
-\r
-/*\r
- returns 1 if given character is OCT digit 0-7,\r
- returns 0 otherwise\r
-*/\r
-static int is_oct (byte c)\r
-{\r
- return c >= '0' && c <= '7';\r
-}\r
-\r
-/*\r
- returns value of passed character as if it was OCT digit\r
-*/\r
-static int oct2dec (byte c)\r
-{\r
- return c - '0';\r
-}\r
-\r
-static byte get_escape_sequence (const byte **text)\r
-{\r
- int value = 0;\r
-\r
- /* skip '\' character */\r
- (*text)++;\r
-\r
- switch (*(*text)++)\r
- {\r
- case '\'':\r
- return '\'';\r
- case '"':\r
- return '\"';\r
- case '?':\r
- return '\?';\r
- case '\\':\r
- return '\\';\r
- case 'a':\r
- return '\a';\r
- case 'b':\r
- return '\b';\r
- case 'f':\r
- return '\f';\r
- case 'n':\r
- return '\n';\r
- case 'r':\r
- return '\r';\r
- case 't':\r
- return '\t';\r
- case 'v':\r
- return '\v';\r
- case 'x':\r
- return (byte) hex_convert (text);\r
- }\r
-\r
- (*text)--;\r
- if (is_oct (**text))\r
- {\r
- value = oct2dec (*(*text)++);\r
- if (is_oct (**text))\r
- {\r
- value = value * 010 + oct2dec (*(*text)++);\r
- if (is_oct (**text))\r
- value = value * 010 + oct2dec (*(*text)++);\r
- }\r
- }\r
-\r
- return (byte) value;\r
-}\r
-\r
-/*\r
- copies characters from *text to *str until " or ' character is encountered,\r
- assumes that *str points to NULL object - caller is responsible for later freeing the string,\r
- assumes that *text points to " or ' character that starts the string,\r
- text pointer is advanced to point past the " or ' character,\r
- returns 0 if string was successfully copied,\r
- returns 1 otherwise\r
-*/\r
-static int get_string (const byte **text, byte **str)\r
-{\r
- const byte *t = *text;\r
- byte *p = NULL;\r
- unsigned int len = 0;\r
- byte term_char;\r
-\r
- if (string_grow (&p, &len, '\0'))\r
- return 1;\r
-\r
- /* read " or ' character that starts the string */\r
- term_char = *t++;\r
- /* while next character is not the terminating character */\r
- while (*t && *t != term_char)\r
- {\r
- byte c;\r
-\r
- if (*t == '\\')\r
- c = get_escape_sequence (&t);\r
- else\r
- c = *t++;\r
-\r
- if (string_grow (&p, &len, c))\r
- {\r
- mem_free ((void **) &p);\r
- return 1;\r
- }\r
- }\r
- /* skip " or ' character that ends the string */\r
- t++;\r
-\r
- *text = t;\r
- *str = p;\r
- return 0;\r
-}\r
-\r
-/*\r
- gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>\r
- assumes that *text already points to <symbol>,\r
- returns 0 if emit code is successfully read,\r
- returns 1 otherwise\r
-*/\r
-static int get_emtcode (const byte **text, map_byte **ma)\r
-{\r
- const byte *t = *text;\r
- map_byte *m = NULL;\r
-\r
- map_byte_create (&m);\r
- if (m == NULL)\r
- return 1;\r
-\r
- if (get_identifier (&t, &m->key))\r
- {\r
- map_byte_destroy (&m);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- if (*t == '\'')\r
- {\r
- byte *c;\r
-\r
- if (get_string (&t, &c))\r
- {\r
- map_byte_destroy (&m);\r
- return 1;\r
- }\r
-\r
- m->data = (byte) c[0];\r
- mem_free ((void **) &c);\r
- }\r
- else\r
- {\r
- /* skip HEX "0x" or "0X" prefix */\r
- t += 2;\r
- m->data = (byte) hex_convert (&t);\r
- }\r
-\r
- eat_spaces (&t);\r
-\r
- *text = t;\r
- *ma = m;\r
- return 0;\r
-}\r
-\r
-/*\r
- gets regbyte declaration, the syntax is: ".regbyte" " " <symbol> " " ("0x" | "0X") <hex_value>\r
- assumes that *text already points to <symbol>,\r
- returns 0 if regbyte is successfully read,\r
- returns 1 otherwise\r
-*/\r
-static int get_regbyte (const byte **text, map_byte **ma)\r
-{\r
- return get_emtcode (text, ma);\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise\r
-*/\r
-static int get_errtext (const byte **text, map_str **ma)\r
-{\r
- const byte *t = *text;\r
- map_str *m = NULL;\r
-\r
- map_str_create (&m);\r
- if (m == NULL)\r
- return 1;\r
-\r
- if (get_identifier (&t, &m->key))\r
- {\r
- map_str_destroy (&m);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- if (get_string (&t, &m->data))\r
- {\r
- map_str_destroy (&m);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- *text = t;\r
- *ma = m;\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise,\r
-*/\r
-static int get_error (const byte **text, error **er, map_str *maps)\r
-{\r
- const byte *t = *text;\r
- byte *temp = NULL;\r
-\r
- if (*t != '.')\r
- return 0;\r
-\r
- t++;\r
- if (get_identifier (&t, &temp))\r
- return 1;\r
- eat_spaces (&t);\r
-\r
- if (!str_equal ((byte *) "error", temp))\r
- {\r
- mem_free ((void **) &temp);\r
- return 0;\r
- }\r
-\r
- mem_free ((void **) &temp);\r
-\r
- error_create (er);\r
- if (*er == NULL)\r
- return 1;\r
-\r
- if (*t == '\"')\r
- {\r
- if (get_string (&t, &(**er).m_text))\r
- {\r
- error_destroy (er);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
- }\r
- else\r
- {\r
- if (get_identifier (&t, &temp))\r
- {\r
- error_destroy (er);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- if (map_str_find (&maps, temp, &(**er).m_text))\r
- {\r
- mem_free ((void **) &temp);\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- mem_free ((void **) &temp);\r
- }\r
-\r
- /* try to extract "token" from "...$token$..." */\r
- {\r
- byte *processed = NULL;\r
- unsigned int len = 0, i = 0;\r
-\r
- if (string_grow (&processed, &len, '\0'))\r
- {\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- while (i < str_length ((**er).m_text))\r
- {\r
- /* check if the dollar sign is repeated - if so skip it */\r
- if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$')\r
- {\r
- if (string_grow (&processed, &len, '$'))\r
- {\r
- mem_free ((void **) &processed);\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- i += 2;\r
- }\r
- else if ((**er).m_text[i] != '$')\r
- {\r
- if (string_grow (&processed, &len, (**er).m_text[i]))\r
- {\r
- mem_free ((void **) &processed);\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- i++;\r
- }\r
- else\r
- {\r
- if (string_grow (&processed, &len, '$'))\r
- {\r
- mem_free ((void **) &processed);\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- {\r
- /* length of token being extracted */\r
- unsigned int tlen = 0;\r
-\r
- if (string_grow (&(**er).m_token_name, &tlen, '\0'))\r
- {\r
- mem_free ((void **) &processed);\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- /* skip the dollar sign */\r
- i++;\r
-\r
- while ((**er).m_text[i] != '$')\r
- {\r
- if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i]))\r
- {\r
- mem_free ((void **) &processed);\r
- error_destroy (er);\r
- return 1;\r
- }\r
-\r
- i++;\r
- }\r
-\r
- /* skip the dollar sign */\r
- i++;\r
- }\r
- }\r
- }\r
-\r
- mem_free ((void **) &(**er).m_text);\r
- (**er).m_text = processed;\r
- }\r
-\r
- *text = t;\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise,\r
-*/\r
-static int get_emits (const byte **text, emit **em, map_byte *mapb)\r
-{\r
- const byte *t = *text;\r
- byte *temp = NULL;\r
- emit *e = NULL;\r
- emit_dest dest;\r
-\r
- if (*t != '.')\r
- return 0;\r
-\r
- t++;\r
- if (get_identifier (&t, &temp))\r
- return 1;\r
- eat_spaces (&t);\r
-\r
- /* .emit */\r
- if (str_equal ((byte *) "emit", temp))\r
- dest = ed_output;\r
- /* .load */\r
- else if (str_equal ((byte *) "load", temp))\r
- dest = ed_regbyte;\r
- else\r
- {\r
- mem_free ((void **) &temp);\r
- return 0;\r
- }\r
-\r
- mem_free ((void **) &temp);\r
-\r
- emit_create (&e);\r
- if (e == NULL)\r
- return 1;\r
-\r
- e->m_emit_dest = dest;\r
-\r
- if (dest == ed_regbyte)\r
- {\r
- if (get_identifier (&t, &e->m_regname))\r
- {\r
- emit_destroy (&e);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
- }\r
-\r
- /* 0xNN */\r
- if (*t == '0')\r
- {\r
- t += 2;\r
- e->m_byte = (byte) hex_convert (&t);\r
-\r
- e->m_emit_type = et_byte;\r
- }\r
- /* * */\r
- else if (*t == '*')\r
- {\r
- t++;\r
-\r
- e->m_emit_type = et_stream;\r
- }\r
- /* $ */\r
- else if (*t == '$')\r
- {\r
- t++;\r
-\r
- e->m_emit_type = et_position;\r
- }\r
- /* 'c' */\r
- else if (*t == '\'')\r
- {\r
- if (get_string (&t, &temp))\r
- {\r
- emit_destroy (&e);\r
- return 1;\r
- }\r
- e->m_byte = (byte) temp[0];\r
-\r
- mem_free ((void **) &temp);\r
-\r
- e->m_emit_type = et_byte;\r
- }\r
- else\r
- {\r
- if (get_identifier (&t, &temp))\r
- {\r
- emit_destroy (&e);\r
- return 1;\r
- }\r
-\r
- if (map_byte_find (&mapb, temp, &e->m_byte))\r
- {\r
- mem_free ((void **) &temp);\r
- emit_destroy (&e);\r
- return 1;\r
- }\r
-\r
- mem_free ((void **) &temp);\r
-\r
- e->m_emit_type = et_byte;\r
- }\r
-\r
- eat_spaces (&t);\r
-\r
- if (get_emits (&t, &e->m_next, mapb))\r
- {\r
- emit_destroy (&e);\r
- return 1;\r
- }\r
-\r
- *text = t;\r
- *em = e;\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise,\r
-*/\r
-static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb)\r
-{\r
- const byte *t = *text;\r
- spec *s = NULL;\r
-\r
- spec_create (&s);\r
- if (s == NULL)\r
- return 1;\r
-\r
- /* first - read optional .if statement */\r
- if (*t == '.')\r
- {\r
- const byte *u = t;\r
- byte *keyword = NULL;\r
-\r
- /* skip the dot */\r
- u++;\r
-\r
- if (get_identifier (&u, &keyword))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
-\r
- /* .if */\r
- if (str_equal ((byte *) "if", keyword))\r
- {\r
- cond_create (&s->m_cond);\r
- if (s->m_cond == NULL)\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
-\r
- /* skip the left paren */\r
- eat_spaces (&u);\r
- u++;\r
-\r
- /* get the left operand */\r
- eat_spaces (&u);\r
- if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- s->m_cond->m_operands[0].m_type = cot_regbyte;\r
-\r
- /* get the operator (!= or ==) */\r
- eat_spaces (&u);\r
- if (*u == '!')\r
- s->m_cond->m_type = ct_not_equal;\r
- else\r
- s->m_cond->m_type = ct_equal;\r
- u += 2;\r
-\r
- /* skip the 0x prefix */\r
- eat_spaces (&u);\r
- u += 2;\r
-\r
- /* get the right operand */\r
- s->m_cond->m_operands[1].m_byte = hex_convert (&u);\r
- s->m_cond->m_operands[1].m_type = cot_byte;\r
-\r
- /* skip the right paren */\r
- eat_spaces (&u);\r
- u++;\r
-\r
- eat_spaces (&u);\r
-\r
- t = u;\r
- }\r
-\r
- mem_free ((void **) &keyword);\r
- }\r
-\r
- if (*t == '\'')\r
- {\r
- byte *temp = NULL;\r
-\r
- if (get_string (&t, &temp))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- if (*t == '-')\r
- {\r
- byte *temp2 = NULL;\r
-\r
- /* skip the '-' character */\r
- t++;\r
- eat_spaces (&t);\r
-\r
- if (get_string (&t, &temp2))\r
- {\r
- mem_free ((void **) &temp);\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- s->m_spec_type = st_byte_range;\r
- s->m_byte[0] = *temp;\r
- s->m_byte[1] = *temp2;\r
-\r
- mem_free ((void **) &temp2);\r
- }\r
- else\r
- {\r
- s->m_spec_type = st_byte;\r
- *s->m_byte = *temp;\r
- }\r
-\r
- mem_free ((void **) &temp);\r
- }\r
- else if (*t == '"')\r
- {\r
- if (get_string (&t, &s->m_string))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- s->m_spec_type = st_string;\r
- }\r
- else if (*t == '.')\r
- {\r
- byte *keyword = NULL;\r
-\r
- /* skip the dot */\r
- t++;\r
-\r
- if (get_identifier (&t, &keyword))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- /* .true */\r
- if (str_equal ((byte *) "true", keyword))\r
- {\r
- s->m_spec_type = st_true;\r
- }\r
- /* .false */\r
- else if (str_equal ((byte *) "false", keyword))\r
- {\r
- s->m_spec_type = st_false;\r
- }\r
- /* .debug */\r
- else if (str_equal ((byte *) "debug", keyword))\r
- {\r
- s->m_spec_type = st_debug;\r
- }\r
- /* .loop */\r
- else if (str_equal ((byte *) "loop", keyword))\r
- {\r
- if (get_identifier (&t, &s->m_string))\r
- {\r
- mem_free ((void **) &keyword);\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- s->m_spec_type = st_identifier_loop;\r
- }\r
-\r
- mem_free ((void **) &keyword);\r
- }\r
- else\r
- {\r
- if (get_identifier (&t, &s->m_string))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- s->m_spec_type = st_identifier;\r
- }\r
-\r
- if (get_error (&t, &s->m_errtext, maps))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
-\r
- if (get_emits (&t, &s->m_emits, mapb))\r
- {\r
- spec_destroy (&s);\r
- return 1;\r
- }\r
-\r
- *text = t;\r
- *sp = s;\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise,\r
-*/\r
-static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)\r
-{\r
- const byte *t = *text;\r
- rule *r = NULL;\r
-\r
- rule_create (&r);\r
- if (r == NULL)\r
- return 1;\r
-\r
- if (get_spec (&t, &r->m_specs, maps, mapb))\r
- {\r
- rule_destroy (&r);\r
- return 1;\r
- }\r
-\r
- while (*t != ';')\r
- {\r
- byte *op = NULL;\r
- spec *sp = NULL;\r
-\r
- /* skip the dot that precedes "and" or "or" */\r
- t++;\r
-\r
- /* read "and" or "or" keyword */\r
- if (get_identifier (&t, &op))\r
- {\r
- rule_destroy (&r);\r
- return 1;\r
- }\r
- eat_spaces (&t);\r
-\r
- if (r->m_oper == op_none)\r
- {\r
- /* .and */\r
- if (str_equal ((byte *) "and", op))\r
- r->m_oper = op_and;\r
- /* .or */\r
- else\r
- r->m_oper = op_or;\r
- }\r
-\r
- mem_free ((void **) &op);\r
-\r
- if (get_spec (&t, &sp, maps, mapb))\r
- {\r
- rule_destroy (&r);\r
- return 1;\r
- }\r
-\r
- spec_append (&r->m_specs, &sp);\r
- }\r
-\r
- /* skip the semicolon */\r
- t++;\r
- eat_spaces (&t);\r
-\r
- *text = t;\r
- *ru = r;\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise,\r
-*/\r
-static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)\r
-{\r
- if (map_rule_find (&mapr, symbol, ru))\r
- return 1;\r
-\r
-/* (**ru).m_referenced = 1; */\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- returns 0 on success,\r
- returns 1 otherwise,\r
-*/\r
-static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,\r
- byte **string_symbol, map_byte *regbytes)\r
-{\r
- rule *rulez = di->m_rulez;\r
-\r
- /* update dependecies for the root and lexer symbols */\r
- if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||\r
- (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))\r
- return 1;\r
-\r
- mem_free ((void **) syntax_symbol);\r
- mem_free ((void **) string_symbol);\r
-\r
- /* update dependecies for the rest of the rules */\r
- while (rulez)\r
- {\r
- spec *sp = rulez->m_specs;\r
-\r
- /* iterate through all the specifiers */\r
- while (sp)\r
- {\r
- /* update dependency for identifier */\r
- if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)\r
- {\r
- if (update_dependency (mapr, sp->m_string, &sp->m_rule))\r
- return 1;\r
-\r
- mem_free ((void **) &sp->m_string);\r
- }\r
-\r
- /* some errtexts reference to a rule */\r
- if (sp->m_errtext && sp->m_errtext->m_token_name)\r
- {\r
- if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))\r
- return 1;\r
-\r
- mem_free ((void **) &sp->m_errtext->m_token_name);\r
- }\r
-\r
- /* update dependency for condition */\r
- if (sp->m_cond)\r
- {\r
- int i;\r
- for (i = 0; i < 2; i++)\r
- if (sp->m_cond->m_operands[i].m_type == cot_regbyte)\r
- {\r
- sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (®bytes,\r
- sp->m_cond->m_operands[i].m_regname);\r
-\r
- if (sp->m_cond->m_operands[i].m_regbyte == NULL)\r
- return 1;\r
-\r
- mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);\r
- }\r
- }\r
-\r
- /* update dependency for all .load instructions */\r
- if (sp->m_emits)\r
- {\r
- emit *em = sp->m_emits;\r
- while (em != NULL)\r
- {\r
- if (em->m_emit_dest == ed_regbyte)\r
- {\r
- em->m_regbyte = map_byte_locate (®bytes, em->m_regname);\r
-\r
- if (em->m_regbyte == NULL)\r
- return 1;\r
-\r
- mem_free ((void **) &em->m_regname);\r
- }\r
-\r
- em = em->m_next;\r
- }\r
- }\r
-\r
- sp = sp->m_next;\r
- }\r
-\r
- rulez = rulez->m_next;\r
- }\r
-\r
-/* check for unreferenced symbols */\r
-/* de = di->m_defntns;\r
- while (de)\r
- {\r
- if (!de->m_referenced)\r
- {\r
- map_def *ma = mapd;\r
- while (ma)\r
- {\r
- if (ma->data == de)\r
- {\r
- assert (0);\r
- break;\r
- }\r
- ma = ma->next;\r
- }\r
- }\r
- de = de->m_next;\r
- }\r
-*/\r
- return 0;\r
-}\r
-\r
-static int satisfies_condition (cond *co, regbyte_ctx *ctx)\r
-{\r
- byte values[2];\r
- int i;\r
-\r
- if (co == NULL)\r
- return 1;\r
-\r
- for (i = 0; i < 2; i++)\r
- switch (co->m_operands[i].m_type)\r
- {\r
- case cot_byte:\r
- values[i] = co->m_operands[i].m_byte;\r
- break;\r
- case cot_regbyte:\r
- values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);\r
- break;\r
- }\r
-\r
- switch (co->m_type)\r
- {\r
- case ct_equal:\r
- return values[0] == values[1];\r
- case ct_not_equal:\r
- return values[0] != values[1];\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)\r
-{\r
- while (top != limit)\r
- {\r
- regbyte_ctx *rbc = top->m_prev;\r
- regbyte_ctx_destroy (&top);\r
- top = rbc;\r
- }\r
-}\r
-\r
-typedef enum match_result_\r
-{\r
- mr_not_matched, /* the examined string does not match */\r
- mr_matched, /* the examined string matches */\r
- mr_error_raised, /* mr_not_matched + error has been raised */\r
- mr_dont_emit, /* used by identifier loops only */\r
- mr_internal_error /* an internal error has occured such as out of memory */\r
-} match_result;\r
-\r
-/*\r
- This function does the main job. It parses the text and generates output data.\r
-\r
- XXX optimize it - the barray seems to be the bottleneck\r
-*/\r
-static match_result match (dict *di, const byte *text, unsigned int *index, rule *ru, barray **ba,\r
- int filtering_string, regbyte_ctx **rbc)\r
-{\r
- unsigned int ind = *index;\r
- match_result status = mr_not_matched;\r
- spec *sp = ru->m_specs;\r
- regbyte_ctx *ctx = *rbc;\r
-\r
- /* for every specifier in the rule */\r
- while (sp)\r
- {\r
- unsigned int i, len, save_ind = ind;\r
- barray *array = NULL;\r
-\r
- if (satisfies_condition (sp->m_cond, ctx))\r
- {\r
- switch (sp->m_spec_type)\r
- {\r
- case st_identifier:\r
- barray_create (&array);\r
- if (array == NULL)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- return mr_internal_error;\r
- }\r
-\r
- status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);\r
- if (status == mr_internal_error)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
- return mr_internal_error;\r
- }\r
- break;\r
- case st_string:\r
- len = str_length (sp->m_string);\r
-\r
- /* prefilter the stream */\r
- if (!filtering_string && di->m_string)\r
- {\r
- barray *ba;\r
- unsigned int filter_index = 0;\r
- match_result result;\r
- regbyte_ctx *null_ctx = NULL;\r
-\r
- barray_create (&ba);\r
- if (ba == NULL)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- return mr_internal_error;\r
- }\r
-\r
- result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);\r
-\r
- if (result == mr_internal_error)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&ba);\r
- return mr_internal_error;\r
- }\r
-\r
- if (result != mr_matched)\r
- {\r
- barray_destroy (&ba);\r
- status = mr_not_matched;\r
- break;\r
- }\r
-\r
- barray_destroy (&ba);\r
-\r
- if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))\r
- {\r
- status = mr_not_matched;\r
- break;\r
- }\r
-\r
- status = mr_matched;\r
- ind += len;\r
- }\r
- else\r
- {\r
- status = mr_matched;\r
- for (i = 0; status == mr_matched && i < len; i++)\r
- if (text[ind + i] != sp->m_string[i])\r
- status = mr_not_matched;\r
- if (status == mr_matched)\r
- ind += len;\r
- }\r
- break;\r
- case st_byte:\r
- status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;\r
- if (status == mr_matched)\r
- ind++;\r
- break;\r
- case st_byte_range:\r
- status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?\r
- mr_matched : mr_not_matched;\r
- if (status == mr_matched)\r
- ind++;\r
- break;\r
- case st_true:\r
- status = mr_matched;\r
- break;\r
- case st_false:\r
- status = mr_not_matched;\r
- break;\r
- case st_debug:\r
- status = ru->m_oper == op_and ? mr_matched : mr_not_matched;\r
- break;\r
- case st_identifier_loop:\r
- barray_create (&array);\r
- if (array == NULL)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- return mr_internal_error;\r
- }\r
-\r
- status = mr_dont_emit;\r
- for (;;)\r
- {\r
- match_result result;\r
-\r
- save_ind = ind;\r
- result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);\r
-\r
- if (result == mr_error_raised)\r
- {\r
- status = result;\r
- break;\r
- }\r
- else if (result == mr_matched)\r
- {\r
- if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||\r
- barray_append (ba, &array))\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
- return mr_internal_error;\r
- }\r
- barray_destroy (&array);\r
- barray_create (&array);\r
- if (array == NULL)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- return mr_internal_error;\r
- }\r
- }\r
- else if (result == mr_internal_error)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
- return mr_internal_error;\r
- }\r
- else\r
- break;\r
- }\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- status = mr_not_matched;\r
- }\r
-\r
- if (status == mr_error_raised)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
-\r
- return mr_error_raised;\r
- }\r
-\r
- if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
-\r
- if (sp->m_errtext)\r
- {\r
- set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,\r
- ind), ind);\r
-\r
- return mr_error_raised;\r
- }\r
-\r
- return mr_not_matched;\r
- }\r
-\r
- if (status == mr_matched)\r
- {\r
- if (sp->m_emits)\r
- if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx))\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
- return mr_internal_error;\r
- }\r
-\r
- if (array)\r
- if (barray_append (ba, &array))\r
- {\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- barray_destroy (&array);\r
- return mr_internal_error;\r
- }\r
- }\r
-\r
- barray_destroy (&array);\r
-\r
- /* if the rule operator is a logical or, we pick up the first matching specifier */\r
- if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))\r
- {\r
- *index = ind;\r
- *rbc = ctx;\r
- return mr_matched;\r
- }\r
-\r
- sp = sp->m_next;\r
- }\r
-\r
- /* everything went fine - all specifiers match up */\r
- if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))\r
- {\r
- *index = ind;\r
- *rbc = ctx;\r
- return mr_matched;\r
- }\r
-\r
- free_regbyte_ctx_stack (ctx, *rbc);\r
- return mr_not_matched;\r
-}\r
-\r
-static byte *error_get_token (error *er, dict *di, const byte *text, unsigned int ind)\r
-{\r
- byte *str = NULL;\r
-\r
- if (er->m_token)\r
- {\r
- barray *ba;\r
- unsigned int filter_index = 0;\r
- regbyte_ctx *ctx = NULL;\r
-\r
- barray_create (&ba);\r
- if (ba != NULL)\r
- {\r
- if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched &&\r
- filter_index)\r
- {\r
- str = mem_alloc (filter_index + 1);\r
- if (str != NULL)\r
- {\r
- str_copy_n (str, text + ind, filter_index);\r
- str[filter_index] = '\0';\r
- }\r
- }\r
- barray_destroy (&ba);\r
- }\r
- }\r
-\r
- return str;\r
-}\r
-\r
-typedef struct grammar_load_state_\r
-{\r
- dict *di;\r
- byte *syntax_symbol;\r
- byte *string_symbol;\r
- map_str *maps;\r
- map_byte *mapb;\r
- map_rule *mapr;\r
-} grammar_load_state;\r
-\r
-static void grammar_load_state_create (grammar_load_state **gr)\r
-{\r
- *gr = mem_alloc (sizeof (grammar_load_state));\r
- if (*gr)\r
- {\r
- (**gr).di = NULL;\r
- (**gr).syntax_symbol = NULL;\r
- (**gr).string_symbol = NULL;\r
- (**gr).maps = NULL;\r
- (**gr).mapb = NULL;\r
- (**gr).mapr = NULL;\r
- }\r
-}\r
-\r
-static void grammar_load_state_destroy (grammar_load_state **gr)\r
-{\r
- if (*gr)\r
- {\r
- dict_destroy (&(**gr).di);\r
- mem_free ((void **) &(**gr).syntax_symbol);\r
- mem_free ((void **) &(**gr).string_symbol);\r
- map_str_destroy (&(**gr).maps);\r
- map_byte_destroy (&(**gr).mapb);\r
- map_rule_destroy (&(**gr).mapr);\r
- mem_free ((void **) gr);\r
- }\r
-}\r
-\r
-/*\r
- the API\r
-*/\r
-\r
-grammar grammar_load_from_text (const byte *text)\r
-{\r
- grammar_load_state *g = NULL;\r
- grammar id = 0;\r
-\r
- clear_last_error ();\r
-\r
- grammar_load_state_create (&g);\r
- if (g == NULL)\r
- return 0;\r
-\r
- dict_create (&g->di);\r
- if (g->di == NULL)\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- eat_spaces (&text);\r
-\r
- /* skip ".syntax" keyword */\r
- text += 7;\r
- eat_spaces (&text);\r
-\r
- /* retrieve root symbol */\r
- if (get_identifier (&text, &g->syntax_symbol))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
- eat_spaces (&text);\r
-\r
- /* skip semicolon */\r
- text++;\r
- eat_spaces (&text);\r
-\r
- while (*text)\r
- {\r
- byte *symbol = NULL;\r
- int is_dot = *text == '.';\r
-\r
- if (is_dot)\r
- text++;\r
-\r
- if (get_identifier (&text, &symbol))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
- eat_spaces (&text);\r
-\r
- /* .emtcode */\r
- if (is_dot && str_equal (symbol, (byte *) "emtcode"))\r
- {\r
- map_byte *ma = NULL;\r
-\r
- mem_free ((void **) &symbol);\r
-\r
- if (get_emtcode (&text, &ma))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- map_byte_append (&g->mapb, &ma);\r
- }\r
- /* .regbyte */\r
- else if (is_dot && str_equal (symbol, (byte *) "regbyte"))\r
- {\r
- map_byte *ma = NULL;\r
-\r
- mem_free ((void **) &symbol);\r
-\r
- if (get_regbyte (&text, &ma))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- map_byte_append (&g->di->m_regbytes, &ma);\r
- }\r
- /* .errtext */\r
- else if (is_dot && str_equal (symbol, (byte *) "errtext"))\r
- {\r
- map_str *ma = NULL;\r
-\r
- mem_free ((void **) &symbol);\r
-\r
- if (get_errtext (&text, &ma))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- map_str_append (&g->maps, &ma);\r
- }\r
- /* .string */\r
- else if (is_dot && str_equal (symbol, (byte *) "string"))\r
- {\r
- mem_free ((void **) &symbol);\r
-\r
- if (g->di->m_string != NULL)\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- if (get_identifier (&text, &g->string_symbol))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- /* skip semicolon */\r
- eat_spaces (&text);\r
- text++;\r
- eat_spaces (&text);\r
- }\r
- else\r
- {\r
- rule *ru = NULL;\r
- map_rule *ma = NULL;\r
-\r
- if (get_rule (&text, &ru, g->maps, g->mapb))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- rule_append (&g->di->m_rulez, &ru);\r
-\r
- /* if a rule consist of only one specifier, give it an ".and" operator */\r
- if (ru->m_oper == op_none)\r
- ru->m_oper = op_and;\r
-\r
- map_rule_create (&ma);\r
- if (ma == NULL)\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- ma->key = symbol;\r
- ma->data = ru;\r
- map_rule_append (&g->mapr, &ma);\r
- }\r
- }\r
-\r
- if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol,\r
- g->di->m_regbytes))\r
- {\r
- grammar_load_state_destroy (&g);\r
- return 0;\r
- }\r
-\r
- dict_append (&g_dicts, &g->di);\r
- id = g->di->m_id;\r
- g->di = NULL;\r
-\r
- grammar_load_state_destroy (&g);\r
-\r
- return id;\r
-}\r
-\r
-int grammar_set_reg8 (grammar id, const byte *name, byte value)\r
-{\r
- dict *di = NULL;\r
- map_byte *reg = NULL;\r
-\r
- clear_last_error ();\r
-\r
- dict_find (&g_dicts, id, &di);\r
- if (di == NULL)\r
- {\r
- set_last_error (INVALID_GRAMMAR_ID, NULL, -1);\r
- return 0;\r
- }\r
-\r
- reg = map_byte_locate (&di->m_regbytes, name);\r
- if (reg == NULL)\r
- {\r
- set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1);\r
- return 0;\r
- }\r
-\r
- reg->data = value;\r
- return 1;\r
-}\r
-\r
-int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size)\r
-{\r
- dict *di = NULL;\r
- barray *ba = NULL;\r
- unsigned int index = 0;\r
- regbyte_ctx *rbc = NULL;\r
-\r
- clear_last_error ();\r
-\r
- dict_find (&g_dicts, id, &di);\r
- if (di == NULL)\r
- {\r
- set_last_error (INVALID_GRAMMAR_ID, NULL, -1);\r
- return 0;\r
- }\r
-\r
- barray_create (&ba);\r
- if (ba == NULL)\r
- return 0;\r
-\r
- *prod = NULL;\r
- *size = 0;\r
-\r
- if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched)\r
- {\r
- barray_destroy (&ba);\r
- free_regbyte_ctx_stack (rbc, NULL);\r
- return 0;\r
- }\r
-\r
- free_regbyte_ctx_stack (rbc, NULL);\r
-\r
- *prod = mem_alloc (ba->len * sizeof (byte));\r
- if (*prod == NULL)\r
- {\r
- barray_destroy (&ba);\r
- return 0;\r
- }\r
-\r
- mem_copy (*prod, ba->data, ba->len * sizeof (byte));\r
- *size = ba->len;\r
- barray_destroy (&ba);\r
-\r
- return 1;\r
-}\r
-\r
-int grammar_destroy (grammar id)\r
-{\r
- dict **di = &g_dicts;\r
-\r
- clear_last_error ();\r
-\r
- while (*di != NULL)\r
- {\r
- if ((**di).m_id == id)\r
- {\r
- dict *tmp = *di;\r
- *di = (**di).m_next;\r
- dict_destroy (&tmp);\r
- return 1;\r
- }\r
-\r
- di = &(**di).m_next;\r
- }\r
-\r
- set_last_error (INVALID_GRAMMAR_ID, NULL, -1);\r
- return 0;\r
-}\r
-\r
-void grammar_get_last_error (byte *text, unsigned int size, int *pos)\r
-{\r
- unsigned int len = 0, dots_made = 0;\r
- const byte *p = error_message;\r
-\r
- *text = '\0';\r
-\r
-#define APPEND_CHARACTER(x) if (dots_made == 0) {\\r
- if (len < size - 1) {\\r
- text[len++] = (x); text[len] = '\0';\\r
- } else {\\r
- int i;\\r
- for (i = 0; i < 3; i++)\\r
- if (--len >= 0)\\r
- text[len] = '.';\\r
- dots_made = 1;\\r
- }\\r
- }\r
-\r
- if (p)\r
- while (*p)\r
- if (*p == '$')\r
- {\r
- const byte *r = error_param;\r
-\r
- while (*r)\r
- {\r
- APPEND_CHARACTER(*r)\r
- r++;\r
- }\r
-\r
- p++;\r
- }\r
- else\r
- {\r
- APPEND_CHARACTER(*p)\r
- p++;\r
- }\r
-\r
- *pos = error_position;\r
-\r
-#undef APPEND_CHARACTER\r
-\r
-}\r
-\r
+/*
+ * 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 (¶m);
+ 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 (®bytes,
+ 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 (®bytes, 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
+
+}
+
-#ifndef GRAMMAR_H\r
-#define GRAMMAR_H\r
-\r
-\r
-#ifndef GRAMMAR_PORT_INCLUDE\r
-#error Do not include this file directly, include your grammar_XXX.h instead\r
-#endif\r
-\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-void grammar_alloc_free (void *);\r
-void *grammar_alloc_malloc (unsigned int);\r
-void *grammar_alloc_realloc (void *, unsigned int, unsigned int);\r
-void *grammar_memory_copy (void *, const void *, unsigned int);\r
-int grammar_string_compare (const byte *, const byte *);\r
-int grammar_string_compare_n (const byte *, const byte *, unsigned int);\r
-byte *grammar_string_copy (byte *, const byte *);\r
-byte *grammar_string_copy_n (byte *, const byte *, unsigned int);\r
-byte *grammar_string_duplicate (const byte *);\r
-unsigned int grammar_string_length (const byte *);\r
-\r
-/*\r
- loads grammar script from null-terminated ASCII <text>\r
- returns unique grammar id to grammar object\r
- returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text)\r
-*/\r
-grammar grammar_load_from_text (const byte *text);\r
-\r
-/*\r
- sets a new <value> to a register <name> for grammar <id>\r
- returns 0 on error (call grammar_get_last_error to retrieve the error text)\r
- returns 1 on success\r
-*/\r
-int grammar_set_reg8 (grammar id, const byte *name, byte value);\r
-\r
-/*\r
- checks if a null-terminated <text> matches given grammar <id>\r
- returns 0 on error (call grammar_get_last_error to retrieve the error text)\r
- returns 1 on success, the <prod> points to newly allocated buffer with production and <size>\r
- is filled with the production size\r
- call grammar_alloc_free to free the memory block pointed by <prod>\r
-*/\r
-int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size);\r
-\r
-/*\r
- destroys grammar object identified by <id>\r
- returns 0 on error (call grammar_get_last_error to retrieve the error text)\r
- returns 1 on success\r
-*/\r
-int grammar_destroy (grammar id);\r
-\r
-/*\r
- retrieves last grammar error reported either by grammar_load_from_text, grammar_check\r
- or grammar_destroy\r
- the user allocated <text> buffer receives error description, <pos> points to error position,\r
- <size> is the size of the text buffer to fill in - it must be at least 4 bytes long,\r
-*/\r
-void grammar_get_last_error (byte *text, unsigned int size, int *pos);\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif\r
-\r
+/*
+ * 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
+
-#include "grammar_mesa.h"\r
-\r
-#define GRAMMAR_PORT_BUILD 1\r
-#include "grammar.c"\r
-#undef GRAMMAR_PORT_BUILD\r
-\r
-\r
-void grammar_alloc_free (void *ptr)\r
-{\r
- _mesa_free (ptr);\r
-}\r
-\r
-void *grammar_alloc_malloc (unsigned int size)\r
-{\r
- return _mesa_malloc (size);\r
-}\r
-\r
-void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size)\r
-{\r
- return _mesa_realloc (ptr, old_size, size);\r
-}\r
-\r
-void *grammar_memory_copy (void *dst, const void * src, unsigned int size)\r
-{\r
- return _mesa_memcpy (dst, src, size);\r
-}\r
-\r
-int grammar_string_compare (const byte *str1, const byte *str2)\r
-{\r
- return _mesa_strcmp ((const char *) str1, (const char *) str2);\r
-}\r
-\r
-int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n)\r
-{\r
- return _mesa_strncmp ((const char *) str1, (const char *) str2, n);\r
-}\r
-\r
-byte *grammar_string_copy (byte *dst, const byte *src)\r
-{\r
- return (byte *) _mesa_strcpy ((char *) dst, (const char *) src);\r
-}\r
-\r
-byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n)\r
-{\r
- return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n);\r
-}\r
-\r
-byte *grammar_string_duplicate (const byte *src)\r
-{\r
- return (byte *) _mesa_strdup ((const char *) src);\r
-}\r
-\r
-unsigned int grammar_string_length (const byte *str)\r
-{\r
- return _mesa_strlen ((const char *) str);\r
-}\r
-\r
+/*
+ * 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);
+}
+
-#ifndef GRAMMAR_MESA_H\r
-#define GRAMMAR_MESA_H\r
-\r
-\r
-#include "imports.h"\r
-/* NOTE: include Mesa 3-D specific headers here */\r
-\r
-\r
-typedef GLuint grammar;\r
-typedef GLubyte byte;\r
-\r
-\r
-#define GRAMMAR_PORT_INCLUDE 1\r
-#include "grammar.h"\r
-#undef GRAMMAR_PORT_INCLUDE\r
-\r
-\r
-#endif\r
-\r
+/*
+ * 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
+
-".syntax grammar;\n"\r
-".emtcode DECLARATION_END 0x00\n"\r
-".emtcode DECLARATION_EMITCODE 0x01\n"\r
-".emtcode DECLARATION_ERRORTEXT 0x02\n"\r
-".emtcode DECLARATION_REGBYTE 0x03\n"\r
-".emtcode DECLARATION_LEXER 0x04\n"\r
-".emtcode DECLARATION_RULE 0x05\n"\r
-".emtcode SPECIFIER_END 0x00\n"\r
-".emtcode SPECIFIER_AND_TAG 0x01\n"\r
-".emtcode SPECIFIER_OR_TAG 0x02\n"\r
-".emtcode SPECIFIER_CHARACTER_RANGE 0x03\n"\r
-".emtcode SPECIFIER_CHARACTER 0x04\n"\r
-".emtcode SPECIFIER_STRING 0x05\n"\r
-".emtcode SPECIFIER_IDENTIFIER 0x06\n"\r
-".emtcode SPECIFIER_TRUE 0x07\n"\r
-".emtcode SPECIFIER_FALSE 0x08\n"\r
-".emtcode SPECIFIER_DEBUG 0x09\n"\r
-".emtcode IDENTIFIER_NO_LOOP 0x00\n"\r
-".emtcode IDENTIFIER_LOOP 0x01\n"\r
-".emtcode ERROR_NOT_PRESENT 0x00\n"\r
-".emtcode ERROR_PRESENT 0x01\n"\r
-".emtcode EMIT_NULL 0x00\n"\r
-".emtcode EMIT_INTEGER 0x01\n"\r
-".emtcode EMIT_IDENTIFIER 0x02\n"\r
-".emtcode EMIT_CHARACTER 0x03\n"\r
-".emtcode EMIT_LAST_CHARACTER 0x04\n"\r
-".emtcode EMIT_CURRENT_POSITION 0x05\n"\r
-".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n"\r
-".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n"\r
-".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n"\r
-".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n"\r
-".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n"\r
-".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n"\r
-"grammar\n"\r
-" grammar_1 .error INVALID_GRAMMAR;\n"\r
-"grammar_1\n"\r
-" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n"\r
-" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n"\r
-"optional_space\n"\r
-" space .or .true;\n"\r
-"space\n"\r
-" single_space .and .loop single_space;\n"\r
-"single_space\n"\r
-" white_char .or comment_block;\n"\r
-"white_char\n"\r
-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"\r
-"comment_block\n"\r
-" '/' .and '*' .and .loop comment_char .and '*' .and '/';\n"\r
-"comment_char\n"\r
-" comment_char_no_star .or comment_char_1;\n"\r
-"comment_char_1\n"\r
-" '*' .and comment_char_no_slash;\n"\r
-"comment_char_no_star\n"\r
-" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"\r
-"comment_char_no_slash\n"\r
-" '\\x30'-'\\xFF' .or '\\x01'-'\\x2E';\n"\r
-"identifier\n"\r
-" identifier_ne .error IDENTIFIER_EXPECTED;\n"\r
-"identifier_ne\n"\r
-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n"\r
-"first_idchar\n"\r
-" 'a'-'z' .or 'A'-'Z' .or '_';\n"\r
-"follow_idchar\n"\r
-" first_idchar .or digit_dec;\n"\r
-"digit_dec\n"\r
-" '0'-'9';\n"\r
-"semicolon\n"\r
-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"\r
-"declaration_list\n"\r
-" declaration .and .loop declaration;\n"\r
-"declaration\n"\r
-" emitcode_definition .emit DECLARATION_EMITCODE .or\n"\r
-" errortext_definition .emit DECLARATION_ERRORTEXT .or\n"\r
-" regbyte_definition .emit DECLARATION_REGBYTE .or\n"\r
-" lexer_definition .emit DECLARATION_LEXER .or\n"\r
-" rule_definition .emit DECLARATION_RULE;\n"\r
-"emitcode_definition\n"\r
-" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n"\r
-"integer\n"\r
-" integer_ne .error INTEGER_EXPECTED;\n"\r
-"integer_ne\n"\r
-" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n"\r
-"hex_prefix\n"\r
-" '0' .and hex_prefix_1;\n"\r
-"hex_prefix_1\n"\r
-" 'x' .or 'X';\n"\r
-"digit_hex\n"\r
-" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n"\r
-"space_or_null\n"\r
-" space .or '\\0';\n"\r
-"errortext_definition\n"\r
-" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n"\r
-"string\n"\r
-" string_ne .error STRING_EXPECTED;\n"\r
-"string_ne\n"\r
-" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n"\r
-"string_char_double_quotes\n"\r
-" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n"\r
-"string_char\n"\r
-" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n"\r
-" '\\x01'-'\\x09';\n"\r
-"escape_sequence\n"\r
-" '\\\\' .emit * .and escape_code;\n"\r
-"escape_code\n"\r
-" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n"\r
-"simple_escape_code\n"\r
-" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n"\r
-"hex_escape_code\n"\r
-" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n"\r
-"oct_escape_code\n"\r
-" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n"\r
-"digit_oct\n"\r
-" '0'-'7';\n"\r
-"optional_digit_oct\n"\r
-" digit_oct .emit * .or .true;\n"\r
-"regbyte_definition\n"\r
-" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n"\r
-"lexer_definition\n"\r
-" \".string\" .and space .and identifier .and semicolon;\n"\r
-"rule_definition\n"\r
-" identifier_ne .and space .and definition;\n"\r
-"definition\n"\r
-" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n"\r
-"optional_specifiers_and_or\n"\r
-" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n"\r
-"specifier\n"\r
-" specifier_condition .and optional_space .and specifier_rule;\n"\r
-"specifier_condition\n"\r
-" specifier_condition_1 .or .true;\n"\r
-"specifier_condition_1\n"\r
-" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n"\r
-" right_operand .and optional_space .and ')';\n"\r
-"left_operand\n"\r
-" identifier;\n"\r
-"operator\n"\r
-" operator_1 .or operator_2;\n"\r
-"operator_1\n"\r
-" optional_space .and '!' .and '=' .and optional_space;\n"\r
-"operator_2\n"\r
-" optional_space .and '=' .and '=' .and optional_space;\n"\r
-"right_operand\n"\r
-" integer;\n"\r
-"specifier_rule\n"\r
-" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n"\r
-"specifier_rule_1\n"\r
-" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n"\r
-" character .emit SPECIFIER_CHARACTER .or\n"\r
-" string_ne .emit SPECIFIER_STRING .or\n"\r
-" \".true\" .emit SPECIFIER_TRUE .or\n"\r
-" \".false\" .emit SPECIFIER_FALSE .or\n"\r
-" \".debug\" .emit SPECIFIER_DEBUG .or\n"\r
-" loop_identifier .emit SPECIFIER_IDENTIFIER;\n"\r
-"character\n"\r
-" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n"\r
-"string_char_single_quotes\n"\r
-" escape_sequence .or string_char .emit * .or '\"' .emit *;\n"\r
-"character_range\n"\r
-" character .and optional_space .and '-' .and optional_space .and character;\n"\r
-"loop_identifier\n"\r
-" optional_loop .and identifier;\n"\r
-"optional_loop\n"\r
-" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_NO_LOOP;\n"\r
-"optional_loop_1\n"\r
-" \".loop\" .and space;\n"\r
-"optional_error\n"\r
-" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n"\r
-"error\n"\r
-" space .and \".error\" .and space .and identifier;\n"\r
-"emit\n"\r
-" emit_output .or emit_regbyte;\n"\r
-"emit_output\n"\r
-" space .and \".emit\" .and space .and emit_param;\n"\r
-"emit_param\n"\r
-" integer_ne .emit EMIT_INTEGER .or\n"\r
-" identifier_ne .emit EMIT_IDENTIFIER .or\n"\r
-" character .emit EMIT_CHARACTER .or\n"\r
-" '*' .emit EMIT_LAST_CHARACTER .or\n"\r
-" '$' .emit EMIT_CURRENT_POSITION;\n"\r
-"emit_regbyte\n"\r
-" space .and \".load\" .and space .and identifier .and space .and emit_param;\n"\r
-"and_specifiers\n"\r
-" and_specifier .and .loop and_specifier;\n"\r
-"or_specifiers\n"\r
-" or_specifier .and .loop or_specifier;\n"\r
-"and_specifier\n"\r
-" space .and \".and\" .and space .and specifier;\n"\r
-"or_specifier\n"\r
-" space .and \".or\" .and space .and specifier;\n"\r
-".string __string_filter;\n"\r
-"__string_filter\n"\r
-" __first_identifier_char .and .loop __next_identifier_char;\n"\r
-"__first_identifier_char\n"\r
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n"\r
-"__next_identifier_char\n"\r
-" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"\r
-""
\ 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"
+""