Added missing Copyrights.
diff --git a/src/mesa/shader/arbprogram.syn b/src/mesa/shader/arbprogram.syn
index 0fc03e7..e6249ab 100644
--- a/src/mesa/shader/arbprogram.syn
+++ b/src/mesa/shader/arbprogram.syn
@@ -1,2725 +1,2725 @@
-.syntax program;

-

-/*

-   This value must be incremented every time emit code values or structure of the production

-   array changes. This value is placed at the beginning of the production array. The loader

-   compares the value with its REVISION value. If they do not match, the loader is not up

-   to date.

-*/

-.emtcode REVISION                                   0x07

-

-/* program type */

-.emtcode FRAGMENT_PROGRAM                           0x01

-.emtcode VERTEX_PROGRAM                             0x02

-

-/* program section */

-.emtcode OPTION                                     0x01

-.emtcode INSTRUCTION                                0x02

-.emtcode DECLARATION                                0x03

-.emtcode END                                        0x04

-

-/* GL_ARB_fragment_program option flags */

-.emtcode ARB_PRECISION_HINT_FASTEST                 0x01

-.emtcode ARB_PRECISION_HINT_NICEST                  0x02

-.emtcode ARB_FOG_EXP                                0x04

-.emtcode ARB_FOG_EXP2                               0x08

-.emtcode ARB_FOG_LINEAR                             0x10

-

-/* GL_ARB_vertex_program option flags */

-.emtcode ARB_POSITION_INVARIANT                     0x20

-

-/* GL_ARB_fragment_program_shadow option flags */

-.emtcode ARB_FRAGMENT_PROGRAM_SHADOW                0x40

-

-/* GL_ARB_fragment_program instruction class */

-.emtcode OP_ALU_INST                                0x00

-.emtcode OP_TEX_INST                                0x01

-

-/* GL_ARB_vertex_program instruction class */

-/*       OP_ALU_INST */

-

-/* GL_ARB_fragment_program instruction type */

-.emtcode OP_ALU_VECTOR                               0x00

-.emtcode OP_ALU_SCALAR                               0x01

-.emtcode OP_ALU_BINSC                                0x02

-.emtcode OP_ALU_BIN                                  0x03

-.emtcode OP_ALU_TRI                                  0x04

-.emtcode OP_ALU_SWZ                                  0x05

-.emtcode OP_TEX_SAMPLE                               0x06

-.emtcode OP_TEX_KIL                                  0x07

-

-/* GL_ARB_vertex_program instruction type */

-.emtcode OP_ALU_ARL                                  0x08

-/*       OP_ALU_VECTOR */

-/*       OP_ALU_SCALAR */

-/*       OP_ALU_BINSC */

-/*       OP_ALU_BIN */

-/*       OP_ALU_TRI */

-/*       OP_ALU_SWZ */

-

-/* GL_ARB_fragment_program instruction code */

-.emtcode OP_ABS                                     0x00

-.emtcode OP_ABS_SAT                                 0x1B

-.emtcode OP_FLR                                     0x09

-.emtcode OP_FLR_SAT                                 0x26

-.emtcode OP_FRC                                     0x0A

-.emtcode OP_FRC_SAT                                 0x27

-.emtcode OP_LIT                                     0x0C

-.emtcode OP_LIT_SAT                                 0x2A

-.emtcode OP_MOV                                     0x11

-.emtcode OP_MOV_SAT                                 0x30

-.emtcode OP_COS                                     0x1F

-.emtcode OP_COS_SAT                                 0x20

-.emtcode OP_EX2                                     0x07

-.emtcode OP_EX2_SAT                                 0x25

-.emtcode OP_LG2                                     0x0B

-.emtcode OP_LG2_SAT                                 0x29

-.emtcode OP_RCP                                     0x14

-.emtcode OP_RCP_SAT                                 0x33

-.emtcode OP_RSQ                                     0x15

-.emtcode OP_RSQ_SAT                                 0x34

-.emtcode OP_SIN                                     0x38

-.emtcode OP_SIN_SAT                                 0x39

-.emtcode OP_SCS                                     0x35

-.emtcode OP_SCS_SAT                                 0x36

-.emtcode OP_POW                                     0x13

-.emtcode OP_POW_SAT                                 0x32

-.emtcode OP_ADD                                     0x01

-.emtcode OP_ADD_SAT                                 0x1C

-.emtcode OP_DP3                                     0x03

-.emtcode OP_DP3_SAT                                 0x21

-.emtcode OP_DP4                                     0x04

-.emtcode OP_DP4_SAT                                 0x22

-.emtcode OP_DPH                                     0x05

-.emtcode OP_DPH_SAT                                 0x23

-.emtcode OP_DST                                     0x06

-.emtcode OP_DST_SAT                                 0x24

-.emtcode OP_MAX                                     0x0F

-.emtcode OP_MAX_SAT                                 0x2E

-.emtcode OP_MIN                                     0x10

-.emtcode OP_MIN_SAT                                 0x2F

-.emtcode OP_MUL                                     0x12

-.emtcode OP_MUL_SAT                                 0x31

-.emtcode OP_SGE                                     0x16

-.emtcode OP_SGE_SAT                                 0x37

-.emtcode OP_SLT                                     0x17

-.emtcode OP_SLT_SAT                                 0x3A

-.emtcode OP_SUB                                     0x18

-.emtcode OP_SUB_SAT                                 0x3B

-.emtcode OP_XPD                                     0x1A

-.emtcode OP_XPD_SAT                                 0x43

-.emtcode OP_CMP                                     0x1D

-.emtcode OP_CMP_SAT                                 0x1E

-.emtcode OP_LRP                                     0x2B

-.emtcode OP_LRP_SAT                                 0x2C

-.emtcode OP_MAD                                     0x0E

-.emtcode OP_MAD_SAT                                 0x2D

-.emtcode OP_SWZ                                     0x19

-.emtcode OP_SWZ_SAT                                 0x3C

-.emtcode OP_TEX                                     0x3D

-.emtcode OP_TEX_SAT                                 0x3E

-.emtcode OP_TXB                                     0x3F

-.emtcode OP_TXB_SAT                                 0x40

-.emtcode OP_TXP                                     0x41

-.emtcode OP_TXP_SAT                                 0x42

-.emtcode OP_KIL                                     0x28

-

-/* GL_ARB_vertex_program instruction code */

-.emtcode OP_ARL                                     0x02

-/*       OP_ABS */

-/*       OP_FLR */

-/*       OP_FRC */

-/*       OP_LIT */

-/*       OP_MOV */

-/*       OP_EX2 */

-.emtcode OP_EXP                                     0x08

-/*       OP_LG2 */

-.emtcode OP_LOG                                     0x0D

-/*       OP_RCP */

-/*       OP_RSQ */

-/*       OP_POW */

-/*       OP_ADD */

-/*       OP_DP3 */

-/*       OP_DP4 */

-/*       OP_DPH */

-/*       OP_DST */

-/*       OP_MAX */

-/*       OP_MIN */

-/*       OP_MUL */

-/*       OP_SGE */

-/*       OP_SLT */

-/*       OP_SUB */

-/*       OP_XPD */

-/*       OP_MAD */

-/*       OP_SWZ */

-

-/* fragment attribute binding */

-.emtcode FRAGMENT_ATTRIB_COLOR                      0x01

-.emtcode FRAGMENT_ATTRIB_TEXCOORD                   0x02

-.emtcode FRAGMENT_ATTRIB_FOGCOORD                   0x03

-.emtcode FRAGMENT_ATTRIB_POSITION                   0x04

-

-/* vertex attribute binding */

-.emtcode VERTEX_ATTRIB_POSITION                     0x01

-.emtcode VERTEX_ATTRIB_WEIGHT                       0x02

-.emtcode VERTEX_ATTRIB_NORMAL                       0x03

-.emtcode VERTEX_ATTRIB_COLOR                        0x04

-.emtcode VERTEX_ATTRIB_FOGCOORD                     0x05

-.emtcode VERTEX_ATTRIB_TEXCOORD                     0x06

-.emtcode VERTEX_ATTRIB_MATRIXINDEX                  0x07

-.emtcode VERTEX_ATTRIB_GENERIC                      0x08

-

-/* fragment result binding */

-.emtcode FRAGMENT_RESULT_COLOR                      0x01

-.emtcode FRAGMENT_RESULT_DEPTH                      0x02

-

-/* vertex result binding */

-.emtcode VERTEX_RESULT_POSITION                     0x01

-.emtcode VERTEX_RESULT_COLOR                        0x02

-.emtcode VERTEX_RESULT_FOGCOORD                     0x03

-.emtcode VERTEX_RESULT_POINTSIZE                    0x04

-.emtcode VERTEX_RESULT_TEXCOORD                     0x05

-

-/* texture target */

-.emtcode TEXTARGET_1D                               0x01

-.emtcode TEXTARGET_2D                               0x02

-.emtcode TEXTARGET_3D                               0x03

-.emtcode TEXTARGET_RECT                             0x04

-.emtcode TEXTARGET_CUBE                             0x05

-/* GL_ARB_fragment_program_shadow */

-.emtcode TEXTARGET_SHADOW1D                         0x06

-.emtcode TEXTARGET_SHADOW2D                         0x07

-.emtcode TEXTARGET_SHADOWRECT                       0x08

-

-/* face type */

-.emtcode FACE_FRONT                                 0x00

-.emtcode FACE_BACK                                  0x01

-

-/* color type */

-.emtcode COLOR_PRIMARY                              0x00

-.emtcode COLOR_SECONDARY                            0x01

-

-/* component */

-.emtcode COMPONENT_X                                0x00

-.emtcode COMPONENT_Y                                0x01

-.emtcode COMPONENT_Z                                0x02

-.emtcode COMPONENT_W                                0x03

-.emtcode COMPONENT_0                                0x04

-.emtcode COMPONENT_1                                0x05

-

-/* array index type */

-.emtcode ARRAY_INDEX_ABSOLUTE                       0x00

-.emtcode ARRAY_INDEX_RELATIVE                       0x01

-

-/* matrix name */

-.emtcode MATRIX_MODELVIEW                           0x01

-.emtcode MATRIX_PROJECTION                          0x02

-.emtcode MATRIX_MVP                                 0x03

-.emtcode MATRIX_TEXTURE                             0x04

-.emtcode MATRIX_PALETTE                             0x05

-.emtcode MATRIX_PROGRAM                             0x06

-

-/* matrix modifier */

-.emtcode MATRIX_MODIFIER_IDENTITY                   0x00

-.emtcode MATRIX_MODIFIER_INVERSE                    0x01

-.emtcode MATRIX_MODIFIER_TRANSPOSE                  0x02

-.emtcode MATRIX_MODIFIER_INVTRANS                   0x03

-

-/* constant type */

-.emtcode CONSTANT_SCALAR                            0x01

-.emtcode CONSTANT_VECTOR                            0x02

-

-/* program param type */

-.emtcode PROGRAM_PARAM_ENV                          0x01

-.emtcode PROGRAM_PARAM_LOCAL                        0x02

-

-/* register type */

-.emtcode REGISTER_ATTRIB                            0x01

-.emtcode REGISTER_PARAM                             0x02

-.emtcode REGISTER_RESULT                            0x03

-.emtcode REGISTER_ESTABLISHED_NAME                  0x04

-

-/* param binding */

-.emtcode PARAM_NULL                                 0x00

-.emtcode PARAM_ARRAY_ELEMENT                        0x01

-.emtcode PARAM_STATE_ELEMENT                        0x02

-.emtcode PARAM_PROGRAM_ELEMENT                      0x03

-.emtcode PARAM_PROGRAM_ELEMENTS                     0x04

-.emtcode PARAM_CONSTANT                             0x05

-

-/* param state property */

-.emtcode STATE_MATERIAL                             0x01

-.emtcode STATE_LIGHT                                0x02

-.emtcode STATE_LIGHT_MODEL                          0x03

-.emtcode STATE_LIGHT_PROD                           0x04

-.emtcode STATE_FOG                                  0x05

-.emtcode STATE_MATRIX_ROWS                          0x06

-/* GL_ARB_fragment_program */

-.emtcode STATE_TEX_ENV                              0x07

-.emtcode STATE_DEPTH                                0x08

-/* GL_ARB_vertex_program */

-.emtcode STATE_TEX_GEN                              0x09

-.emtcode STATE_CLIP_PLANE                           0x0A

-.emtcode STATE_POINT                                0x0B

-

-/* state material property */

-.emtcode MATERIAL_AMBIENT                           0x01

-.emtcode MATERIAL_DIFFUSE                           0x02

-.emtcode MATERIAL_SPECULAR                          0x03

-.emtcode MATERIAL_EMISSION                          0x04

-.emtcode MATERIAL_SHININESS                         0x05

-

-/* state light property */

-.emtcode LIGHT_AMBIENT                              0x01

-.emtcode LIGHT_DIFFUSE                              0x02

-.emtcode LIGHT_SPECULAR                             0x03

-.emtcode LIGHT_POSITION                             0x04

-.emtcode LIGHT_ATTENUATION                          0x05

-.emtcode LIGHT_HALF                                 0x06

-.emtcode LIGHT_SPOT_DIRECTION                       0x07

-

-/* state light model property */

-.emtcode LIGHT_MODEL_AMBIENT                        0x01

-.emtcode LIGHT_MODEL_SCENECOLOR                     0x02

-

-/* state light product property */

-.emtcode LIGHT_PROD_AMBIENT                         0x01

-.emtcode LIGHT_PROD_DIFFUSE                         0x02

-.emtcode LIGHT_PROD_SPECULAR                        0x03

-

-/* state texture environment property */

-.emtcode TEX_ENV_COLOR                              0x01

-

-/* state texture generation coord property */

-.emtcode TEX_GEN_EYE                                0x01

-.emtcode TEX_GEN_OBJECT                             0x02

-

-/* state fog property */

-.emtcode FOG_COLOR                                  0x01

-.emtcode FOG_PARAMS                                 0x02

-

-/* state depth property */

-.emtcode DEPTH_RANGE                                0x01

-

-/* state point parameters property */

-.emtcode POINT_SIZE                                 0x01

-.emtcode POINT_ATTENUATION                          0x02

-

-/* declaration */

-.emtcode ATTRIB                                     0x01

-.emtcode PARAM                                      0x02

-.emtcode TEMP                                       0x03

-.emtcode OUTPUT                                     0x04

-.emtcode ALIAS                                      0x05

-/* GL_ARB_vertex_program */

-.emtcode ADDRESS                                    0x06

-

-/* error messages */

-.errtext UNKNOWN_PROGRAM_SIGNATURE                  "1001: '$e_signature$': unknown program signature"

-.errtext MISSING_END_OR_INVALID_STATEMENT           "1002: '$e_statement$': invalid statement"

-.errtext CODE_AFTER_END                             "1003: '$e_statement$': code after 'END' keyword"

-.errtext INVALID_PROGRAM_OPTION                     "1004: '$e_identifier$': invalid program option"

-.errtext EXT_SWIZ_COMP_EXPECTED                     "1005: extended swizzle component expected but '$e_token$' found"

-.errtext TEX_TARGET_EXPECTED                        "1006: texture target expected but '$e_token$' found"

-.errtext TEXTURE_EXPECTED                           "1007: 'texture' expected but '$e_identifier$' found"

-.errtext SOURCE_REGISTER_EXPECTED                   "1008: source register expected but '$e_token$' found"

-.errtext DESTINATION_REGISTER_EXPECTED              "1009: destination register expected but '$e_token$' found"

-.errtext INVALID_ADDRESS_COMPONENT                  "1010: '$e_identifier$': invalid address component"

-.errtext INVALID_ADDRESS_WRITEMASK                  "1011: '$e_identifier$': invalid address writemask"

-.errtext INVALID_COMPONENT                          "1012: '$e_charordigit$': invalid component"

-.errtext INVALID_SUFFIX                             "1013: '$e_identifier$': invalid suffix"

-.errtext INVALID_WRITEMASK                          "1014: '$e_identifier$': invalid writemask"

-.errtext FRAGMENT_EXPECTED                          "1015: 'fragment' expected but '$e_identifier$' found"

-.errtext VERTEX_EXPECTED                            "1016: 'vertex' expected but '$e_identifier$' found"

-.errtext INVALID_FRAGMENT_PROPERTY                  "1017: '$e_identifier$': invalid fragment property"

-.errtext INVALID_VERTEX_PROPERTY                    "1018: '$e_identifier$': invalid vertex property"

-.errtext INVALID_STATE_PROPERTY                     "1019: '$e_identifier$': invalid state property"

-.errtext INVALID_MATERIAL_PROPERTY                  "1020: '$e_identifier$': invalid material property"

-.errtext INVALID_LIGHT_PROPERTY                     "1021: '$e_identifier$': invalid light property"

-.errtext INVALID_SPOT_PROPERTY                      "1022: '$e_identifier$': invalid spot property"

-.errtext INVALID_LIGHTMODEL_PROPERTY                "1023: '$e_identifier$': invalid light model property"

-.errtext INVALID_LIGHTPROD_PROPERTY                 "1024: '$e_identifier$': invalid light product property"

-.errtext INVALID_TEXENV_PROPERTY                    "1025: '$e_identifier$': invalid texture environment property"

-.errtext INVALID_TEXGEN_PROPERTY                    "1026: '$e_identifier$': invalid texture generating property"

-.errtext INVALID_TEXGEN_COORD                       "1027: '$e_identifier$': invalid texture generating coord"

-.errtext INVALID_FOG_PROPERTY                       "1028: '$e_identifier$': invalid fog property"

-.errtext INVALID_DEPTH_PROPERTY                     "1029: '$e_identifier$': invalid depth property"

-.errtext INVALID_CLIPPLANE_PROPERTY                 "1030: '$e_identifier$': invalid clip plane property"

-.errtext INVALID_POINT_PROPERTY                     "1031: '$e_identifier$': invalid point property"

-.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED   "1032: matrix row selector or modifier expected but '$e_token$' found"

-.errtext INVALID_MATRIX_NAME                        "1033: '$e_identifier$': invalid matrix name"

-.errtext INVALID_PROGRAM_PROPERTY                   "1034: '$e_identifier$': invalid program property"

-.errtext RESULT_EXPECTED                            "1035: 'result' expected but '$e_token$' found"

-.errtext INVALID_RESULT_PROPERTY                    "1036: '$e_identifier$': invalid result property"

-.errtext INVALID_FACE_PROPERTY                      "1037: '$e_identifier$': invalid face property"

-.errtext INVALID_COLOR_PROPERTY                     "1038: '$e_identifier$': invalid color property"

-.errtext IDENTIFIER_EXPECTED                        "1039: identifier expected but '$e_token$' found"

-.errtext RESERVED_KEYWORD                           "1040: use of reserved keyword as an identifier"

-.errtext INTEGER_EXPECTED                           "1041: integer value expected but '$e_token$' found"

-.errtext MISSING_SEMICOLON                          "1042: ';' expected but '$e_token$' found"

-.errtext MISSING_COMMA                              "1043: ',' expected but '$e_token$' found"

-.errtext MISSING_LBRACKET                           "1044: '[' expected but '$e_token$' found"

-.errtext MISSING_RBRACKET                           "1045: ']' expected but '$e_token$' found"

-.errtext MISSING_DOT                                "1046: '.' expected but '$e_token$' found"

-.errtext MISSING_EQUAL                              "1047: '=' expected but '$e_token$' found"

-.errtext MISSING_LBRACE                             "1048: '{' expected but '$e_token$' found"

-.errtext MISSING_RBRACE                             "1049: '}' expected but '$e_token$' found"

-.errtext MISSING_DOTDOT                             "1050: '..' expected but '$e_token$' found"

-.errtext MISSING_FRACTION_OR_EXPONENT               "1051: missing fraction part or exponent"

-.errtext MISSING_DOT_OR_EXPONENT                    "1052: missing '.' or exponent"

-.errtext EXPONENT_VALUE_EXPECTED                    "1053: exponent value expected"

-.errtext INTEGER_OUT_OF_RANGE                       "1054: integer value out of range"

-.errtext OPERATION_NEEDS_DESTINATION_VARIABLE       "1055: operation needs destination variable"

-.errtext OPERATION_NEEDS_SOURCE_VARIABLE            "1056: operation needs source variable"

-.errtext ADDRESS_REGISTER_EXPECTED                  "1057: address register expected but '$e_token$' found"

-.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED       "1058: address register or integer literal expected but '$e_token$' found"

-

-/* extension presence condition registers */

-

-/* GL_ARB_vertex_blend */

-/* GL_EXT_vertex_weighting */

-.regbyte vertex_blend                               0x00

-

-/* GL_ARB_matrix_palette */

-.regbyte matrix_palette                             0x00

-

-/* GL_ARB_point_parameters */

-/* GL_EXT_point_parameters */

-.regbyte point_parameters                           0x01

-

-/* GL_EXT_secondary_color */

-.regbyte secondary_color                            0x01

-

-/* GL_EXT_fog_coord */

-.regbyte fog_coord                                  0x01

-

-/* GL_EXT_texture_rectangle */

-/* GL_NV_texture_rectangle */

-.regbyte texture_rectangle                          0x01

-

-/* GL_ARB_fragment_program_shadow */

-.regbyte fragment_program_shadow                    0x00

-

-/* option presence condition registers */

-/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */

-/* register is set to 1 to indicate that the OPTION was specified. */

-

-/* GL_ARB_fragment_program */

-.regbyte ARB_precision_hint_fastest                 0x00

-.regbyte ARB_precision_hint_nicest                  0x00

-.regbyte ARB_fog_exp                                0x00

-.regbyte ARB_fog_exp2                               0x00

-.regbyte ARB_fog_linear                             0x00

-

-/* GL_ARB_vertex_program */

-.regbyte ARB_position_invariant                     0x00

-

-/* GL_ARB_fragment_program_shadow */

-.regbyte ARB_fragment_program_shadow                0x00

-

-/* program target condition register */

-/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */

-/* to distinguish between them we need a register that will store for us the current target. */

-/* the client will typically set the register to apropriate value before parsing a particular */

-/* program. the mapping between program targets and their values is listed below. */

-/* */

-/* program target               register value    */

-/* ---------------------------------------------- */

-/* FRAGMENT_PROGRAM             0x10              */

-/* VERTEX_PROGRAM               0x20              */

-/* */

-/* the initial value of the register is 0 to catch potential errors with not setting the register */

-/* with the proper value. */

-.regbyte program_target                             0x00

-

-/*

-    <program>              ::= <optionSequence> <statementSequence> "END"

-*/

-program

-    programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;

-programs

-    .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or

-    .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;

-frag_program_1_0

-    '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and

-    optional_space .and fp_optionSequence .and fp_statementSequence .and

-    "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and

-    '\0' .error CODE_AFTER_END;

-vert_program_1_0

-    '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and

-    optional_space .and vp_optionSequence .and vp_statementSequence .and

-    "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and

-    '\0' .error CODE_AFTER_END;

-

-/*

-    <optionSequence>       ::= <optionSequence> <option>

-                             | ""

-*/

-fp_optionSequence

-    .loop fp_option;

-vp_optionSequence

-    .loop vp_option;

-

-/*

-    <option>               ::= "OPTION" <identifier> ";"

-

-NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of

-      these options is encountered, the other one is automatically disabled.

-      the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear.

-*/

-fp_option

-    "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and

-    fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;

-vp_option

-    "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and

-    vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;

-fp_optionString

-    .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest"

-        .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or

-    .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest"

-        .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or

-    fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or

-    fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or

-    fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or

-    .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow"

-        .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;

-vp_optionString

-    "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;

-fp_ARB_fog_exp

-    .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp";

-fp_ARB_fog_exp2

-    .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2";

-fp_ARB_fog_linear

-    .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear";

-

-/*

-    <statementSequence>    ::= <statementSequence> <statement>

-                             | ""

-*/

-fp_statementSequence

-    .loop fp_statement;

-vp_statementSequence

-    .loop vp_statement;

-

-/*

-    <statement>            ::= <instruction> ";"

-                             | <namingStatement> ";"

-

-NOTE: ".emit $" in the definitions below means that we output instruction position (offset of

-      the first character of instruction) for program debugging purposes.

-*/

-fp_statement

-    fp_statement_1 .or fp_statement_2;

-vp_statement

-    vp_statement_1 .or vp_statement_2;

-fp_statement_1

-    fp_instruction .emit INSTRUCTION .emit $ .and semicolon;

-fp_statement_2

-    fp_namingStatement .emit DECLARATION .and semicolon;

-vp_statement_1

-    vp_instruction .emit INSTRUCTION .emit $ .and semicolon;

-vp_statement_2

-    vp_namingStatement .emit DECLARATION .and semicolon;

-

-/*

-fragment program

-    <instruction>          ::= <ALUInstruction>

-                             | <TexInstruction>

-

-vertex program

-    <instruction>          ::= <ARL_instruction>

-                             | <VECTORop_instruction>

-                             | <SCALARop_instruction>

-                             | <BINSCop_instruction>

-                             | <BINop_instruction>

-                             | <TRIop_instruction>

-                             | <SWZ_instruction>

-*/

-fp_instruction

-    ALUInstruction .emit OP_ALU_INST .or

-    TexInstruction .emit OP_TEX_INST;

-vp_instruction

-    ARL_instruction .emit OP_ALU_ARL .or

-    vp_VECTORop_instruction .emit OP_ALU_VECTOR .or

-    vp_SCALARop_instruction .emit OP_ALU_SCALAR .or

-    vp_BINSCop_instruction .emit OP_ALU_BINSC .or

-    vp_BINop_instruction .emit OP_ALU_BIN .or

-    vp_TRIop_instruction .emit OP_ALU_TRI .or

-    vp_SWZ_instruction .emit OP_ALU_SWZ;

-

-/*

-fragment program

-    <ALUInstruction>       ::= <VECTORop_instruction>

-                             | <SCALARop_instruction>

-                             | <BINSCop_instruction>

-                             | <BINop_instruction>

-                             | <TRIop_instruction>

-                             | <SWZ_instruction>

-*/

-ALUInstruction

-    fp_VECTORop_instruction .emit OP_ALU_VECTOR .or

-    fp_SCALARop_instruction .emit OP_ALU_SCALAR .or

-    fp_BINSCop_instruction .emit OP_ALU_BINSC .or

-    fp_BINop_instruction .emit OP_ALU_BIN .or

-    fp_TRIop_instruction .emit OP_ALU_TRI .or

-    fp_SWZ_instruction .emit OP_ALU_SWZ;

-

-/*

-fragment program

-    <TexInstruction>       ::= <SAMPLE_instruction>

-                             | <KIL_instruction>

-*/

-TexInstruction

-    SAMPLE_instruction .emit OP_TEX_SAMPLE .or

-    KIL_instruction .emit OP_TEX_KIL;

-

-/*

-vertex program

-    <ARL_instruction>      ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>

-*/

-ARL_instruction

-    "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;

-

-/*

-fragment program

-    <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," 

-                               <vectorSrcReg>

-

-vertex program

-    <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>

-*/

-fp_VECTORop_instruction

-    fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;

-vp_VECTORop_instruction

-    vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;

-

-/*

-fragment program

-    <VECTORop>             ::= "ABS" | "ABS_SAT"

-                             | "FLR" | "FLR_SAT"

-                             | "FRC" | "FRC_SAT"

-                             | "LIT" | "LIT_SAT"

-                             | "MOV" | "MOV_SAT"

-

-vertex program

-    <VECTORop>             ::= "ABS"

-                             | "FLR"

-                             | "FRC"

-                             | "LIT"

-                             | "MOV"

-*/

-fp_VECTORop

-    "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or

-    "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or

-    "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or

-    "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or

-    "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT;

-vp_VECTORop

-    "ABS" .emit OP_ABS .or

-    "FLR" .emit OP_FLR .or

-    "FRC" .emit OP_FRC .or

-    "LIT" .emit OP_LIT .or

-    "MOV" .emit OP_MOV;

-

-/*

-    <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>

-*/

-fp_SCALARop_instruction

-    fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;

-vp_SCALARop_instruction

-    vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;

-

-/*

-fragment program

-    <SCALARop>             ::= "COS" | "COS_SAT"

-                             | "EX2" | "EX2_SAT"

-                             | "LG2" | "LG2_SAT"

-                             | "RCP" | "RCP_SAT"

-                             | "RSQ" | "RSQ_SAT"

-                             | "SIN" | "SIN_SAT"

-                             | "SCS" | "SCS_SAT"

-

-vertex program

-    <SCALARop>             ::= "EX2"

-                             | "EXP"

-                             | "LG2"

-                             | "LOG"

-                             | "RCP"

-                             | "RSQ"

-*/

-fp_SCALARop

-    "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or

-    "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or

-    "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or

-    "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or

-    "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or

-    "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or

-    "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT;

-vp_SCALARop

-    "EX2" .emit OP_EX2 .or

-    "EXP" .emit OP_EXP .or

-    "LG2" .emit OP_LG2 .or

-    "LOG" .emit OP_LOG .or

-    "RCP" .emit OP_RCP .or

-    "RSQ" .emit OP_RSQ;

-

-/*

-    <BINSCop_instruction>  ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","

-                               <scalarSrcReg>

-*/

-fp_BINSCop_instruction

-    fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and

-    fp_scalarSrcReg;

-vp_BINSCop_instruction

-    vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and

-    vp_scalarSrcReg;

-

-/*

-fragment program

-    <BINSCop>              ::= "POW" | "POW_SAT"

-

-vertex program

-    <BINSCop>              ::= "POW"

-*/

-fp_BINSCop

-    "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT;

-vp_BINSCop

-    "POW" .emit OP_POW;

-

-/*

-fragment program

-    <BINop_instruction>    ::= <BINop> <maskedDstReg> ","

-                               <vectorSrcReg> "," <vectorSrcReg>

-

-vertex program

-    <BINop_instruction>    ::= <BINop> <maskedDstReg> ","

-                               <swizzleSrcReg> "," <swizzleSrcReg>

-*/

-fp_BINop_instruction

-    fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and

-    vectorSrcReg;

-vp_BINop_instruction

-    vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and

-    swizzleSrcReg;

-

-/*

-fragment program

-    <BINop>                ::= "ADD" | "ADD_SAT"

-                             | "DP3" | "DP3_SAT"

-                             | "DP4" | "DP4_SAT"

-                             | "DPH" | "DPH_SAT"

-                             | "DST" | "DST_SAT"

-                             | "MAX" | "MAX_SAT"

-                             | "MIN" | "MIN_SAT"

-                             | "MUL" | "MUL_SAT"

-                             | "SGE" | "SGE_SAT"

-                             | "SLT" | "SLT_SAT"

-                             | "SUB" | "SUB_SAT"

-                             | "XPD" | "XPD_SAT"

-

-vertex program

-    <BINop>                ::= "ADD"

-                             | "DP3"

-                             | "DP4"

-                             | "DPH"

-                             | "DST"

-                             | "MAX"

-                             | "MIN"

-                             | "MUL"

-                             | "SGE"

-                             | "SLT"

-                             | "SUB"

-                             | "XPD"

-*/

-fp_BINop

-    "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or

-    "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or

-    "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or

-    "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or

-    "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or

-    "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or

-    "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or

-    "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or

-    "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or

-    "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or

-    "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or

-    "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT;

-vp_BINop

-    "ADD" .emit OP_ADD .or

-    "DP3" .emit OP_DP3 .or

-    "DP4" .emit OP_DP4 .or

-    "DPH" .emit OP_DPH .or

-    "DST" .emit OP_DST .or

-    "MAX" .emit OP_MAX .or

-    "MIN" .emit OP_MIN .or

-    "MUL" .emit OP_MUL .or

-    "SGE" .emit OP_SGE .or

-    "SLT" .emit OP_SLT .or

-    "SUB" .emit OP_SUB .or

-    "XPD" .emit OP_XPD;

-

-/*

-fragment program

-    <TRIop_instruction>    ::= <TRIop> <maskedDstReg> ","

-                               <vectorSrcReg> "," <vectorSrcReg> ","

-                               <vectorSrcReg>

-

-vertex program

-    <TRIop_instruction>    ::= <TRIop> <maskedDstReg> ","

-                               <swizzleSrcReg> "," <swizzleSrcReg> ","

-                               <swizzleSrcReg>

-*/

-fp_TRIop_instruction

-    fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and

-    vectorSrcReg .and comma .and vectorSrcReg;

-vp_TRIop_instruction

-    vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and

-    swizzleSrcReg .and comma .and swizzleSrcReg;

-

-/*

-fragment program

-    <TRIop>                ::= "CMP" | "CMP_SAT"

-                             | "LRP" | "LRP_SAT"

-                             | "MAD" | "MAD_SAT"

-

-vertex program

-    <TRIop>                ::= "MAD"

-*/

-fp_TRIop

-    "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or

-    "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or

-    "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT;

-vp_TRIop

-    "MAD" .emit OP_MAD;

-

-/*

-fragment program

-    <SWZ_instruction>      ::= <SWZop> <maskedDstReg> "," 

-                               <srcReg> "," <extendedSwizzle>

-

-vertex program

-    <SWZ_instruction>      ::= "SWZ" <maskedDstReg> "," <srcReg> "," 

-                               <extendedSwizzle>

-*/

-fp_SWZ_instruction

-    SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and

-    fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;

-vp_SWZ_instruction

-    "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and

-    vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;

-

-/*

-fragment program

-    <SWZop>                ::= "SWZ" | "SWZ_SAT"

-*/

-SWZop

-    "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT;

-

-/*

-fragment program

-    <SAMPLE_instruction>   ::= <SAMPLEop> <maskedDstReg> ","

-                               <vectorSrcReg> "," <texImageUnit> "," 

-                               <texTarget>

-*/

-SAMPLE_instruction

-    SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and

-    texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;

-

-/*

-fragment program

-    <SAMPLEop>             ::= "TEX" | "TEX_SAT"

-                             | "TXP" | "TXP_SAT"

-                             | "TXB" | "TXB_SAT"

-*/

-SAMPLEop

-    "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or

-    "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or

-    "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT;

-

-/*

-fragment program

-    <KIL_instruction>      ::= "KIL" <vectorSrcReg>

-*/

-KIL_instruction

-    "KIL" .emit OP_KIL .and space_src .and vectorSrcReg;

-

-/*

-fragment program

-    <texImageUnit>         ::= "texture" <optTexImageUnitNum>

-*/

-texImageUnit

-    "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum;

-

-/*

-fragment program

-    <texTarget>            ::= "1D"

-                             | "2D"

-                             | "3D"

-                             | "CUBE"

-                             | "RECT"

-                             | <shadowTarget> (if option ARB_fragment_program_shadow present)

-*/

-texTarget

-    "1D" .emit TEXTARGET_1D .or

-    "2D" .emit TEXTARGET_2D .or

-    "3D" .emit TEXTARGET_3D .or

-    .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or

-    "CUBE" .emit TEXTARGET_CUBE .or

-    .if (ARB_fragment_program_shadow != 0x00) shadowTarget;

-

-/*

-GL_ARB_fragment_program_shadow

-    <shadowTarget>         ::= "SHADOW1D"

-                             | "SHADOW2D"

-                             | "SHADOWRECT"

-*/

-shadowTarget

-    "SHADOW1D" .emit TEXTARGET_SHADOW1D .or

-    "SHADOW2D" .emit TEXTARGET_SHADOW2D .or

-    .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT;

-

-/*

-fragment program

-    <optTexImageUnitNum>   ::= ""

-                             | "[" <texImageUnitNum> "]"

-*/

-optTexImageUnitNum

-    optTexImageUnitNum_1 .or .true .emit 0x00;

-optTexImageUnitNum_1

-    lbracket_ne .and texImageUnitNum .and rbracket;

-

-/*

-fragment program

-    <texImageUnitNum>      ::= <integer> from 0 to 

-                               MAX_TEXTURE_IMAGE_UNITS_ARB-1

-*/

-texImageUnitNum

-    integer;

-

-/*

-    <scalarSrcReg>         ::= <optionalSign> <srcReg> <scalarSuffix>

-*/

-fp_scalarSrcReg

-    optionalSign .and fp_srcReg .and fp_scalarSuffix;

-vp_scalarSrcReg

-    optionalSign .and vp_srcReg .and vp_scalarSuffix;

-

-/*

-vertex program

-    <swizzleSrcReg>        ::= <optionalSign> <srcReg> <swizzleSuffix>

-*/

-swizzleSrcReg

-    optionalSign .and vp_srcReg .and swizzleSuffix;

-

-/*

-fragment program

-    <vectorSrcReg>         ::= <optionalSign> <srcReg> <optionalSuffix> 

-*/

-vectorSrcReg

-    optionalSign .and fp_srcReg .and optionalSuffix;

-

-/*

-    <maskedDstReg>         ::= <dstReg> <optionalMask>

-*/

-fp_maskedDstReg

-    fp_dstReg .and fp_optionalMask;

-vp_maskedDstReg

-    vp_dstReg .and vp_optionalMask;

-

-/*

-vertex program

-    <maskedAddrReg>        ::= <addrReg> <addrWriteMask>

-*/

-maskedAddrReg

-    addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;

-

-/*

-fragment program

-    <extendedSwizzle>      ::= <xyzwExtendedSwizzle>

-                             | <rgbaExtendedSwizzle>

-

-vertex program

-    <extendedSwizzle>      ::= <extSwizComp> "," <extSwizComp> "," 

-                                 <extSwizComp> "," <extSwizComp>

-

-NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez

-*/

-fp_extendedSwizzle

-    rgbaExtendedSwizzle .or xyzwExtendedSwizzle;

-vp_extendedSwizzle

-    extSwizComp .and comma .and

-    extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    extSwizComp .error EXT_SWIZ_COMP_EXPECTED;

-

-/*

-fragment program

-    <xyzwExtendedSwizzle>  ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> "," 

-                               <xyzwExtSwizComp> "," <xyzwExtSwizComp>

-*/

-xyzwExtendedSwizzle

-    xyzwExtSwizComp .and comma .and

-    xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;

-

-/*

-fragment program

-    <rgbaExtendedSwizzle>  ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> "," 

-                               <rgbaExtSwizComp> "," <rgbaExtSwizComp>

-*/

-rgbaExtendedSwizzle

-    rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or

-    rgbaExtendedSwizzle_4;

-rgbaExtendedSwizzle_1

-    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and

-    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;

-rgbaExtendedSwizzle_2

-    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and

-    rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;

-rgbaExtendedSwizzle_3

-    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and

-    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;

-rgbaExtendedSwizzle_4

-    rgbaExtSwizComp_alpha .and comma .and 

-    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and

-    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;

-

-/*

-fragment program

-    <xyzwExtSwizComp>      ::= <optionalSign> <xyzwExtSwizSel>

-*/

-xyzwExtSwizComp

-    optionalSign .and xyzwExtSwizSel;

-

-/*

-fragment program

-    <rgbaExtSwizComp>      ::= <optionalSign> <rgbaExtSwizSel>

-*/

-rgbaExtSwizComp

-    optionalSign .and rgbaExtSwizSel;

-rgbaExtSwizComp_digit

-    optionalSign .and rgbaExtSwizSel_digit;

-rgbaExtSwizComp_alpha

-    optionalSign .and rgbaExtSwizSel_alpha;

-

-/*

-vertex program

-    <extSwizComp>          ::= <optionalSign> <extSwizSel>

-*/

-extSwizComp

-    optionalSign .and extSwizSel;

-

-/*

-fragment program

-    <xyzwExtSwizSel>       ::= "0" 

-                             | "1" 

-                             | <xyzwComponent>

-*/

-xyzwExtSwizSel

-    "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single;

-

-/*

-fragment program

-    <rgbaExtSwizSel>       ::= "0" 

-                             | "1" 

-                             | <rgbaComponent>

-*/

-rgbaExtSwizSel

-    rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;

-rgbaExtSwizSel_digit

-    "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1;

-rgbaExtSwizSel_alpha

-    rgbaComponent_single;

-

-/*

-vertex program

-    <extSwizSel>           ::= "0" 

-                             | "1" 

-                             | <component>

-*/

-extSwizSel

-    "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single;

-

-/*

-fragment program

-    <srcReg>               ::= <fragmentAttribReg>

-                             | <temporaryReg>

-                             | <progParamReg>

-

-vertex program

-    <srcReg>               ::= <vertexAttribReg>

-                             | <temporaryReg>

-                             | <progParamReg>

-*/

-fp_srcReg

-    fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;

-vp_srcReg

-    vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;

-fp_srcReg_1

-    fragmentAttribReg .emit REGISTER_ATTRIB .or

-    fp_progParamReg .emit REGISTER_PARAM .or

-    fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;

-vp_srcReg_1

-    vertexAttribReg .emit REGISTER_ATTRIB .or

-    vp_progParamReg .emit REGISTER_PARAM .or

-    vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;

-

-/*

-fragment program

-    <dstReg>               ::= <temporaryReg>

-                             | <fragmentResultReg>

-

-vertex program

-    <dstReg>               ::= <temporaryReg>

-                             | <vertexResultReg>

-*/

-fp_dstReg

-    fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;

-vp_dstReg

-    vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;

-fp_dstReg_1

-    fragmentResultReg .emit REGISTER_RESULT .or

-    fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;

-vp_dstReg_1

-    vertexResultReg .emit REGISTER_RESULT .or

-    vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;

-

-/*

-fragment program

-    <fragmentAttribReg>    ::= <establishedName>

-                             | <fragAttribBinding>

-

-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>

-*/

-fragmentAttribReg

-    /*fp_establishedName .or */fragAttribBinding;

-

-/*

-vertex program

-    <vertexAttribReg>      ::= <establishedName>

-                             | <vtxAttribBinding>

-

-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>

-*/

-vertexAttribReg

-    vtxAttribBinding;

-

-/*

-    <temporaryReg>         ::= <establishedName>

-*/

-fp_temporaryReg

-    fp_establishedName_no_error_on_identifier;

-vp_temporaryReg

-    vp_establishedName_no_error_on_identifier;

-

-/*

-fragment program

-    <progParamReg>         ::= <progParamSingle>

-                             | <progParamArray> "[" <progParamArrayAbs> "]"

-                             | <paramSingleItemUse>

-

-vertex program

-    <progParamReg>         ::= <progParamSingle>

-                             | <progParamArray> "[" <progParamArrayMem> "]"

-                             | <paramSingleItemUse>

-*/

-fp_progParamReg

-    fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;

-vp_progParamReg

-    vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;

-fp_progParamReg_1

-    fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and

-    rbracket;

-vp_progParamReg_1

-    vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and

-    rbracket;

-

-/*

-    <progParamSingle>      ::= <establishedName>

-

-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>

-*/

-fp_progParamSingle

-    .false;

-vp_progParamSingle

-    .false;

-

-/*

-    <progParamArray>       ::= <establishedName>

-*/

-fp_progParamArray

-    fp_establishedName_no_error_on_identifier;

-vp_progParamArray

-    vp_establishedName_no_error_on_identifier;

-

-/*

-vertex program

-    <progParamArrayMem>    ::= <progParamArrayAbs>

-                             | <progParamArrayRel>

-*/

-progParamArrayMem

-    progParamArrayAbs .or progParamArrayRel;

-

-/*

-    <progParamArrayAbs>    ::= <integer>

-*/

-progParamArrayAbs

-    integer_ne .emit ARRAY_INDEX_ABSOLUTE;

-

-/*

-vertex program

-    <progParamArrayRel>    ::= <addrReg> <addrComponent> <addrRegRelOffset>

-*/

-progParamArrayRel

-    addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and

-    addrComponent .and addrRegRelOffset;

-

-/*

-vertex program

-    <addrRegRelOffset>     ::= ""

-                             | "+" <addrRegPosOffset>

-                             | "-" <addrRegNegOffset>

-*/

-addrRegRelOffset

-    addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;

-addrRegRelOffset_1

-    plus_ne .and addrRegPosOffset;

-addrRegRelOffset_2

-    minus_ne .and addrRegNegOffset;

-

-/*

-vertex program

-    <addrRegPosOffset>     ::= <integer> from 0 to 63

-*/

-addrRegPosOffset

-    integer_0_63;

-

-/*

-vertex program

-    <addrRegNegOffset>     ::= <integer> from 0 to 64

-*/

-addrRegNegOffset

-    integer_0_64;

-

-/*

-fragment program

-    <fragmentResultReg>    ::= <establishedName>

-                             | <resultBinding>

-

-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>

-*/

-fragmentResultReg

-    fp_resultBinding;

-

-/*

-vertex program

-    <vertexResultReg>      ::= <establishedName>

-                             | <resultBinding>

-

-NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>

-*/

-vertexResultReg

-    vp_resultBinding;

-

-/*

-vertex program

-    <addrReg>              ::= <establishedName>

-*/

-addrReg

-    vp_establishedName_no_error_on_identifier;

-

-/*

-vertex program

-    <addrComponent>        ::= "." "x"

-*/

-addrComponent

-    dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X

-    .emit COMPONENT_X .emit COMPONENT_X;

-

-/*

-vertex program

-    <addrWriteMask>        ::= "." "x"

-*/

-addrWriteMask

-    dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;

-

-/*

-    <scalarSuffix>         ::= "." <component>

-*/

-fp_scalarSuffix

-    dot .and fp_component_single .error INVALID_COMPONENT;

-vp_scalarSuffix

-    dot .and vp_component_single .error INVALID_COMPONENT;

-

-/*

-vertex program

-    <swizzleSuffix>        ::= ""

-                             | "." <component>

-                             | "." <component> <component>

-                                   <component> <component>

-*/

-swizzleSuffix

-    swizzleSuffix_1 .or

-    .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;

-swizzleSuffix_1

-    dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;

-swizzleSuffix_2

-    swizzleSuffix_3 .or swizzleSuffix_4;

-swizzleSuffix_3

-    vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and

-    vp_component_multi .error INVALID_COMPONENT;

-swizzleSuffix_4

-    "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or

-    "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or

-    "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or

-    "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;

-

-/*

-fragment program

-    <optionalSuffix>       ::= "" 

-                             | "." <component> 

-                             | "." <xyzwComponent> <xyzwComponent>

-                                   <xyzwComponent> <xyzwComponent>

-                             | "." <rgbaComponent> <rgbaComponent>

-                                   <rgbaComponent> <rgbaComponent>

-*/

-optionalSuffix

-    optionalSuffix_1 .or

-    .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;

-optionalSuffix_1

-    dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;

-optionalSuffix_2

-    optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;

-optionalSuffix_3

-    xyzwComponent_multi .and xyzwComponent_multi .and

-    xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;

-optionalSuffix_4

-    rgbaComponent_multi .and rgbaComponent_multi .and

-    rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;

-optionalSuffix_5

-    "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or

-    "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or

-    "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or

-    "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or

-    "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or

-    "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or

-    "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or

-    "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;

-

-/*

-fragment program

-    <component>            ::= <xyzwComponent>

-                             | <rgbaComponent>

-

-vertex program

-    <component>            ::= "x"

-                             | "y"

-                             | "z"

-                             | "w"

-*/

-fp_component_single

-    xyzwComponent_single .or rgbaComponent_single;

-vp_component_multi

-    'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or

-    'w' .emit COMPONENT_W;

-vp_component_single

-    "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or

-    "w" .emit COMPONENT_W;

-

-/*

-fragment program

-    <xyzwComponent>        ::= "x" | "y" | "z" | "w"

-*/

-xyzwComponent_multi

-    'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or

-    'w' .emit COMPONENT_W;

-xyzwComponent_single

-    "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or

-    "w" .emit COMPONENT_W;

-

-/*

-fragment program

-    <rgbaComponent>        ::= "r" | "g" | "b" | "a"

-*/

-rgbaComponent_multi

-    'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or

-    'a' .emit COMPONENT_W;

-rgbaComponent_single

-    "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or

-    "a" .emit COMPONENT_W;

-

-/*

-fragment program

-    <optionalMask>         ::= ""

-                             | <xyzwMask>

-                             | <rgbaMask>

-

-vertex program

-    <optionalMask>         ::= ""

-                             | "." "x"

-                             | "." "y"

-                             | "." "xy"

-                             | "." "z"

-                             | "." "xz"

-                             | "." "yz"

-                             | "." "xyz"

-                             | "." "w"

-                             | "." "xw"

-                             | "." "yw"

-                             | "." "xyw"

-                             | "." "zw"

-                             | "." "xzw"

-                             | "." "yzw"

-                             | "." "xyzw"

-

-NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez

-*/

-fp_optionalMask

-    rgbaMask .or xyzwMask .or .true .emit 0x0F;

-vp_optionalMask

-    xyzwMask .or .true .emit 0x0F;

-

-/*

-fragment program

-    <xyzwMask>             ::= "." "x"

-                             | "." "y"

-                             | "." "xy"

-                             | "." "z"

-                             | "." "xz"

-                             | "." "yz"

-                             | "." "xyz"

-                             | "." "w"

-                             | "." "xw"

-                             | "." "yw"

-                             | "." "xyw"

-                             | "." "zw"

-                             | "." "xzw"

-                             | "." "yzw"

-                             | "." "xyzw"

-

-NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>.

-*/

-xyzwMask

-    dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;

-xyzwMask_1

-    "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or

-    "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or

-    "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or

-    "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01;

-

-/*

-fragment program

-    <rgbaMask>             ::= "." "r"

-                             | "." "g"

-                             | "." "rg"

-                             | "." "b"

-                             | "." "rb"

-                             | "." "gb"

-                             | "." "rgb"

-                             | "." "a"

-                             | "." "ra"

-                             | "." "ga"

-                             | "." "rga"

-                             | "." "ba"

-                             | "." "rba"

-                             | "." "gba"

-                             | "." "rgba"

-*/

-rgbaMask

-    dot_ne .and rgbaMask_1;

-rgbaMask_1

-    "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or

-    "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or

-    "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or

-    "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01;

-

-/*

-fragment program

-    <namingStatement>      ::= <ATTRIB_statement>

-                             | <PARAM_statement>

-                             | <TEMP_statement>

-                             | <OUTPUT_statement>

-                             | <ALIAS_statement>

-

-vertex program

-    <namingStatement>      ::= <ATTRIB_statement>

-                             | <PARAM_statement>

-                             | <TEMP_statement>

-                             | <ADDRESS_statement>

-                             | <OUTPUT_statement>

-                             | <ALIAS_statement>

-*/

-fp_namingStatement

-    fp_ATTRIB_statement .emit ATTRIB .or

-    fp_PARAM_statement .emit PARAM .or

-    fp_TEMP_statement .emit TEMP .or

-    fp_OUTPUT_statement .emit OUTPUT .or

-    fp_ALIAS_statement .emit ALIAS;

-vp_namingStatement

-    vp_ATTRIB_statement .emit ATTRIB .or

-    vp_PARAM_statement .emit PARAM .or

-    vp_TEMP_statement .emit TEMP .or

-    ADDRESS_statement .emit ADDRESS .or

-    vp_OUTPUT_statement .emit OUTPUT .or

-    vp_ALIAS_statement .emit ALIAS;

-

-/*

-fragment program

-    <ATTRIB_statement>     ::= "ATTRIB" <establishName> "="

-                                 <fragAttribBinding>

-

-vertex program

-    <ATTRIB_statement>     ::= "ATTRIB" <establishName> "="

-                                 <vtxAttribBinding>

-*/

-fp_ATTRIB_statement

-    "ATTRIB" .and space .and fp_establishName .and equal .and

-    fragAttribBinding .error FRAGMENT_EXPECTED;

-vp_ATTRIB_statement

-    "ATTRIB" .and space .and vp_establishName .and equal .and

-    vtxAttribBinding .error VERTEX_EXPECTED;

-

-/*

-fragment program

-    <fragAttribBinding>    ::= "fragment" "." <fragAttribItem>

-*/

-fragAttribBinding

-    "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;

-

-/*

-vertex program

-    <vtxAttribBinding>     ::= "vertex" "." <vtxAttribItem>

-*/

-vtxAttribBinding

-    "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;

-

-/*

-fragment program

-    <fragAttribItem>       ::= "color" <optColorType>

-                             | "texcoord" <optTexCoordNum>

-                             | "fogcoord"

-                             | "position"

-*/

-fragAttribItem

-    fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or

-    fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or

-    .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or

-    "position" .emit FRAGMENT_ATTRIB_POSITION;

-fragAttribItem_1

-    "color" .and optColorType;

-fragAttribItem_2

-    "texcoord" .and optTexCoordNum;

-

-/*

-vertex program

-    <vtxAttribItem>        ::= "position"

-                             | "weight" <vtxOptWeightNum>

-                             | "normal"

-                             | "color" <optColorType>

-                             | "fogcoord"

-                             | "texcoord" <optTexCoordNum>

-                             | "matrixindex" "[" <vtxWeightNum> "]"

-                             | "attrib" "[" <vtxAttribNum> "]"

-*/

-vtxAttribItem

-    "position" .emit VERTEX_ATTRIB_POSITION .or

-    .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or

-    "normal" .emit VERTEX_ATTRIB_NORMAL .or

-    vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or

-    "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or

-    vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or

-    .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or

-    vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;

-vtxAttribItem_1

-    "weight" .and vtxOptWeightNum;

-vtxAttribItem_2

-    "color" .and optColorType;

-vtxAttribItem_3

-    "texcoord" .and optTexCoordNum;

-vtxAttribItem_4

-    "matrixindex" .and lbracket .and vtxWeightNum .and rbracket;

-vtxAttribItem_5

-    "attrib" .and lbracket .and vtxAttribNum .and rbracket;

-

-/*

-vertex program

-    <vtxAttribNum>         ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1

-*/

-vtxAttribNum

-    integer;

-

-/*

-vertex program

-    <vtxOptWeightNum>      ::= ""

-                             | "[" <vtxWeightNum> "]"

-*/

-vtxOptWeightNum

-    vtxOptWeightNum_1 .or .true .emit 0x00;

-vtxOptWeightNum_1

-    lbracket_ne .and vtxWeightNum .and rbracket;

-

-/*

-vertex program

-    <vtxWeightNum>         ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,

-                                 must be divisible by four

-*/

-vtxWeightNum

-    integer;

-

-/*

-    <PARAM_statement>      ::= <PARAM_singleStmt>

-                             | <PARAM_multipleStmt>

-*/

-fp_PARAM_statement

-    fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;

-vp_PARAM_statement

-    vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;

-

-/*

-    <PARAM_singleStmt>     ::= "PARAM" <establishName> <paramSingleInit>

-*/

-fp_PARAM_singleStmt

-    "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and

-    .true .emit PARAM_NULL;

-vp_PARAM_singleStmt

-    "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and

-    .true .emit PARAM_NULL;

-

-/*

-    <PARAM_multipleStmt>   ::= "PARAM" <establishName> "[" <optArraySize> "]"

-                                   <paramMultipleInit>

-*/

-fp_PARAM_multipleStmt

-    "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and

-    fp_paramMultipleInit .and .true .emit PARAM_NULL;

-vp_PARAM_multipleStmt

-    "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and

-    vp_paramMultipleInit .and .true .emit PARAM_NULL;

-

-/*

-    <optArraySize>         ::= ""

-                             | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB

-                                 (maximum number of allowed program 

-                                  parameter bindings)

-*/

-optArraySize

-    optional_integer;

-

-/*

-    <paramSingleInit>      ::= "=" <paramSingleItemDecl>

-*/

-fp_paramSingleInit

-    equal .and fp_paramSingleItemDecl;

-vp_paramSingleInit

-    equal .and vp_paramSingleItemDecl;

-

-/*

-    <paramMultipleInit>    ::= "=" "{" <paramMultInitList> "}"

-*/

-fp_paramMultipleInit

-    equal .and lbrace .and fp_paramMultInitList .and rbrace;

-vp_paramMultipleInit

-    equal .and lbrace .and vp_paramMultInitList .and rbrace;

-

-/*

-    <paramMultInitList>    ::= <paramMultipleItem>

-                             | <paramMultipleItem> "," <paramMultiInitList>

-*/

-fp_paramMultInitList

-    fp_paramMultInitList_1 .or fp_paramMultipleItem;

-vp_paramMultInitList

-    vp_paramMultInitList_1 .or vp_paramMultipleItem;

-fp_paramMultInitList_1

-    fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;

-vp_paramMultInitList_1

-    vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;

-

-/*

-    <paramSingleItemDecl>  ::= <stateSingleItem>

-                             | <programSingleItem>

-                             | <paramConstDecl>

-*/

-fp_paramSingleItemDecl

-    fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or

-    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or

-    paramConstDecl .emit PARAM_CONSTANT;

-vp_paramSingleItemDecl

-    vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or

-    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or

-    paramConstDecl .emit PARAM_CONSTANT;

-

-/*

-    <paramSingleItemUse>   ::= <stateSingleItem>

-                             | <programSingleItem>

-                             | <paramConstUse>

-*/

-fp_paramSingleItemUse

-    fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or

-    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or

-    paramConstUse .emit PARAM_CONSTANT;

-vp_paramSingleItemUse

-    vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or

-    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or

-    paramConstUse .emit PARAM_CONSTANT;

-

-/*

-    <paramMultipleItem>    ::= <stateMultipleItem>

-                             | <programMultipleItem>

-                             | <paramConstDecl>

-*/

-fp_paramMultipleItem

-    fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or

-    programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or

-    paramConstDecl .emit PARAM_CONSTANT;

-vp_paramMultipleItem

-    vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or

-    programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or

-    paramConstDecl .emit PARAM_CONSTANT;

-

-/*

-    <stateMultipleItem>    ::= <stateSingleItem>

-                             | "state" "." <stateMatrixRows>

-*/

-fp_stateMultipleItem

-    stateMultipleItem_1 .or fp_stateSingleItem;

-vp_stateMultipleItem

-    stateMultipleItem_1 .or vp_stateSingleItem;

-stateMultipleItem_1

-    "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;

-

-/*

-fragment program

-    <stateSingleItem>      ::= "state" "." <stateMaterialItem>

-                             | "state" "." <stateLightItem>

-                             | "state" "." <stateLightModelItem>

-                             | "state" "." <stateLightProdItem>

-                             | "state" "." <stateTexEnvItem>

-                             | "state" "." <stateFogItem>

-                             | "state" "." <stateDepthItem>

-                             | "state" "." <stateMatrixRow>

-

-vertex program

-    <stateSingleItem>      ::= "state" "." <stateMaterialItem>

-                             | "state" "." <stateLightItem>

-                             | "state" "." <stateLightModelItem>

-                             | "state" "." <stateLightProdItem>

-                             | "state" "." <stateTexGenItem>

-                             | "state" "." <stateFogItem>

-                             | "state" "." <stateClipPlaneItem>

-                             | "state" "." <statePointItem>

-                             | "state" "." <stateMatrixRow>

-*/

-fp_stateSingleItem

-    "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;

-vp_stateSingleItem

-    "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;

-fp_stateSingleItem_1

-    stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or

-    stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;

-vp_stateSingleItem_1

-    stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or

-    stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or

-    stateSingleItem_11;

-stateSingleItem_1

-    stateMaterialItem .emit STATE_MATERIAL;

-stateSingleItem_2

-    stateLightItem .emit STATE_LIGHT;

-stateSingleItem_3

-    stateLightModelItem .emit STATE_LIGHT_MODEL;

-stateSingleItem_4

-    stateLightProdItem .emit STATE_LIGHT_PROD;

-stateSingleItem_5

-    stateTexEnvItem .emit STATE_TEX_ENV;

-stateSingleItem_6

-    stateTexGenItem .emit STATE_TEX_GEN;

-stateSingleItem_7

-    stateFogItem .emit STATE_FOG;

-stateSingleItem_8

-    stateDepthItem .emit STATE_DEPTH;

-stateSingleItem_9

-    stateClipPlaneItem .emit STATE_CLIP_PLANE;

-stateSingleItem_10

-    statePointItem .emit STATE_POINT;

-stateSingleItem_11

-    stateMatrixRow .emit STATE_MATRIX_ROWS;

-

-/*

-    <stateMaterialItem>    ::= "material" <optFaceType> "." <stateMatProperty>

-*/

-stateMaterialItem

-    "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;

-

-/*

-    <stateMatProperty>     ::= "ambient"

-                             | "diffuse"

-                             | "specular"

-                             | "emission"

-                             | "shininess"

-*/

-stateMatProperty

-    "ambient" .emit MATERIAL_AMBIENT .or

-    "diffuse" .emit MATERIAL_DIFFUSE .or

-    "specular" .emit MATERIAL_SPECULAR .or

-    "emission" .emit MATERIAL_EMISSION .or

-    "shininess" .emit MATERIAL_SHININESS;

-

-/*

-    <stateLightItem>       ::= "light" "[" <stateLightNumber> "]" "." 

-                                 <stateLightProperty>

-*/

-stateLightItem

-    "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and

-    stateLightProperty .error INVALID_LIGHT_PROPERTY;

-

-/*

-    <stateLightProperty>   ::= "ambient"

-                             | "diffuse" 

-                             | "specular"

-                             | "position"

-                             | "attenuation"

-                             | "spot" "." <stateSpotProperty>

-                             | "half"

-*/

-stateLightProperty

-    "ambient" .emit LIGHT_AMBIENT .or

-    "diffuse" .emit LIGHT_DIFFUSE .or

-    "specular" .emit LIGHT_SPECULAR .or

-    "position" .emit LIGHT_POSITION .or

-    "attenuation" .emit LIGHT_ATTENUATION .or

-    stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or

-    "half" .emit LIGHT_HALF;

-stateLightProperty_1

-    "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;

-

-/*

-    <stateSpotProperty>    ::= "direction" 

-*/

-stateSpotProperty

-    "direction";

-

-/*

-    <stateLightModelItem>  ::= "lightmodel" <stateLModProperty>

-*/

-stateLightModelItem

-    "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;

-

-/*

-    <stateLModProperty>    ::= "." "ambient"

-                             | <optFaceType> "." "scenecolor"

-*/

-stateLModProperty

-    stateLModProperty_1 .or stateLModProperty_2;

-stateLModProperty_1

-    dot .and "ambient" .emit LIGHT_MODEL_AMBIENT;

-stateLModProperty_2

-    stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;

-stateLModProperty_3

-    optFaceType .and dot .and "scenecolor";

-

-/*

-    <stateLightProdItem>   ::= "lightprod" "[" <stateLightNumber> "]"

-                                 <optFaceType> "." <stateLProdProperty>

-*/

-stateLightProdItem

-    "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and

-    stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;

-

-/*

-    <stateLProdProperty>   ::= "ambient"

-                             | "diffuse"

-                             | "specular"

-*/

-stateLProdProperty

-    "ambient" .emit LIGHT_PROD_AMBIENT .or

-    "diffuse" .emit LIGHT_PROD_DIFFUSE .or

-    "specular" .emit LIGHT_PROD_SPECULAR;

-

-/*

-    <stateLightNumber>     ::= <integer> from 0 to MAX_LIGHTS-1

-*/

-stateLightNumber

-    integer;

-

-/*

-fragment program

-    <stateTexEnvItem>      ::= "texenv" <optLegacyTexUnitNum> "." 

-                                 <stateTexEnvProperty>

-*/

-stateTexEnvItem

-    "texenv" .and optLegacyTexUnitNum .and dot .and

-    stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;

-

-/*

-fragment program

-    <stateTexEnvProperty>  ::= "color"

-*/

-stateTexEnvProperty

-    "color" .emit TEX_ENV_COLOR;

-

-/*

-fragment program

-    <optLegacyTexUnitNum>  ::= ""

-                             | "[" <legacyTexUnitNum> "]"

-

-NOTE: <optLegaceTexUnitNum> is not optional.

-*/

-optLegacyTexUnitNum

-    lbracket_ne .and legacyTexUnitNum .and rbracket;

-

-/*

-fragment program

-    <legacyTexUnitNum>     ::= <integer> from 0 to MAX_TEXTURE_UNITS-1

-*/

-legacyTexUnitNum

-    integer;

-

-/*

-vertex program

-    <stateTexGenItem>      ::= "texgen" <optTexCoordNum> "."

-                                 <stateTexGenType> "." <stateTexGenCoord>

-*/

-stateTexGenItem

-    "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and

-    dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;

-

-/*

-vertex program

-    <stateTexGenType>      ::= "eye"

-                             | "object"

-*/

-stateTexGenType

-    "eye" .emit TEX_GEN_EYE .or

-    "object" .emit TEX_GEN_OBJECT;

-

-/*

-vertex program

-    <stateTexGenCoord>     ::= "s"

-                             | "t"

-                             | "r"

-                             | "q"

-*/

-stateTexGenCoord

-    "s" .emit COMPONENT_X .or

-    "t" .emit COMPONENT_Y .or

-    "r" .emit COMPONENT_Z .or

-    "q" .emit COMPONENT_W;

-

-/*

-    <stateFogItem>         ::= "fog" "." <stateFogProperty>

-*/

-stateFogItem

-    "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;

-

-/*

-    <stateFogProperty>     ::= "color"

-                             | "params"

-*/

-stateFogProperty

-    "color" .emit FOG_COLOR .or

-    "params" .emit FOG_PARAMS;

-

-/*

-fragment program

-    <stateDepthItem>       ::= "depth" "." <stateDepthProperty>

-*/

-stateDepthItem

-    "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;

-

-/*

-fragment program

-    <stateDepthProperty>   ::= "range"

-*/

-stateDepthProperty

-    "range" .emit DEPTH_RANGE;

-

-/*

-vertex program

-    <stateClipPlaneItem>   ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"

-*/

-stateClipPlaneItem

-    "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and

-    "plane" .error INVALID_CLIPPLANE_PROPERTY;

-

-/*

-vertex program

-    <stateClipPlaneNum>    ::= <integer> from 0 to MAX_CLIP_PLANES-1

-*/

-stateClipPlaneNum

-    integer;

-

-/*

-vertex program

-    <statePointItem>       ::= "point" . <statePointProperty>

-*/

-statePointItem

-    "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;

-

-/*

-vertex program

-    <statePointProperty>   ::= "size"

-                             | "attenuation"

-*/

-statePointProperty

-    "size" .emit POINT_SIZE .or

-    .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION;

-

-/*

-    <stateMatrixRow>       ::= <stateMatrixItem> "." "row" "[" 

-                                  <stateMatrixRowNum> "]"

-*/

-stateMatrixRow

-    stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and

-    lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;

-

-/*

-    <stateMatrixRows>      ::= <stateMatrixItem> <optMatrixRows>

-*/

-stateMatrixRows

-    stateMatrixItem .and optMatrixRows;

-

-/*

-    <optMatrixRows>        ::= ""

-                             | "." "row" "[" <stateMatrixRowNum> ".." 

-                                  <stateMatrixRowNum> "]"

-*/

-optMatrixRows

-    optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;

-optMatrixRows_1

-    dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and

-    stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;

-

-/*

-    <stateMatrixItem>      ::= "matrix" . <stateMatrixName> 

-                               <stateOptMatModifier>

-*/

-stateMatrixItem

-    "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;

-

-/*

-    <stateOptMatModifier>  ::= ""

-                             | "." <stateMatModifier>

-*/

-stateOptMatModifier

-    stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;

-stateOptMatModifier_1

-    dot_ne .and stateMatModifier;

-

-/*

-    <stateMatModifier>     ::= "inverse" 

-                             | "transpose" 

-                             | "invtrans"

-*/

-stateMatModifier

-    "inverse" .emit MATRIX_MODIFIER_INVERSE .or

-    "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or

-    "invtrans" .emit MATRIX_MODIFIER_INVTRANS;

-

-/*

-    <stateMatrixRowNum>    ::= <integer> from 0 to 3

-*/

-stateMatrixRowNum

-    integer_0_3;

-

-/*

-    <stateMatrixName>      ::= "modelview" <stateOptModMatNum>

-                             | "projection"

-                             | "mvp"

-                             | "texture" <optTexCoordNum>

-                             | "palette" "[" <statePaletteMatNum> "]"

-                             | "program" "[" <stateProgramMatNum> "]"

-*/

-stateMatrixName

-    stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or

-    "projection" .emit MATRIX_PROJECTION .or

-    "mvp" .emit MATRIX_MVP .or

-    stateMatrixName_1_2 .emit MATRIX_TEXTURE .or

-    .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or

-    stateMatrixName_1_4 .emit MATRIX_PROGRAM;

-stateMatrixName_1_1

-    "modelview" .and stateOptModMatNum;

-stateMatrixName_1_2

-    "texture" .and optTexCoordNum;

-stateMatrixName_1_3

-    "palette" .and lbracket .and statePaletteMatNum .and rbracket;

-stateMatrixName_1_4

-    "program" .and lbracket .and stateProgramMatNum .and rbracket;

-

-/*

-    <stateOptModMatNum>    ::= ""

-                             | "[" <stateModMatNum> "]"

-*/

-stateOptModMatNum

-    .if (vertex_blend != 0x00) stateOptModMatNum_1 .or

-    .true .emit 0x00;

-stateOptModMatNum_1

-    lbracket_ne .and stateModMatNum .and rbracket;

-

-/*

-    <stateModMatNum>       ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1

-*/

-stateModMatNum

-    integer;

-

-/*

-    <optTexCoordNum>       ::= ""

-                             | "[" <texCoordNum> "]"

-*/

-optTexCoordNum

-    optTexCoordNum_1 .or .true .emit 0x00;

-optTexCoordNum_1

-    lbracket_ne .and texCoordNum .and rbracket;

-

-/*

-    <texCoordNum>          ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1

-*/

-texCoordNum

-    integer;

-

-/*

-    <statePaletteMatNum>   ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1

-*/

-statePaletteMatNum

-    integer;

-

-/*

-    <stateProgramMatNum>   ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1

-*/

-stateProgramMatNum

-    integer;

-

-/*

-    <programSingleItem>    ::= <progEnvParam>

-                             | <progLocalParam>

-

-NOTE: <programSingleItem> has been modified for correct error handling. If program property

-      is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.

-*/

-programSingleItem

-    "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;

-programSingleItem_1

-    progEnvParam .or progLocalParam;

-

-/*

-    <programMultipleItem>  ::= <progEnvParams>

-                             | <progLocalParams>

-

-NOTE: <programMultipleItem> has been modified for correct error handling. If program property

-      is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.

-*/

-programMultipleItem

-    "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;

-programMultipleItem_1

-    progEnvParams .or progLocalParams;

-

-/*

-    <progEnvParams>        ::= "program" "." "env" 

-                                 "[" <progEnvParamNums> "]"

-

-NOTE: "program" "." has been moved to <programMultipleItem>.

-*/

-progEnvParams

-    "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;

-

-/*

-    <progEnvParamNums>     ::= <progEnvParamNum>

-                             | <progEnvParamNum> ".." <progEnvParamNum>

-*/

-progEnvParamNums

-    progEnvParamNums_1 .or progEnvParamNums_2;

-progEnvParamNums_1

-    progEnvParamNum .and dotdot_ne .and progEnvParamNum;

-progEnvParamNums_2

-    progEnvParamNum .and .true .emit 0x00;

-

-/*

-    <progEnvParam>         ::= "program" "." "env" 

-                                 "[" <progEnvParamNum> "]"

-

-NOTE: "program" "." has been moved to <programSingleItem>.

-*/

-progEnvParam

-    "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;

-

-/*

-    <progLocalParams>      ::= "program" "." "local" 

-                                 "[" <progLocalParamNums> "]"

-

-NOTE: "program" "." has been moved to <programMultipleItem>.

-*/

-progLocalParams

-    "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;

-

-/*

-    <progLocalParamNums>   ::= <progLocalParamNum>

-                             | <progLocalParamNum> ".." <progLocalParamNum>

-*/

-progLocalParamNums

-    progLocalParamNums_1 .or progLocalParamNums_2;

-progLocalParamNums_1

-    progLocalParamNum .and dotdot_ne .and progLocalParamNum;

-progLocalParamNums_2

-    progLocalParamNum .and .true .emit 0x00;

-

-/*

-    <progLocalParam>       ::= "program" "." "local" 

-                                 "[" <progLocalParamNum> "]"

-

-NOTE: "program" "." has been moved to <programSingleItem>.

-*/

-progLocalParam

-    "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;

-

-/*

-    <progEnvParamNum>      ::= <integer> from 0 to

-                               MAX_PROGRAM_ENV_PARAMETERS_ARB - 1

-*/

-progEnvParamNum

-    integer;

-

-/*

-    <progLocalParamNum>    ::= <integer> from 0 to

-                               MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1

-*/

-progLocalParamNum

-    integer;

-

-/*

-    <paramConstDecl>       ::= <paramConstScalarDecl>

-                             | <paramConstVector>

-*/

-paramConstDecl

-    paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;

-

-/*

-    <paramConstUse>        ::= <paramConstScalarUse>

-                             | <paramConstVector>

-*/

-paramConstUse

-    paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;

-

-/*

-    <paramConstScalarDecl> ::= <signedFloatConstant>

-*/

-paramConstScalarDecl

-    signedFloatConstant;

-

-/*

-    <paramConstScalarUse>  ::= <floatConstant>

-*/

-paramConstScalarUse

-    floatConstant;

-

-/*

-    <paramConstVector>     ::= "{" <signedFloatConstant> "}"

-                             | "{" <signedFloatConstant> "," 

-                                   <signedFloatConstant> "}"

-                             | "{" <signedFloatConstant> "," 

-                                   <signedFloatConstant> ","

-                                   <signedFloatConstant> "}"

-                             | "{" <signedFloatConstant> "," 

-                                   <signedFloatConstant> ","

-                                   <signedFloatConstant> "," 

-                                   <signedFloatConstant> "}"

-*/

-paramConstVector

-    paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or

-    paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;

-paramConstVector_1

-    lbrace_ne .and signedFloatConstant .and rbrace;

-paramConstVector_2

-    lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;

-paramConstVector_3

-    lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and

-    signedFloatConstant .and rbrace;

-paramConstVector_4

-    lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and

-    signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;

-

-/*

-    <signedFloatConstant>  ::= <optionalSign> <floatConstant>

-*/

-signedFloatConstant

-    optionalSign .and floatConstant;

-

-/*

-    <floatConstant>        ::= see text

-    The <floatConstant> rule matches a floating-point constant consisting

-    of an integer part, a decimal point, a fraction part, an "e" or

-    "E", and an optionally signed integer exponent.  The integer and

-    fraction parts both consist of a sequence of one or more digits ("0"

-    through "9").  Either the integer part or the fraction parts (not

-    both) may be missing; either the decimal point or the "e" (or "E")

-    and the exponent (not both) may be missing.

-*/

-floatConstant

-    float;

-

-/*

-    <optionalSign>         ::= ""

-                             | "-"

-                             | "+"

-*/

-optionalSign

-    optional_sign_ne;

-

-/*

-    <TEMP_statement>       ::= "TEMP" <varNameList>

-*/

-fp_TEMP_statement

-    "TEMP" .and space .and fp_varNameList .and .true .emit 0x00;

-vp_TEMP_statement

-    "TEMP" .and space .and vp_varNameList .and .true .emit 0x00;

-

-/*

-vertex program

-    <ADDRESS_statement>    ::= "ADDRESS" <varNameList>

-*/

-ADDRESS_statement

-    "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00;

-

-/*

-    <varNameList>          ::= <establishName>

-                             | <establishName> "," <varNameList>

-*/

-fp_varNameList

-    fp_varNameList_1 .or fp_establishName;

-vp_varNameList

-    vp_varNameList_1 .or vp_establishName;

-fp_varNameList_1

-    fp_establishName .and comma_ne .and fp_varNameList;

-vp_varNameList_1

-    vp_establishName .and comma_ne .and vp_varNameList;

-

-/*

-    <OUTPUT_statement>     ::= "OUTPUT" <establishName> "="

-                                 <resultBinding>

-*/

-fp_OUTPUT_statement

-    "OUTPUT" .and space .and fp_establishName .and equal .and

-    fp_resultBinding .error RESULT_EXPECTED;

-vp_OUTPUT_statement

-    "OUTPUT" .and space .and vp_establishName .and equal .and

-    vp_resultBinding .error RESULT_EXPECTED;

-

-/*

-fragment program

-    <resultBinding>        ::= "result" "." "color"

-                             | "result" "." "depth"

-

-vertex program

-    <resultBinding>        ::= "result" "." "position"

-                             | "result" "." <resultColBinding>

-                             | "result" "." "fogcoord"

-                             | "result" "." "pointsize"

-                             | "result" "." "texcoord" <optTexCoordNum>

-*/

-fp_resultBinding

-    "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;

-vp_resultBinding

-    "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;

-fp_resultBinding_1

-    "color" .emit FRAGMENT_RESULT_COLOR .or

-    "depth" .emit FRAGMENT_RESULT_DEPTH;

-vp_resultBinding_1

-    .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or

-    resultColBinding .emit VERTEX_RESULT_COLOR .or

-    "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or

-    "pointsize" .emit VERTEX_RESULT_POINTSIZE .or

-    vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;

-vp_resultBinding_2

-    "texcoord" .and optTexCoordNum;

-

-/*

-vertex program

-    <resultColBinding>     ::= "color" <optFaceType> <optColorType>

-*/

-resultColBinding

-    "color" .and optFaceType .and optColorType;

-

-/*

-    <optFaceType>          ::= ""

-                             | "." "front"

-                             | "." "back"

-*/

-optFaceType

-    FaceType .or .true .emit FACE_FRONT;

-FaceType

-    dot_ne .and FaceProperty;

-FaceProperty

-    "front" .emit FACE_FRONT .or "back" .emit FACE_BACK;

-

-/*

-    <optColorType>         ::= ""

-                             | "." "primary"

-                             | "." "secondary"

-*/

-optColorType

-    ColorType .or .true .emit COLOR_PRIMARY;

-ColorType

-    dot_ne .and ColorProperty;

-ColorProperty

-    "primary" .emit COLOR_PRIMARY .or

-    .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY;

-

-/*

-    <ALIAS_statement>      ::= "ALIAS" <establishName> "="

-                                 <establishedName>

-*/

-fp_ALIAS_statement

-    "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;

-vp_ALIAS_statement

-    "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;

-fp_ALIAS_statement_1

-    space .and fp_establishName;

-vp_ALIAS_statement_1

-    space .and vp_establishName;

-

-/*

-    <establishName>        ::= <identifier>

-*/

-fp_establishName

-    fp_identifier;

-vp_establishName

-    vp_identifier;

-

-/*

-    <establishedName>      ::= <identifier>

-*/

-fp_establishedName

-    fp_identifier;

-vp_establishedName

-    vp_identifier;

-fp_establishedName_no_error_on_identifier

-    fp_identifier_ne;

-vp_establishedName_no_error_on_identifier

-    vp_identifier_ne;

-

-/*

-fragment program

-    <identifier>           ::= see text

-    The <identifier> rule matches a sequence of one or more letters ("A"

-    through "Z", "a" through "z"), digits ("0" through "9), underscores 

-    ("_"), or dollar signs ("$"); the first character must not be a 

-    number.  Upper and lower case letters are considered different 

-    (names are case-sensitive).  The following strings are reserved 

-    keywords and may not be used as identifiers:

-

-        ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,

-        COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT, 

-        END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2, 

-        LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT, 

-        MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM, 

-        POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS, 

-        SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT, 

-        TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT, 

-        fragment, program, result, state, and texture.

-

-vertex program

-    <identifier>           ::= see text

-    The <identifier> rule matches a sequence of one or more letters ("A"

-    through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),

-    or dollar signs ("$"); the first character must not be a number.  Upper

-    and lower case letters are considered different (names are

-    case-sensitive).  The following strings are reserved keywords and may not

-    be used as identifiers:

-

-        ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,

-        EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,

-        PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,

-        state, and vertex.

-*/

-fp_identifier

-    fp_identifier_ne .error IDENTIFIER_EXPECTED;

-vp_identifier

-    vp_identifier_ne .error IDENTIFIER_EXPECTED;

-fp_identifier_ne

-    fp_not_reserved_identifier .and identifier_ne;

-vp_identifier_ne

-    vp_not_reserved_identifier .and identifier_ne;

-

-fp_not_reserved_identifier

-    fp_not_reserved_identifier_1 .or .true;

-fp_not_reserved_identifier_1

-    fp_reserved_identifier .and .false .error RESERVED_KEYWORD;

-vp_not_reserved_identifier

-    vp_not_reserved_identifier_1 .or .true;

-vp_not_reserved_identifier_1

-    vp_reserved_identifier .and .false .error RESERVED_KEYWORD;

-

-fp_reserved_identifier

-    "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or

-    "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or

-    "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or

-    "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or

-    "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or

-    "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or

-    "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or

-    "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or

-    "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or

-    "fragment" .or "program" .or "result" .or "state" .or "texture";

-vp_reserved_identifier

-    "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or

-    "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or

-    "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or

-    "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or

-    "XPD" .or "program" .or "result" .or "state" .or "vertex";

-

-/*

-    The <integer> rule matches an integer constant.  The integer consists

-    of a sequence of one or more digits ("0" through "9").

-*/

-integer

-    integer_ne .error INTEGER_EXPECTED;

-

-zero

-    '0';

-

-leading_zeroes

-    .loop zero;

-

-no_digit

-    no_digit_1 .or .true;

-no_digit_1

-    digit10 .and .false .error INTEGER_OUT_OF_RANGE;

-

-all_zeroes

-    all_zeroes_1 .or no_digit_1;

-all_zeroes_1

-    '0' .and .loop zero .and no_digit;

-

-integer_0_3

-    integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;

-integer_0_3_1

-    integer_0_3_2 .or all_zeroes .emit '0';

-integer_0_3_2       /* [1, 3] */

-    leading_zeroes .and '1'-'3' .emit * .and no_digit;

-

-integer_0_63

-    integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;

-integer_0_63_1

-    integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or

-    all_zeroes .emit '0';

-integer_0_63_2      /* [7, 9] */

-    leading_zeroes .and '7'-'9' .emit * .and no_digit;

-integer_0_63_3      /* [10, 59] */

-    leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;

-integer_0_63_4      /* [60, 63] */

-    leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;

-integer_0_63_5      /* [1, 6] */

-    leading_zeroes .and '1'-'6' .emit * .and no_digit;

-

-integer_0_64

-    integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;

-integer_0_64_1

-    integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or

-    all_zeroes .emit '0';

-integer_0_64_2      /* [7, 9] */

-    leading_zeroes .and '7'-'9' .emit * .and no_digit;

-integer_0_64_3      /* [10, 59] */

-    leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;

-integer_0_64_4      /* [60, 64] */

-    leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;

-integer_0_64_5      /* [1, 6] */

-    leading_zeroes .and '1'-'6' .emit * .and no_digit;

-

-optional_space

-    space .or .true;

-

-space_dst

-    space .error OPERATION_NEEDS_DESTINATION_VARIABLE;

-

-space_src

-    space .error OPERATION_NEEDS_SOURCE_VARIABLE;

-

-space

-    single_space .and .loop single_space;

-

-single_space

-    white_char .or comment_block;

-

-white_char

-    ' ' .or '\t' .or '\n' .or '\r';

-

-comment_block

-    '#' .and .loop comment_char .and new_line;

-

-/* All ASCII characters except '\r', '\n' and '\0' */

-comment_char

-    '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';

-

-new_line

-    '\n' .or crlf .or '\0';

-

-crlf

-    '\r' .and '\n';

-

-semicolon

-    optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;

-

-comma

-    optional_space .and ',' .error MISSING_COMMA .and optional_space;

-

-comma_ne

-    optional_space .and ',' .and optional_space;

-

-lbracket

-    optional_space .and '[' .error MISSING_LBRACKET .and optional_space;

-

-lbracket_ne

-    optional_space .and '[' .and optional_space;

-

-rbracket

-    optional_space .and ']' .error MISSING_RBRACKET .and optional_space;

-

-dot

-    optional_space .and '.' .error MISSING_DOT .and optional_space;

-

-dot_ne

-    optional_space .and '.' .and optional_space;

-

-equal

-    optional_space .and '=' .error MISSING_EQUAL .and optional_space;

-

-lbrace

-    optional_space .and '{' .error MISSING_LBRACE .and optional_space;

-

-lbrace_ne

-    optional_space .and '{' .and optional_space;

-

-rbrace

-    optional_space .and '}' .error MISSING_RBRACE .and optional_space;

-

-dotdot

-    optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;

-

-dotdot_ne

-    optional_space .and '.' .and '.' .and optional_space;

-

-/*

-    The definition below accepts the following floating point number formats:

-    .99 .99e99 99. 99.99 99.99e99 99.e99 99e99

-    Also 99 format was considered and accepted because of a large number of existing program

-    strings with such a format.

-*/

-float

-    float_1 .or float_2 .or float_legacy;

-float_1

-    '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;

-float_2

-    integer_ne .and float_3;

-float_3

-    float_4 .or float_5;

-float_4

-    '.' .and optional_integer .and optional_exponent;

-float_5

-    exponent .emit 0x00;

-float_legacy

-    integer_ne .and .true .emit 0x00 .emit 0x00;

-

-/*

-    Below is a correct version of <float> definiton.

-*/

-/*

-float

-    float_1 .or float_2;

-float_1

-    '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;

-float_2

-    integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT;

-float_3

-    float_4 .or float_5;

-float_4

-    '.' .and optional_integer .and optional_exponent;

-float_5

-    exponent .emit 0x00;

-*/

-

-integer_ne

-    integer_ne_1 .and .true .emit 0x00 .emit $;

-integer_ne_1

-    digit10 .emit * .and .loop digit10 .emit *;

-

-optional_integer

-    integer_ne .or .true .emit 0x00;

-

-/*

-NOTE: If exponent part is omited we treat it as if it was "E+1".

-*/

-optional_exponent

-    exponent .or .true .emit 0x00;

-

-exponent

-    exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;

-exponent_1

-    'e' .or 'E';

-

-optional_sign_ne

-    minus_ne .or plus_ne .or .true;

-

-plus_ne

-    optional_space .and '+' .and optional_space;

-

-minus_ne

-    optional_space .and '-' .emit '-' .and optional_space;

-

-identifier_ne

-    first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;

-

-follow_idchar

-    first_idchar .or digit10;

-

-first_idchar

-    'a'-'z' .or 'A'-'Z' .or '_' .or '$';

-

-digit10

-    '0'-'9';

-

-/*

-    string filtering - if a string is encountered in grammar ("blabla"), the symbol below is

-    executed to create the string. The symbol must not throw any errors and emit bytes - it should

-    stop if it encounters invalid character. After this the resulting string (from starting

-    position up to the invalid character (but without it) is compared with the grammar string.

-*/

-.string __string_filter;

-

-__string_filter

-    .loop __identifier_char;

-

-__identifier_char

-    'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';

-

-/*

-    error token filtering

-*/

-e_signature

-    e_signature_char .and .loop e_signature_char;

-e_signature_char

-    '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';

-

-e_statement

-    .loop e_statement_not_term;

-/* All ASCII characters to one of '\r', '\n', '\0' and ';' */

-e_statement_not_term

-    '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C';

-

-e_identifier

-    e_identifier_first .and .loop e_identifier_next;

-e_identifier_first

-    'a'-'z' .or 'A'-'Z' .or '_' .or '$';

-e_identifier_next

-    e_identifier_first .or '0'-'9';

-

-e_token

-    e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or

-    '-' .or ',' .or ';';

-e_token_number

-    e_token_digit .and .loop e_token_digit;

-e_token_digit

-    '0'-'9';

-

-e_charordigit

-    'A'-'Z' .or 'a'-'z' .or '0'-'9';

-

+.syntax program;
+
+/*
+   This value must be incremented every time emit code values or structure of the production
+   array changes. This value is placed at the beginning of the production array. The loader
+   compares the value with its REVISION value. If they do not match, the loader is not up
+   to date.
+*/
+.emtcode REVISION                                   0x07
+
+/* program type */
+.emtcode FRAGMENT_PROGRAM                           0x01
+.emtcode VERTEX_PROGRAM                             0x02
+
+/* program section */
+.emtcode OPTION                                     0x01
+.emtcode INSTRUCTION                                0x02
+.emtcode DECLARATION                                0x03
+.emtcode END                                        0x04
+
+/* GL_ARB_fragment_program option flags */
+.emtcode ARB_PRECISION_HINT_FASTEST                 0x01
+.emtcode ARB_PRECISION_HINT_NICEST                  0x02
+.emtcode ARB_FOG_EXP                                0x04
+.emtcode ARB_FOG_EXP2                               0x08
+.emtcode ARB_FOG_LINEAR                             0x10
+
+/* GL_ARB_vertex_program option flags */
+.emtcode ARB_POSITION_INVARIANT                     0x20
+
+/* GL_ARB_fragment_program_shadow option flags */
+.emtcode ARB_FRAGMENT_PROGRAM_SHADOW                0x40
+
+/* GL_ARB_fragment_program instruction class */
+.emtcode OP_ALU_INST                                0x00
+.emtcode OP_TEX_INST                                0x01
+
+/* GL_ARB_vertex_program instruction class */
+/*       OP_ALU_INST */
+
+/* GL_ARB_fragment_program instruction type */
+.emtcode OP_ALU_VECTOR                               0x00
+.emtcode OP_ALU_SCALAR                               0x01
+.emtcode OP_ALU_BINSC                                0x02
+.emtcode OP_ALU_BIN                                  0x03
+.emtcode OP_ALU_TRI                                  0x04
+.emtcode OP_ALU_SWZ                                  0x05
+.emtcode OP_TEX_SAMPLE                               0x06
+.emtcode OP_TEX_KIL                                  0x07
+
+/* GL_ARB_vertex_program instruction type */
+.emtcode OP_ALU_ARL                                  0x08
+/*       OP_ALU_VECTOR */
+/*       OP_ALU_SCALAR */
+/*       OP_ALU_BINSC */
+/*       OP_ALU_BIN */
+/*       OP_ALU_TRI */
+/*       OP_ALU_SWZ */
+
+/* GL_ARB_fragment_program instruction code */
+.emtcode OP_ABS                                     0x00
+.emtcode OP_ABS_SAT                                 0x1B
+.emtcode OP_FLR                                     0x09
+.emtcode OP_FLR_SAT                                 0x26
+.emtcode OP_FRC                                     0x0A
+.emtcode OP_FRC_SAT                                 0x27
+.emtcode OP_LIT                                     0x0C
+.emtcode OP_LIT_SAT                                 0x2A
+.emtcode OP_MOV                                     0x11
+.emtcode OP_MOV_SAT                                 0x30
+.emtcode OP_COS                                     0x1F
+.emtcode OP_COS_SAT                                 0x20
+.emtcode OP_EX2                                     0x07
+.emtcode OP_EX2_SAT                                 0x25
+.emtcode OP_LG2                                     0x0B
+.emtcode OP_LG2_SAT                                 0x29
+.emtcode OP_RCP                                     0x14
+.emtcode OP_RCP_SAT                                 0x33
+.emtcode OP_RSQ                                     0x15
+.emtcode OP_RSQ_SAT                                 0x34
+.emtcode OP_SIN                                     0x38
+.emtcode OP_SIN_SAT                                 0x39
+.emtcode OP_SCS                                     0x35
+.emtcode OP_SCS_SAT                                 0x36
+.emtcode OP_POW                                     0x13
+.emtcode OP_POW_SAT                                 0x32
+.emtcode OP_ADD                                     0x01
+.emtcode OP_ADD_SAT                                 0x1C
+.emtcode OP_DP3                                     0x03
+.emtcode OP_DP3_SAT                                 0x21
+.emtcode OP_DP4                                     0x04
+.emtcode OP_DP4_SAT                                 0x22
+.emtcode OP_DPH                                     0x05
+.emtcode OP_DPH_SAT                                 0x23
+.emtcode OP_DST                                     0x06
+.emtcode OP_DST_SAT                                 0x24
+.emtcode OP_MAX                                     0x0F
+.emtcode OP_MAX_SAT                                 0x2E
+.emtcode OP_MIN                                     0x10
+.emtcode OP_MIN_SAT                                 0x2F
+.emtcode OP_MUL                                     0x12
+.emtcode OP_MUL_SAT                                 0x31
+.emtcode OP_SGE                                     0x16
+.emtcode OP_SGE_SAT                                 0x37
+.emtcode OP_SLT                                     0x17
+.emtcode OP_SLT_SAT                                 0x3A
+.emtcode OP_SUB                                     0x18
+.emtcode OP_SUB_SAT                                 0x3B
+.emtcode OP_XPD                                     0x1A
+.emtcode OP_XPD_SAT                                 0x43
+.emtcode OP_CMP                                     0x1D
+.emtcode OP_CMP_SAT                                 0x1E
+.emtcode OP_LRP                                     0x2B
+.emtcode OP_LRP_SAT                                 0x2C
+.emtcode OP_MAD                                     0x0E
+.emtcode OP_MAD_SAT                                 0x2D
+.emtcode OP_SWZ                                     0x19
+.emtcode OP_SWZ_SAT                                 0x3C
+.emtcode OP_TEX                                     0x3D
+.emtcode OP_TEX_SAT                                 0x3E
+.emtcode OP_TXB                                     0x3F
+.emtcode OP_TXB_SAT                                 0x40
+.emtcode OP_TXP                                     0x41
+.emtcode OP_TXP_SAT                                 0x42
+.emtcode OP_KIL                                     0x28
+
+/* GL_ARB_vertex_program instruction code */
+.emtcode OP_ARL                                     0x02
+/*       OP_ABS */
+/*       OP_FLR */
+/*       OP_FRC */
+/*       OP_LIT */
+/*       OP_MOV */
+/*       OP_EX2 */
+.emtcode OP_EXP                                     0x08
+/*       OP_LG2 */
+.emtcode OP_LOG                                     0x0D
+/*       OP_RCP */
+/*       OP_RSQ */
+/*       OP_POW */
+/*       OP_ADD */
+/*       OP_DP3 */
+/*       OP_DP4 */
+/*       OP_DPH */
+/*       OP_DST */
+/*       OP_MAX */
+/*       OP_MIN */
+/*       OP_MUL */
+/*       OP_SGE */
+/*       OP_SLT */
+/*       OP_SUB */
+/*       OP_XPD */
+/*       OP_MAD */
+/*       OP_SWZ */
+
+/* fragment attribute binding */
+.emtcode FRAGMENT_ATTRIB_COLOR                      0x01
+.emtcode FRAGMENT_ATTRIB_TEXCOORD                   0x02
+.emtcode FRAGMENT_ATTRIB_FOGCOORD                   0x03
+.emtcode FRAGMENT_ATTRIB_POSITION                   0x04
+
+/* vertex attribute binding */
+.emtcode VERTEX_ATTRIB_POSITION                     0x01
+.emtcode VERTEX_ATTRIB_WEIGHT                       0x02
+.emtcode VERTEX_ATTRIB_NORMAL                       0x03
+.emtcode VERTEX_ATTRIB_COLOR                        0x04
+.emtcode VERTEX_ATTRIB_FOGCOORD                     0x05
+.emtcode VERTEX_ATTRIB_TEXCOORD                     0x06
+.emtcode VERTEX_ATTRIB_MATRIXINDEX                  0x07
+.emtcode VERTEX_ATTRIB_GENERIC                      0x08
+
+/* fragment result binding */
+.emtcode FRAGMENT_RESULT_COLOR                      0x01
+.emtcode FRAGMENT_RESULT_DEPTH                      0x02
+
+/* vertex result binding */
+.emtcode VERTEX_RESULT_POSITION                     0x01
+.emtcode VERTEX_RESULT_COLOR                        0x02
+.emtcode VERTEX_RESULT_FOGCOORD                     0x03
+.emtcode VERTEX_RESULT_POINTSIZE                    0x04
+.emtcode VERTEX_RESULT_TEXCOORD                     0x05
+
+/* texture target */
+.emtcode TEXTARGET_1D                               0x01
+.emtcode TEXTARGET_2D                               0x02
+.emtcode TEXTARGET_3D                               0x03
+.emtcode TEXTARGET_RECT                             0x04
+.emtcode TEXTARGET_CUBE                             0x05
+/* GL_ARB_fragment_program_shadow */
+.emtcode TEXTARGET_SHADOW1D                         0x06
+.emtcode TEXTARGET_SHADOW2D                         0x07
+.emtcode TEXTARGET_SHADOWRECT                       0x08
+
+/* face type */
+.emtcode FACE_FRONT                                 0x00
+.emtcode FACE_BACK                                  0x01
+
+/* color type */
+.emtcode COLOR_PRIMARY                              0x00
+.emtcode COLOR_SECONDARY                            0x01
+
+/* component */
+.emtcode COMPONENT_X                                0x00
+.emtcode COMPONENT_Y                                0x01
+.emtcode COMPONENT_Z                                0x02
+.emtcode COMPONENT_W                                0x03
+.emtcode COMPONENT_0                                0x04
+.emtcode COMPONENT_1                                0x05
+
+/* array index type */
+.emtcode ARRAY_INDEX_ABSOLUTE                       0x00
+.emtcode ARRAY_INDEX_RELATIVE                       0x01
+
+/* matrix name */
+.emtcode MATRIX_MODELVIEW                           0x01
+.emtcode MATRIX_PROJECTION                          0x02
+.emtcode MATRIX_MVP                                 0x03
+.emtcode MATRIX_TEXTURE                             0x04
+.emtcode MATRIX_PALETTE                             0x05
+.emtcode MATRIX_PROGRAM                             0x06
+
+/* matrix modifier */
+.emtcode MATRIX_MODIFIER_IDENTITY                   0x00
+.emtcode MATRIX_MODIFIER_INVERSE                    0x01
+.emtcode MATRIX_MODIFIER_TRANSPOSE                  0x02
+.emtcode MATRIX_MODIFIER_INVTRANS                   0x03
+
+/* constant type */
+.emtcode CONSTANT_SCALAR                            0x01
+.emtcode CONSTANT_VECTOR                            0x02
+
+/* program param type */
+.emtcode PROGRAM_PARAM_ENV                          0x01
+.emtcode PROGRAM_PARAM_LOCAL                        0x02
+
+/* register type */
+.emtcode REGISTER_ATTRIB                            0x01
+.emtcode REGISTER_PARAM                             0x02
+.emtcode REGISTER_RESULT                            0x03
+.emtcode REGISTER_ESTABLISHED_NAME                  0x04
+
+/* param binding */
+.emtcode PARAM_NULL                                 0x00
+.emtcode PARAM_ARRAY_ELEMENT                        0x01
+.emtcode PARAM_STATE_ELEMENT                        0x02
+.emtcode PARAM_PROGRAM_ELEMENT                      0x03
+.emtcode PARAM_PROGRAM_ELEMENTS                     0x04
+.emtcode PARAM_CONSTANT                             0x05
+
+/* param state property */
+.emtcode STATE_MATERIAL                             0x01
+.emtcode STATE_LIGHT                                0x02
+.emtcode STATE_LIGHT_MODEL                          0x03
+.emtcode STATE_LIGHT_PROD                           0x04
+.emtcode STATE_FOG                                  0x05
+.emtcode STATE_MATRIX_ROWS                          0x06
+/* GL_ARB_fragment_program */
+.emtcode STATE_TEX_ENV                              0x07
+.emtcode STATE_DEPTH                                0x08
+/* GL_ARB_vertex_program */
+.emtcode STATE_TEX_GEN                              0x09
+.emtcode STATE_CLIP_PLANE                           0x0A
+.emtcode STATE_POINT                                0x0B
+
+/* state material property */
+.emtcode MATERIAL_AMBIENT                           0x01
+.emtcode MATERIAL_DIFFUSE                           0x02
+.emtcode MATERIAL_SPECULAR                          0x03
+.emtcode MATERIAL_EMISSION                          0x04
+.emtcode MATERIAL_SHININESS                         0x05
+
+/* state light property */
+.emtcode LIGHT_AMBIENT                              0x01
+.emtcode LIGHT_DIFFUSE                              0x02
+.emtcode LIGHT_SPECULAR                             0x03
+.emtcode LIGHT_POSITION                             0x04
+.emtcode LIGHT_ATTENUATION                          0x05
+.emtcode LIGHT_HALF                                 0x06
+.emtcode LIGHT_SPOT_DIRECTION                       0x07
+
+/* state light model property */
+.emtcode LIGHT_MODEL_AMBIENT                        0x01
+.emtcode LIGHT_MODEL_SCENECOLOR                     0x02
+
+/* state light product property */
+.emtcode LIGHT_PROD_AMBIENT                         0x01
+.emtcode LIGHT_PROD_DIFFUSE                         0x02
+.emtcode LIGHT_PROD_SPECULAR                        0x03
+
+/* state texture environment property */
+.emtcode TEX_ENV_COLOR                              0x01
+
+/* state texture generation coord property */
+.emtcode TEX_GEN_EYE                                0x01
+.emtcode TEX_GEN_OBJECT                             0x02
+
+/* state fog property */
+.emtcode FOG_COLOR                                  0x01
+.emtcode FOG_PARAMS                                 0x02
+
+/* state depth property */
+.emtcode DEPTH_RANGE                                0x01
+
+/* state point parameters property */
+.emtcode POINT_SIZE                                 0x01
+.emtcode POINT_ATTENUATION                          0x02
+
+/* declaration */
+.emtcode ATTRIB                                     0x01
+.emtcode PARAM                                      0x02
+.emtcode TEMP                                       0x03
+.emtcode OUTPUT                                     0x04
+.emtcode ALIAS                                      0x05
+/* GL_ARB_vertex_program */
+.emtcode ADDRESS                                    0x06
+
+/* error messages */
+.errtext UNKNOWN_PROGRAM_SIGNATURE                  "1001: '$e_signature$': unknown program signature"
+.errtext MISSING_END_OR_INVALID_STATEMENT           "1002: '$e_statement$': invalid statement"
+.errtext CODE_AFTER_END                             "1003: '$e_statement$': code after 'END' keyword"
+.errtext INVALID_PROGRAM_OPTION                     "1004: '$e_identifier$': invalid program option"
+.errtext EXT_SWIZ_COMP_EXPECTED                     "1005: extended swizzle component expected but '$e_token$' found"
+.errtext TEX_TARGET_EXPECTED                        "1006: texture target expected but '$e_token$' found"
+.errtext TEXTURE_EXPECTED                           "1007: 'texture' expected but '$e_identifier$' found"
+.errtext SOURCE_REGISTER_EXPECTED                   "1008: source register expected but '$e_token$' found"
+.errtext DESTINATION_REGISTER_EXPECTED              "1009: destination register expected but '$e_token$' found"
+.errtext INVALID_ADDRESS_COMPONENT                  "1010: '$e_identifier$': invalid address component"
+.errtext INVALID_ADDRESS_WRITEMASK                  "1011: '$e_identifier$': invalid address writemask"
+.errtext INVALID_COMPONENT                          "1012: '$e_charordigit$': invalid component"
+.errtext INVALID_SUFFIX                             "1013: '$e_identifier$': invalid suffix"
+.errtext INVALID_WRITEMASK                          "1014: '$e_identifier$': invalid writemask"
+.errtext FRAGMENT_EXPECTED                          "1015: 'fragment' expected but '$e_identifier$' found"
+.errtext VERTEX_EXPECTED                            "1016: 'vertex' expected but '$e_identifier$' found"
+.errtext INVALID_FRAGMENT_PROPERTY                  "1017: '$e_identifier$': invalid fragment property"
+.errtext INVALID_VERTEX_PROPERTY                    "1018: '$e_identifier$': invalid vertex property"
+.errtext INVALID_STATE_PROPERTY                     "1019: '$e_identifier$': invalid state property"
+.errtext INVALID_MATERIAL_PROPERTY                  "1020: '$e_identifier$': invalid material property"
+.errtext INVALID_LIGHT_PROPERTY                     "1021: '$e_identifier$': invalid light property"
+.errtext INVALID_SPOT_PROPERTY                      "1022: '$e_identifier$': invalid spot property"
+.errtext INVALID_LIGHTMODEL_PROPERTY                "1023: '$e_identifier$': invalid light model property"
+.errtext INVALID_LIGHTPROD_PROPERTY                 "1024: '$e_identifier$': invalid light product property"
+.errtext INVALID_TEXENV_PROPERTY                    "1025: '$e_identifier$': invalid texture environment property"
+.errtext INVALID_TEXGEN_PROPERTY                    "1026: '$e_identifier$': invalid texture generating property"
+.errtext INVALID_TEXGEN_COORD                       "1027: '$e_identifier$': invalid texture generating coord"
+.errtext INVALID_FOG_PROPERTY                       "1028: '$e_identifier$': invalid fog property"
+.errtext INVALID_DEPTH_PROPERTY                     "1029: '$e_identifier$': invalid depth property"
+.errtext INVALID_CLIPPLANE_PROPERTY                 "1030: '$e_identifier$': invalid clip plane property"
+.errtext INVALID_POINT_PROPERTY                     "1031: '$e_identifier$': invalid point property"
+.errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED   "1032: matrix row selector or modifier expected but '$e_token$' found"
+.errtext INVALID_MATRIX_NAME                        "1033: '$e_identifier$': invalid matrix name"
+.errtext INVALID_PROGRAM_PROPERTY                   "1034: '$e_identifier$': invalid program property"
+.errtext RESULT_EXPECTED                            "1035: 'result' expected but '$e_token$' found"
+.errtext INVALID_RESULT_PROPERTY                    "1036: '$e_identifier$': invalid result property"
+.errtext INVALID_FACE_PROPERTY                      "1037: '$e_identifier$': invalid face property"
+.errtext INVALID_COLOR_PROPERTY                     "1038: '$e_identifier$': invalid color property"
+.errtext IDENTIFIER_EXPECTED                        "1039: identifier expected but '$e_token$' found"
+.errtext RESERVED_KEYWORD                           "1040: use of reserved keyword as an identifier"
+.errtext INTEGER_EXPECTED                           "1041: integer value expected but '$e_token$' found"
+.errtext MISSING_SEMICOLON                          "1042: ';' expected but '$e_token$' found"
+.errtext MISSING_COMMA                              "1043: ',' expected but '$e_token$' found"
+.errtext MISSING_LBRACKET                           "1044: '[' expected but '$e_token$' found"
+.errtext MISSING_RBRACKET                           "1045: ']' expected but '$e_token$' found"
+.errtext MISSING_DOT                                "1046: '.' expected but '$e_token$' found"
+.errtext MISSING_EQUAL                              "1047: '=' expected but '$e_token$' found"
+.errtext MISSING_LBRACE                             "1048: '{' expected but '$e_token$' found"
+.errtext MISSING_RBRACE                             "1049: '}' expected but '$e_token$' found"
+.errtext MISSING_DOTDOT                             "1050: '..' expected but '$e_token$' found"
+.errtext MISSING_FRACTION_OR_EXPONENT               "1051: missing fraction part or exponent"
+.errtext MISSING_DOT_OR_EXPONENT                    "1052: missing '.' or exponent"
+.errtext EXPONENT_VALUE_EXPECTED                    "1053: exponent value expected"
+.errtext INTEGER_OUT_OF_RANGE                       "1054: integer value out of range"
+.errtext OPERATION_NEEDS_DESTINATION_VARIABLE       "1055: operation needs destination variable"
+.errtext OPERATION_NEEDS_SOURCE_VARIABLE            "1056: operation needs source variable"
+.errtext ADDRESS_REGISTER_EXPECTED                  "1057: address register expected but '$e_token$' found"
+.errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED       "1058: address register or integer literal expected but '$e_token$' found"
+
+/* extension presence condition registers */
+
+/* GL_ARB_vertex_blend */
+/* GL_EXT_vertex_weighting */
+.regbyte vertex_blend                               0x00
+
+/* GL_ARB_matrix_palette */
+.regbyte matrix_palette                             0x00
+
+/* GL_ARB_point_parameters */
+/* GL_EXT_point_parameters */
+.regbyte point_parameters                           0x00
+
+/* GL_EXT_secondary_color */
+.regbyte secondary_color                            0x00
+
+/* GL_EXT_fog_coord */
+.regbyte fog_coord                                  0x00
+
+/* GL_EXT_texture_rectangle */
+/* GL_NV_texture_rectangle */
+.regbyte texture_rectangle                          0x00
+
+/* GL_ARB_fragment_program_shadow */
+.regbyte fragment_program_shadow                    0x00
+
+/* option presence condition registers */
+/* they are all initially set to zero - when a particular OPTION is encountered, the appropriate */
+/* register is set to 1 to indicate that the OPTION was specified. */
+
+/* GL_ARB_fragment_program */
+.regbyte ARB_precision_hint_fastest                 0x00
+.regbyte ARB_precision_hint_nicest                  0x00
+.regbyte ARB_fog_exp                                0x00
+.regbyte ARB_fog_exp2                               0x00
+.regbyte ARB_fog_linear                             0x00
+
+/* GL_ARB_vertex_program */
+.regbyte ARB_position_invariant                     0x00
+
+/* GL_ARB_fragment_program_shadow */
+.regbyte ARB_fragment_program_shadow                0x00
+
+/* program target condition register */
+/* this syntax script deals with two program targets - VERTEX_PROGRAM and FRAGMENT_PROGRAM. */
+/* to distinguish between them we need a register that will store for us the current target. */
+/* the client will typically set the register to apropriate value before parsing a particular */
+/* program. the mapping between program targets and their values is listed below. */
+/* */
+/* program target               register value    */
+/* ---------------------------------------------- */
+/* FRAGMENT_PROGRAM             0x10              */
+/* VERTEX_PROGRAM               0x20              */
+/* */
+/* the initial value of the register is 0 to catch potential errors with not setting the register */
+/* with the proper value. */
+.regbyte program_target                             0x00
+
+/*
+    <program>              ::= <optionSequence> <statementSequence> "END"
+*/
+program
+    programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;
+programs
+    .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or
+    .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;
+frag_program_1_0
+    '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and
+    optional_space .and fp_optionSequence .and fp_statementSequence .and
+    "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
+    '\0' .error CODE_AFTER_END;
+vert_program_1_0
+    '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and
+    optional_space .and vp_optionSequence .and vp_statementSequence .and
+    "END" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and
+    '\0' .error CODE_AFTER_END;
+
+/*
+    <optionSequence>       ::= <optionSequence> <option>
+                             | ""
+*/
+fp_optionSequence
+    .loop fp_option;
+vp_optionSequence
+    .loop vp_option;
+
+/*
+    <option>               ::= "OPTION" <identifier> ";"
+
+NOTE: options ARB_precision_hint_nicest and ARB_precision_hint_fastest are exclusive. When one of
+      these options is encountered, the other one is automatically disabled.
+      the same applies to options ARB_fog_exp, ARB_fog_exp2 and ARB_fog_linear.
+*/
+fp_option
+    "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
+    fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
+vp_option
+    "OPTION" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and
+    vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;
+fp_optionString
+    .if (ARB_precision_hint_nicest == 0x00) "ARB_precision_hint_fastest"
+        .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or
+    .if (ARB_precision_hint_fastest == 0x00) "ARB_precision_hint_nicest"
+        .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or
+    fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or
+    fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or
+    fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or
+    .if (fragment_program_shadow != 0x00) "ARB_fragment_program_shadow"
+        .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;
+vp_optionString
+    "ARB_position_invariant" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;
+fp_ARB_fog_exp
+    .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp";
+fp_ARB_fog_exp2
+    .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) "ARB_fog_exp2";
+fp_ARB_fog_linear
+    .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) "ARB_fog_linear";
+
+/*
+    <statementSequence>    ::= <statementSequence> <statement>
+                             | ""
+*/
+fp_statementSequence
+    .loop fp_statement;
+vp_statementSequence
+    .loop vp_statement;
+
+/*
+    <statement>            ::= <instruction> ";"
+                             | <namingStatement> ";"
+
+NOTE: ".emit $" in the definitions below means that we output instruction position (offset of
+      the first character of instruction) for program debugging purposes.
+*/
+fp_statement
+    fp_statement_1 .or fp_statement_2;
+vp_statement
+    vp_statement_1 .or vp_statement_2;
+fp_statement_1
+    fp_instruction .emit INSTRUCTION .emit $ .and semicolon;
+fp_statement_2
+    fp_namingStatement .emit DECLARATION .and semicolon;
+vp_statement_1
+    vp_instruction .emit INSTRUCTION .emit $ .and semicolon;
+vp_statement_2
+    vp_namingStatement .emit DECLARATION .and semicolon;
+
+/*
+fragment program
+    <instruction>          ::= <ALUInstruction>
+                             | <TexInstruction>
+
+vertex program
+    <instruction>          ::= <ARL_instruction>
+                             | <VECTORop_instruction>
+                             | <SCALARop_instruction>
+                             | <BINSCop_instruction>
+                             | <BINop_instruction>
+                             | <TRIop_instruction>
+                             | <SWZ_instruction>
+*/
+fp_instruction
+    ALUInstruction .emit OP_ALU_INST .or
+    TexInstruction .emit OP_TEX_INST;
+vp_instruction
+    ARL_instruction .emit OP_ALU_ARL .or
+    vp_VECTORop_instruction .emit OP_ALU_VECTOR .or
+    vp_SCALARop_instruction .emit OP_ALU_SCALAR .or
+    vp_BINSCop_instruction .emit OP_ALU_BINSC .or
+    vp_BINop_instruction .emit OP_ALU_BIN .or
+    vp_TRIop_instruction .emit OP_ALU_TRI .or
+    vp_SWZ_instruction .emit OP_ALU_SWZ;
+
+/*
+fragment program
+    <ALUInstruction>       ::= <VECTORop_instruction>
+                             | <SCALARop_instruction>
+                             | <BINSCop_instruction>
+                             | <BINop_instruction>
+                             | <TRIop_instruction>
+                             | <SWZ_instruction>
+*/
+ALUInstruction
+    fp_VECTORop_instruction .emit OP_ALU_VECTOR .or
+    fp_SCALARop_instruction .emit OP_ALU_SCALAR .or
+    fp_BINSCop_instruction .emit OP_ALU_BINSC .or
+    fp_BINop_instruction .emit OP_ALU_BIN .or
+    fp_TRIop_instruction .emit OP_ALU_TRI .or
+    fp_SWZ_instruction .emit OP_ALU_SWZ;
+
+/*
+fragment program
+    <TexInstruction>       ::= <SAMPLE_instruction>
+                             | <KIL_instruction>
+*/
+TexInstruction
+    SAMPLE_instruction .emit OP_TEX_SAMPLE .or
+    KIL_instruction .emit OP_TEX_KIL;
+
+/*
+vertex program
+    <ARL_instruction>      ::= "ARL" <maskedAddrReg> "," <scalarSrcReg>
+*/
+ARL_instruction
+    "ARL" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;
+
+/*
+fragment program
+    <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," 
+                               <vectorSrcReg>
+
+vertex program
+    <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg>
+*/
+fp_VECTORop_instruction
+    fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;
+vp_VECTORop_instruction
+    vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;
+
+/*
+fragment program
+    <VECTORop>             ::= "ABS" | "ABS_SAT"
+                             | "FLR" | "FLR_SAT"
+                             | "FRC" | "FRC_SAT"
+                             | "LIT" | "LIT_SAT"
+                             | "MOV" | "MOV_SAT"
+
+vertex program
+    <VECTORop>             ::= "ABS"
+                             | "FLR"
+                             | "FRC"
+                             | "LIT"
+                             | "MOV"
+*/
+fp_VECTORop
+    "ABS" .emit OP_ABS .or "ABS_SAT" .emit OP_ABS_SAT .or
+    "FLR" .emit OP_FLR .or "FLR_SAT" .emit OP_FLR_SAT .or
+    "FRC" .emit OP_FRC .or "FRC_SAT" .emit OP_FRC_SAT .or
+    "LIT" .emit OP_LIT .or "LIT_SAT" .emit OP_LIT_SAT .or
+    "MOV" .emit OP_MOV .or "MOV_SAT" .emit OP_MOV_SAT;
+vp_VECTORop
+    "ABS" .emit OP_ABS .or
+    "FLR" .emit OP_FLR .or
+    "FRC" .emit OP_FRC .or
+    "LIT" .emit OP_LIT .or
+    "MOV" .emit OP_MOV;
+
+/*
+    <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg>
+*/
+fp_SCALARop_instruction
+    fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;
+vp_SCALARop_instruction
+    vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;
+
+/*
+fragment program
+    <SCALARop>             ::= "COS" | "COS_SAT"
+                             | "EX2" | "EX2_SAT"
+                             | "LG2" | "LG2_SAT"
+                             | "RCP" | "RCP_SAT"
+                             | "RSQ" | "RSQ_SAT"
+                             | "SIN" | "SIN_SAT"
+                             | "SCS" | "SCS_SAT"
+
+vertex program
+    <SCALARop>             ::= "EX2"
+                             | "EXP"
+                             | "LG2"
+                             | "LOG"
+                             | "RCP"
+                             | "RSQ"
+*/
+fp_SCALARop
+    "COS" .emit OP_COS .or "COS_SAT" .emit OP_COS_SAT .or
+    "EX2" .emit OP_EX2 .or "EX2_SAT" .emit OP_EX2_SAT .or
+    "LG2" .emit OP_LG2 .or "LG2_SAT" .emit OP_LG2_SAT .or
+    "RCP" .emit OP_RCP .or "RCP_SAT" .emit OP_RCP_SAT .or
+    "RSQ" .emit OP_RSQ .or "RSQ_SAT" .emit OP_RSQ_SAT .or
+    "SIN" .emit OP_SIN .or "SIN_SAT" .emit OP_SIN_SAT .or
+    "SCS" .emit OP_SCS .or "SCS_SAT" .emit OP_SCS_SAT;
+vp_SCALARop
+    "EX2" .emit OP_EX2 .or
+    "EXP" .emit OP_EXP .or
+    "LG2" .emit OP_LG2 .or
+    "LOG" .emit OP_LOG .or
+    "RCP" .emit OP_RCP .or
+    "RSQ" .emit OP_RSQ;
+
+/*
+    <BINSCop_instruction>  ::= <BINSCop> <maskedDstReg> "," <scalarSrcReg> ","
+                               <scalarSrcReg>
+*/
+fp_BINSCop_instruction
+    fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and
+    fp_scalarSrcReg;
+vp_BINSCop_instruction
+    vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and
+    vp_scalarSrcReg;
+
+/*
+fragment program
+    <BINSCop>              ::= "POW" | "POW_SAT"
+
+vertex program
+    <BINSCop>              ::= "POW"
+*/
+fp_BINSCop
+    "POW" .emit OP_POW .or "POW_SAT" .emit OP_POW_SAT;
+vp_BINSCop
+    "POW" .emit OP_POW;
+
+/*
+fragment program
+    <BINop_instruction>    ::= <BINop> <maskedDstReg> ","
+                               <vectorSrcReg> "," <vectorSrcReg>
+
+vertex program
+    <BINop_instruction>    ::= <BINop> <maskedDstReg> ","
+                               <swizzleSrcReg> "," <swizzleSrcReg>
+*/
+fp_BINop_instruction
+    fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
+    vectorSrcReg;
+vp_BINop_instruction
+    vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
+    swizzleSrcReg;
+
+/*
+fragment program
+    <BINop>                ::= "ADD" | "ADD_SAT"
+                             | "DP3" | "DP3_SAT"
+                             | "DP4" | "DP4_SAT"
+                             | "DPH" | "DPH_SAT"
+                             | "DST" | "DST_SAT"
+                             | "MAX" | "MAX_SAT"
+                             | "MIN" | "MIN_SAT"
+                             | "MUL" | "MUL_SAT"
+                             | "SGE" | "SGE_SAT"
+                             | "SLT" | "SLT_SAT"
+                             | "SUB" | "SUB_SAT"
+                             | "XPD" | "XPD_SAT"
+
+vertex program
+    <BINop>                ::= "ADD"
+                             | "DP3"
+                             | "DP4"
+                             | "DPH"
+                             | "DST"
+                             | "MAX"
+                             | "MIN"
+                             | "MUL"
+                             | "SGE"
+                             | "SLT"
+                             | "SUB"
+                             | "XPD"
+*/
+fp_BINop
+    "ADD" .emit OP_ADD .or "ADD_SAT" .emit OP_ADD_SAT .or
+    "DP3" .emit OP_DP3 .or "DP3_SAT" .emit OP_DP3_SAT .or
+    "DP4" .emit OP_DP4 .or "DP4_SAT" .emit OP_DP4_SAT .or
+    "DPH" .emit OP_DPH .or "DPH_SAT" .emit OP_DPH_SAT .or
+    "DST" .emit OP_DST .or "DST_SAT" .emit OP_DST_SAT .or
+    "MAX" .emit OP_MAX .or "MAX_SAT" .emit OP_MAX_SAT .or
+    "MIN" .emit OP_MIN .or "MIN_SAT" .emit OP_MIN_SAT .or
+    "MUL" .emit OP_MUL .or "MUL_SAT" .emit OP_MUL_SAT .or
+    "SGE" .emit OP_SGE .or "SGE_SAT" .emit OP_SGE_SAT .or
+    "SLT" .emit OP_SLT .or "SLT_SAT" .emit OP_SLT_SAT .or
+    "SUB" .emit OP_SUB .or "SUB_SAT" .emit OP_SUB_SAT .or
+    "XPD" .emit OP_XPD .or "XPD_SAT" .emit OP_XPD_SAT;
+vp_BINop
+    "ADD" .emit OP_ADD .or
+    "DP3" .emit OP_DP3 .or
+    "DP4" .emit OP_DP4 .or
+    "DPH" .emit OP_DPH .or
+    "DST" .emit OP_DST .or
+    "MAX" .emit OP_MAX .or
+    "MIN" .emit OP_MIN .or
+    "MUL" .emit OP_MUL .or
+    "SGE" .emit OP_SGE .or
+    "SLT" .emit OP_SLT .or
+    "SUB" .emit OP_SUB .or
+    "XPD" .emit OP_XPD;
+
+/*
+fragment program
+    <TRIop_instruction>    ::= <TRIop> <maskedDstReg> ","
+                               <vectorSrcReg> "," <vectorSrcReg> ","
+                               <vectorSrcReg>
+
+vertex program
+    <TRIop_instruction>    ::= <TRIop> <maskedDstReg> ","
+                               <swizzleSrcReg> "," <swizzleSrcReg> ","
+                               <swizzleSrcReg>
+*/
+fp_TRIop_instruction
+    fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
+    vectorSrcReg .and comma .and vectorSrcReg;
+vp_TRIop_instruction
+    vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and
+    swizzleSrcReg .and comma .and swizzleSrcReg;
+
+/*
+fragment program
+    <TRIop>                ::= "CMP" | "CMP_SAT"
+                             | "LRP" | "LRP_SAT"
+                             | "MAD" | "MAD_SAT"
+
+vertex program
+    <TRIop>                ::= "MAD"
+*/
+fp_TRIop
+    "CMP" .emit OP_CMP .or "CMP_SAT" .emit OP_CMP_SAT .or
+    "LRP" .emit OP_LRP .or "LRP_SAT" .emit OP_LRP_SAT .or
+    "MAD" .emit OP_MAD .or "MAD_SAT" .emit OP_MAD_SAT;
+vp_TRIop
+    "MAD" .emit OP_MAD;
+
+/*
+fragment program
+    <SWZ_instruction>      ::= <SWZop> <maskedDstReg> "," 
+                               <srcReg> "," <extendedSwizzle>
+
+vertex program
+    <SWZ_instruction>      ::= "SWZ" <maskedDstReg> "," <srcReg> "," 
+                               <extendedSwizzle>
+*/
+fp_SWZ_instruction
+    SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and
+    fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
+vp_SWZ_instruction
+    "SWZ" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and
+    vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+    <SWZop>                ::= "SWZ" | "SWZ_SAT"
+*/
+SWZop
+    "SWZ" .emit OP_SWZ .or "SWZ_SAT" .emit OP_SWZ_SAT;
+
+/*
+fragment program
+    <SAMPLE_instruction>   ::= <SAMPLEop> <maskedDstReg> ","
+                               <vectorSrcReg> "," <texImageUnit> "," 
+                               <texTarget>
+*/
+SAMPLE_instruction
+    SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and
+    texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;
+
+/*
+fragment program
+    <SAMPLEop>             ::= "TEX" | "TEX_SAT"
+                             | "TXP" | "TXP_SAT"
+                             | "TXB" | "TXB_SAT"
+*/
+SAMPLEop
+    "TEX" .emit OP_TEX .or "TEX_SAT" .emit OP_TEX_SAT .or
+    "TXB" .emit OP_TXB .or "TXB_SAT" .emit OP_TXB_SAT .or
+    "TXP" .emit OP_TXP .or "TXP_SAT" .emit OP_TXP_SAT;
+
+/*
+fragment program
+    <KIL_instruction>      ::= "KIL" <vectorSrcReg>
+*/
+KIL_instruction
+    "KIL" .emit OP_KIL .and space_src .and vectorSrcReg;
+
+/*
+fragment program
+    <texImageUnit>         ::= "texture" <optTexImageUnitNum>
+*/
+texImageUnit
+    "texture" .error TEXTURE_EXPECTED .and optTexImageUnitNum;
+
+/*
+fragment program
+    <texTarget>            ::= "1D"
+                             | "2D"
+                             | "3D"
+                             | "CUBE"
+                             | "RECT"
+                             | <shadowTarget> (if option ARB_fragment_program_shadow present)
+*/
+texTarget
+    "1D" .emit TEXTARGET_1D .or
+    "2D" .emit TEXTARGET_2D .or
+    "3D" .emit TEXTARGET_3D .or
+    .if (texture_rectangle != 0x00) "RECT" .emit TEXTARGET_RECT .or
+    "CUBE" .emit TEXTARGET_CUBE .or
+    .if (ARB_fragment_program_shadow != 0x00) shadowTarget;
+
+/*
+GL_ARB_fragment_program_shadow
+    <shadowTarget>         ::= "SHADOW1D"
+                             | "SHADOW2D"
+                             | "SHADOWRECT"
+*/
+shadowTarget
+    "SHADOW1D" .emit TEXTARGET_SHADOW1D .or
+    "SHADOW2D" .emit TEXTARGET_SHADOW2D .or
+    .if (texture_rectangle != 0x00) "SHADOWRECT" .emit TEXTARGET_SHADOWRECT;
+
+/*
+fragment program
+    <optTexImageUnitNum>   ::= ""
+                             | "[" <texImageUnitNum> "]"
+*/
+optTexImageUnitNum
+    optTexImageUnitNum_1 .or .true .emit 0x00;
+optTexImageUnitNum_1
+    lbracket_ne .and texImageUnitNum .and rbracket;
+
+/*
+fragment program
+    <texImageUnitNum>      ::= <integer> from 0 to 
+                               MAX_TEXTURE_IMAGE_UNITS_ARB-1
+*/
+texImageUnitNum
+    integer;
+
+/*
+    <scalarSrcReg>         ::= <optionalSign> <srcReg> <scalarSuffix>
+*/
+fp_scalarSrcReg
+    optionalSign .and fp_srcReg .and fp_scalarSuffix;
+vp_scalarSrcReg
+    optionalSign .and vp_srcReg .and vp_scalarSuffix;
+
+/*
+vertex program
+    <swizzleSrcReg>        ::= <optionalSign> <srcReg> <swizzleSuffix>
+*/
+swizzleSrcReg
+    optionalSign .and vp_srcReg .and swizzleSuffix;
+
+/*
+fragment program
+    <vectorSrcReg>         ::= <optionalSign> <srcReg> <optionalSuffix> 
+*/
+vectorSrcReg
+    optionalSign .and fp_srcReg .and optionalSuffix;
+
+/*
+    <maskedDstReg>         ::= <dstReg> <optionalMask>
+*/
+fp_maskedDstReg
+    fp_dstReg .and fp_optionalMask;
+vp_maskedDstReg
+    vp_dstReg .and vp_optionalMask;
+
+/*
+vertex program
+    <maskedAddrReg>        ::= <addrReg> <addrWriteMask>
+*/
+maskedAddrReg
+    addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;
+
+/*
+fragment program
+    <extendedSwizzle>      ::= <xyzwExtendedSwizzle>
+                             | <rgbaExtendedSwizzle>
+
+vertex program
+    <extendedSwizzle>      ::= <extSwizComp> "," <extSwizComp> "," 
+                                 <extSwizComp> "," <extSwizComp>
+
+NOTE: do NOT change the order of <rgbaExtendedSwizzle> and <xyzwExtendedSwizzle> rulez
+*/
+fp_extendedSwizzle
+    rgbaExtendedSwizzle .or xyzwExtendedSwizzle;
+vp_extendedSwizzle
+    extSwizComp .and comma .and
+    extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    extSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+    <xyzwExtendedSwizzle>  ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> "," 
+                               <xyzwExtSwizComp> "," <xyzwExtSwizComp>
+*/
+xyzwExtendedSwizzle
+    xyzwExtSwizComp .and comma .and
+    xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+    <rgbaExtendedSwizzle>  ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> "," 
+                               <rgbaExtSwizComp> "," <rgbaExtSwizComp>
+*/
+rgbaExtendedSwizzle
+    rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or
+    rgbaExtendedSwizzle_4;
+rgbaExtendedSwizzle_1
+    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
+    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;
+rgbaExtendedSwizzle_2
+    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and
+    rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+rgbaExtendedSwizzle_3
+    rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and
+    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+rgbaExtendedSwizzle_4
+    rgbaExtSwizComp_alpha .and comma .and 
+    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and
+    rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;
+
+/*
+fragment program
+    <xyzwExtSwizComp>      ::= <optionalSign> <xyzwExtSwizSel>
+*/
+xyzwExtSwizComp
+    optionalSign .and xyzwExtSwizSel;
+
+/*
+fragment program
+    <rgbaExtSwizComp>      ::= <optionalSign> <rgbaExtSwizSel>
+*/
+rgbaExtSwizComp
+    optionalSign .and rgbaExtSwizSel;
+rgbaExtSwizComp_digit
+    optionalSign .and rgbaExtSwizSel_digit;
+rgbaExtSwizComp_alpha
+    optionalSign .and rgbaExtSwizSel_alpha;
+
+/*
+vertex program
+    <extSwizComp>          ::= <optionalSign> <extSwizSel>
+*/
+extSwizComp
+    optionalSign .and extSwizSel;
+
+/*
+fragment program
+    <xyzwExtSwizSel>       ::= "0" 
+                             | "1" 
+                             | <xyzwComponent>
+*/
+xyzwExtSwizSel
+    "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or xyzwComponent_single;
+
+/*
+fragment program
+    <rgbaExtSwizSel>       ::= "0" 
+                             | "1" 
+                             | <rgbaComponent>
+*/
+rgbaExtSwizSel
+    rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;
+rgbaExtSwizSel_digit
+    "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1;
+rgbaExtSwizSel_alpha
+    rgbaComponent_single;
+
+/*
+vertex program
+    <extSwizSel>           ::= "0" 
+                             | "1" 
+                             | <component>
+*/
+extSwizSel
+    "0" .emit COMPONENT_0 .or "1" .emit COMPONENT_1 .or vp_component_single;
+
+/*
+fragment program
+    <srcReg>               ::= <fragmentAttribReg>
+                             | <temporaryReg>
+                             | <progParamReg>
+
+vertex program
+    <srcReg>               ::= <vertexAttribReg>
+                             | <temporaryReg>
+                             | <progParamReg>
+*/
+fp_srcReg
+    fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
+vp_srcReg
+    vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;
+fp_srcReg_1
+    fragmentAttribReg .emit REGISTER_ATTRIB .or
+    fp_progParamReg .emit REGISTER_PARAM .or
+    fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+vp_srcReg_1
+    vertexAttribReg .emit REGISTER_ATTRIB .or
+    vp_progParamReg .emit REGISTER_PARAM .or
+    vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+
+/*
+fragment program
+    <dstReg>               ::= <temporaryReg>
+                             | <fragmentResultReg>
+
+vertex program
+    <dstReg>               ::= <temporaryReg>
+                             | <vertexResultReg>
+*/
+fp_dstReg
+    fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
+vp_dstReg
+    vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;
+fp_dstReg_1
+    fragmentResultReg .emit REGISTER_RESULT .or
+    fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+vp_dstReg_1
+    vertexResultReg .emit REGISTER_RESULT .or
+    vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;
+
+/*
+fragment program
+    <fragmentAttribReg>    ::= <establishedName>
+                             | <fragAttribBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
+*/
+fragmentAttribReg
+    /*fp_establishedName .or */fragAttribBinding;
+
+/*
+vertex program
+    <vertexAttribReg>      ::= <establishedName>
+                             | <vtxAttribBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
+*/
+vertexAttribReg
+    vtxAttribBinding;
+
+/*
+    <temporaryReg>         ::= <establishedName>
+*/
+fp_temporaryReg
+    fp_establishedName_no_error_on_identifier;
+vp_temporaryReg
+    vp_establishedName_no_error_on_identifier;
+
+/*
+fragment program
+    <progParamReg>         ::= <progParamSingle>
+                             | <progParamArray> "[" <progParamArrayAbs> "]"
+                             | <paramSingleItemUse>
+
+vertex program
+    <progParamReg>         ::= <progParamSingle>
+                             | <progParamArray> "[" <progParamArrayMem> "]"
+                             | <paramSingleItemUse>
+*/
+fp_progParamReg
+    fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;
+vp_progParamReg
+    vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;
+fp_progParamReg_1
+    fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and
+    rbracket;
+vp_progParamReg_1
+    vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and
+    rbracket;
+
+/*
+    <progParamSingle>      ::= <establishedName>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <srcReg>
+*/
+fp_progParamSingle
+    .false;
+vp_progParamSingle
+    .false;
+
+/*
+    <progParamArray>       ::= <establishedName>
+*/
+fp_progParamArray
+    fp_establishedName_no_error_on_identifier;
+vp_progParamArray
+    vp_establishedName_no_error_on_identifier;
+
+/*
+vertex program
+    <progParamArrayMem>    ::= <progParamArrayAbs>
+                             | <progParamArrayRel>
+*/
+progParamArrayMem
+    progParamArrayAbs .or progParamArrayRel;
+
+/*
+    <progParamArrayAbs>    ::= <integer>
+*/
+progParamArrayAbs
+    integer_ne .emit ARRAY_INDEX_ABSOLUTE;
+
+/*
+vertex program
+    <progParamArrayRel>    ::= <addrReg> <addrComponent> <addrRegRelOffset>
+*/
+progParamArrayRel
+    addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and
+    addrComponent .and addrRegRelOffset;
+
+/*
+vertex program
+    <addrRegRelOffset>     ::= ""
+                             | "+" <addrRegPosOffset>
+                             | "-" <addrRegNegOffset>
+*/
+addrRegRelOffset
+    addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;
+addrRegRelOffset_1
+    plus_ne .and addrRegPosOffset;
+addrRegRelOffset_2
+    minus_ne .and addrRegNegOffset;
+
+/*
+vertex program
+    <addrRegPosOffset>     ::= <integer> from 0 to 63
+*/
+addrRegPosOffset
+    integer_0_63;
+
+/*
+vertex program
+    <addrRegNegOffset>     ::= <integer> from 0 to 64
+*/
+addrRegNegOffset
+    integer_0_64;
+
+/*
+fragment program
+    <fragmentResultReg>    ::= <establishedName>
+                             | <resultBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
+*/
+fragmentResultReg
+    fp_resultBinding;
+
+/*
+vertex program
+    <vertexResultReg>      ::= <establishedName>
+                             | <resultBinding>
+
+NOTE: <establishedName> is driven by <temporaryReg> rule at the end of <dstReg>
+*/
+vertexResultReg
+    vp_resultBinding;
+
+/*
+vertex program
+    <addrReg>              ::= <establishedName>
+*/
+addrReg
+    vp_establishedName_no_error_on_identifier;
+
+/*
+vertex program
+    <addrComponent>        ::= "." "x"
+*/
+addrComponent
+    dot .and "x" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X
+    .emit COMPONENT_X .emit COMPONENT_X;
+
+/*
+vertex program
+    <addrWriteMask>        ::= "." "x"
+*/
+addrWriteMask
+    dot .and "x" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;
+
+/*
+    <scalarSuffix>         ::= "." <component>
+*/
+fp_scalarSuffix
+    dot .and fp_component_single .error INVALID_COMPONENT;
+vp_scalarSuffix
+    dot .and vp_component_single .error INVALID_COMPONENT;
+
+/*
+vertex program
+    <swizzleSuffix>        ::= ""
+                             | "." <component>
+                             | "." <component> <component>
+                                   <component> <component>
+*/
+swizzleSuffix
+    swizzleSuffix_1 .or
+    .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
+swizzleSuffix_1
+    dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;
+swizzleSuffix_2
+    swizzleSuffix_3 .or swizzleSuffix_4;
+swizzleSuffix_3
+    vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and
+    vp_component_multi .error INVALID_COMPONENT;
+swizzleSuffix_4
+    "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
+    "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
+    "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
+    "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
+
+/*
+fragment program
+    <optionalSuffix>       ::= "" 
+                             | "." <component> 
+                             | "." <xyzwComponent> <xyzwComponent>
+                                   <xyzwComponent> <xyzwComponent>
+                             | "." <rgbaComponent> <rgbaComponent>
+                                   <rgbaComponent> <rgbaComponent>
+*/
+optionalSuffix
+    optionalSuffix_1 .or
+    .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;
+optionalSuffix_1
+    dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;
+optionalSuffix_2
+    optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;
+optionalSuffix_3
+    xyzwComponent_multi .and xyzwComponent_multi .and
+    xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;
+optionalSuffix_4
+    rgbaComponent_multi .and rgbaComponent_multi .and
+    rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;
+optionalSuffix_5
+    "x" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
+    "y" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
+    "z" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
+    "w" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or
+    "r" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or
+    "g" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or
+    "b" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or
+    "a" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;
+
+/*
+fragment program
+    <component>            ::= <xyzwComponent>
+                             | <rgbaComponent>
+
+vertex program
+    <component>            ::= "x"
+                             | "y"
+                             | "z"
+                             | "w"
+*/
+fp_component_single
+    xyzwComponent_single .or rgbaComponent_single;
+vp_component_multi
+    'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
+    'w' .emit COMPONENT_W;
+vp_component_single
+    "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
+    "w" .emit COMPONENT_W;
+
+/*
+fragment program
+    <xyzwComponent>        ::= "x" | "y" | "z" | "w"
+*/
+xyzwComponent_multi
+    'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or
+    'w' .emit COMPONENT_W;
+xyzwComponent_single
+    "x" .emit COMPONENT_X .or "y" .emit COMPONENT_Y .or "z" .emit COMPONENT_Z .or
+    "w" .emit COMPONENT_W;
+
+/*
+fragment program
+    <rgbaComponent>        ::= "r" | "g" | "b" | "a"
+*/
+rgbaComponent_multi
+    'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or
+    'a' .emit COMPONENT_W;
+rgbaComponent_single
+    "r" .emit COMPONENT_X .or "g" .emit COMPONENT_Y .or "b" .emit COMPONENT_Z .or
+    "a" .emit COMPONENT_W;
+
+/*
+fragment program
+    <optionalMask>         ::= ""
+                             | <xyzwMask>
+                             | <rgbaMask>
+
+vertex program
+    <optionalMask>         ::= ""
+                             | "." "x"
+                             | "." "y"
+                             | "." "xy"
+                             | "." "z"
+                             | "." "xz"
+                             | "." "yz"
+                             | "." "xyz"
+                             | "." "w"
+                             | "." "xw"
+                             | "." "yw"
+                             | "." "xyw"
+                             | "." "zw"
+                             | "." "xzw"
+                             | "." "yzw"
+                             | "." "xyzw"
+
+NOTE: do NOT change the order of <rgbaMask> and <xyzwMask> rulez
+*/
+fp_optionalMask
+    rgbaMask .or xyzwMask .or .true .emit 0x0F;
+vp_optionalMask
+    xyzwMask .or .true .emit 0x0F;
+
+/*
+fragment program
+    <xyzwMask>             ::= "." "x"
+                             | "." "y"
+                             | "." "xy"
+                             | "." "z"
+                             | "." "xz"
+                             | "." "yz"
+                             | "." "xyz"
+                             | "." "w"
+                             | "." "xw"
+                             | "." "yw"
+                             | "." "xyw"
+                             | "." "zw"
+                             | "." "xzw"
+                             | "." "yzw"
+                             | "." "xyzw"
+
+NOTE: <xyzwMask> is also referenced by the vertex program symbol <optionalMask>.
+*/
+xyzwMask
+    dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;
+xyzwMask_1
+    "xyzw" .emit 0x0F .or "xyz" .emit 0x0E .or "xyw" .emit 0x0D .or "xy" .emit 0x0C .or
+    "xzw" .emit 0x0B .or "xz" .emit 0x0A .or "xw" .emit 0x09 .or "x" .emit 0x08 .or
+    "yzw" .emit 0x07 .or "yz" .emit 0x06 .or "yw" .emit 0x05 .or "y" .emit 0x04 .or
+    "zw" .emit 0x03 .or "z" .emit 0x02 .or "w" .emit 0x01;
+
+/*
+fragment program
+    <rgbaMask>             ::= "." "r"
+                             | "." "g"
+                             | "." "rg"
+                             | "." "b"
+                             | "." "rb"
+                             | "." "gb"
+                             | "." "rgb"
+                             | "." "a"
+                             | "." "ra"
+                             | "." "ga"
+                             | "." "rga"
+                             | "." "ba"
+                             | "." "rba"
+                             | "." "gba"
+                             | "." "rgba"
+*/
+rgbaMask
+    dot_ne .and rgbaMask_1;
+rgbaMask_1
+    "rgba" .emit 0x0F .or "rgb" .emit 0x0E .or "rga" .emit 0x0D .or "rg" .emit 0x0C .or
+    "rba" .emit 0x0B .or "rb" .emit 0x0A .or "ra" .emit 0x09 .or "r" .emit 0x08 .or
+    "gba" .emit 0x07 .or "gb" .emit 0x06 .or "ga" .emit 0x05 .or "g" .emit 0x04 .or
+    "ba" .emit 0x03 .or "b" .emit 0x02 .or "a" .emit 0x01;
+
+/*
+fragment program
+    <namingStatement>      ::= <ATTRIB_statement>
+                             | <PARAM_statement>
+                             | <TEMP_statement>
+                             | <OUTPUT_statement>
+                             | <ALIAS_statement>
+
+vertex program
+    <namingStatement>      ::= <ATTRIB_statement>
+                             | <PARAM_statement>
+                             | <TEMP_statement>
+                             | <ADDRESS_statement>
+                             | <OUTPUT_statement>
+                             | <ALIAS_statement>
+*/
+fp_namingStatement
+    fp_ATTRIB_statement .emit ATTRIB .or
+    fp_PARAM_statement .emit PARAM .or
+    fp_TEMP_statement .emit TEMP .or
+    fp_OUTPUT_statement .emit OUTPUT .or
+    fp_ALIAS_statement .emit ALIAS;
+vp_namingStatement
+    vp_ATTRIB_statement .emit ATTRIB .or
+    vp_PARAM_statement .emit PARAM .or
+    vp_TEMP_statement .emit TEMP .or
+    ADDRESS_statement .emit ADDRESS .or
+    vp_OUTPUT_statement .emit OUTPUT .or
+    vp_ALIAS_statement .emit ALIAS;
+
+/*
+fragment program
+    <ATTRIB_statement>     ::= "ATTRIB" <establishName> "="
+                                 <fragAttribBinding>
+
+vertex program
+    <ATTRIB_statement>     ::= "ATTRIB" <establishName> "="
+                                 <vtxAttribBinding>
+*/
+fp_ATTRIB_statement
+    "ATTRIB" .and space .and fp_establishName .and equal .and
+    fragAttribBinding .error FRAGMENT_EXPECTED;
+vp_ATTRIB_statement
+    "ATTRIB" .and space .and vp_establishName .and equal .and
+    vtxAttribBinding .error VERTEX_EXPECTED;
+
+/*
+fragment program
+    <fragAttribBinding>    ::= "fragment" "." <fragAttribItem>
+*/
+fragAttribBinding
+    "fragment" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;
+
+/*
+vertex program
+    <vtxAttribBinding>     ::= "vertex" "." <vtxAttribItem>
+*/
+vtxAttribBinding
+    "vertex" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;
+
+/*
+fragment program
+    <fragAttribItem>       ::= "color" <optColorType>
+                             | "texcoord" <optTexCoordNum>
+                             | "fogcoord"
+                             | "position"
+*/
+fragAttribItem
+    fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or
+    fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or
+    .if (fog_coord != 0x00) "fogcoord" .emit FRAGMENT_ATTRIB_FOGCOORD .or
+    "position" .emit FRAGMENT_ATTRIB_POSITION;
+fragAttribItem_1
+    "color" .and optColorType;
+fragAttribItem_2
+    "texcoord" .and optTexCoordNum;
+
+/*
+vertex program
+    <vtxAttribItem>        ::= "position"
+                             | "weight" <vtxOptWeightNum>
+                             | "normal"
+                             | "color" <optColorType>
+                             | "fogcoord"
+                             | "texcoord" <optTexCoordNum>
+                             | "matrixindex" "[" <vtxWeightNum> "]"
+                             | "attrib" "[" <vtxAttribNum> "]"
+*/
+vtxAttribItem
+    "position" .emit VERTEX_ATTRIB_POSITION .or
+    .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or
+    "normal" .emit VERTEX_ATTRIB_NORMAL .or
+    vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or
+    "fogcoord" .emit VERTEX_ATTRIB_FOGCOORD .or
+    vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or
+    .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or
+    vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;
+vtxAttribItem_1
+    "weight" .and vtxOptWeightNum;
+vtxAttribItem_2
+    "color" .and optColorType;
+vtxAttribItem_3
+    "texcoord" .and optTexCoordNum;
+vtxAttribItem_4
+    "matrixindex" .and lbracket .and vtxWeightNum .and rbracket;
+vtxAttribItem_5
+    "attrib" .and lbracket .and vtxAttribNum .and rbracket;
+
+/*
+vertex program
+    <vtxAttribNum>         ::= <integer> from 0 to MAX_VERTEX_ATTRIBS_ARB-1
+*/
+vtxAttribNum
+    integer;
+
+/*
+vertex program
+    <vtxOptWeightNum>      ::= ""
+                             | "[" <vtxWeightNum> "]"
+*/
+vtxOptWeightNum
+    vtxOptWeightNum_1 .or .true .emit 0x00;
+vtxOptWeightNum_1
+    lbracket_ne .and vtxWeightNum .and rbracket;
+
+/*
+vertex program
+    <vtxWeightNum>         ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1,
+                                 must be divisible by four
+*/
+vtxWeightNum
+    integer;
+
+/*
+    <PARAM_statement>      ::= <PARAM_singleStmt>
+                             | <PARAM_multipleStmt>
+*/
+fp_PARAM_statement
+    fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;
+vp_PARAM_statement
+    vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;
+
+/*
+    <PARAM_singleStmt>     ::= "PARAM" <establishName> <paramSingleInit>
+*/
+fp_PARAM_singleStmt
+    "PARAM" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and
+    .true .emit PARAM_NULL;
+vp_PARAM_singleStmt
+    "PARAM" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and
+    .true .emit PARAM_NULL;
+
+/*
+    <PARAM_multipleStmt>   ::= "PARAM" <establishName> "[" <optArraySize> "]"
+                                   <paramMultipleInit>
+*/
+fp_PARAM_multipleStmt
+    "PARAM" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
+    fp_paramMultipleInit .and .true .emit PARAM_NULL;
+vp_PARAM_multipleStmt
+    "PARAM" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and
+    vp_paramMultipleInit .and .true .emit PARAM_NULL;
+
+/*
+    <optArraySize>         ::= ""
+                             | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB
+                                 (maximum number of allowed program 
+                                  parameter bindings)
+*/
+optArraySize
+    optional_integer;
+
+/*
+    <paramSingleInit>      ::= "=" <paramSingleItemDecl>
+*/
+fp_paramSingleInit
+    equal .and fp_paramSingleItemDecl;
+vp_paramSingleInit
+    equal .and vp_paramSingleItemDecl;
+
+/*
+    <paramMultipleInit>    ::= "=" "{" <paramMultInitList> "}"
+*/
+fp_paramMultipleInit
+    equal .and lbrace .and fp_paramMultInitList .and rbrace;
+vp_paramMultipleInit
+    equal .and lbrace .and vp_paramMultInitList .and rbrace;
+
+/*
+    <paramMultInitList>    ::= <paramMultipleItem>
+                             | <paramMultipleItem> "," <paramMultiInitList>
+*/
+fp_paramMultInitList
+    fp_paramMultInitList_1 .or fp_paramMultipleItem;
+vp_paramMultInitList
+    vp_paramMultInitList_1 .or vp_paramMultipleItem;
+fp_paramMultInitList_1
+    fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;
+vp_paramMultInitList_1
+    vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;
+
+/*
+    <paramSingleItemDecl>  ::= <stateSingleItem>
+                             | <programSingleItem>
+                             | <paramConstDecl>
+*/
+fp_paramSingleItemDecl
+    fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+    paramConstDecl .emit PARAM_CONSTANT;
+vp_paramSingleItemDecl
+    vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+    paramConstDecl .emit PARAM_CONSTANT;
+
+/*
+    <paramSingleItemUse>   ::= <stateSingleItem>
+                             | <programSingleItem>
+                             | <paramConstUse>
+*/
+fp_paramSingleItemUse
+    fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+    paramConstUse .emit PARAM_CONSTANT;
+vp_paramSingleItemUse
+    vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or
+    programSingleItem .emit PARAM_PROGRAM_ELEMENT .or
+    paramConstUse .emit PARAM_CONSTANT;
+
+/*
+    <paramMultipleItem>    ::= <stateMultipleItem>
+                             | <programMultipleItem>
+                             | <paramConstDecl>
+*/
+fp_paramMultipleItem
+    fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
+    programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
+    paramConstDecl .emit PARAM_CONSTANT;
+vp_paramMultipleItem
+    vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or
+    programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or
+    paramConstDecl .emit PARAM_CONSTANT;
+
+/*
+    <stateMultipleItem>    ::= <stateSingleItem>
+                             | "state" "." <stateMatrixRows>
+*/
+fp_stateMultipleItem
+    stateMultipleItem_1 .or fp_stateSingleItem;
+vp_stateMultipleItem
+    stateMultipleItem_1 .or vp_stateSingleItem;
+stateMultipleItem_1
+    "state" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;
+
+/*
+fragment program
+    <stateSingleItem>      ::= "state" "." <stateMaterialItem>
+                             | "state" "." <stateLightItem>
+                             | "state" "." <stateLightModelItem>
+                             | "state" "." <stateLightProdItem>
+                             | "state" "." <stateTexEnvItem>
+                             | "state" "." <stateFogItem>
+                             | "state" "." <stateDepthItem>
+                             | "state" "." <stateMatrixRow>
+
+vertex program
+    <stateSingleItem>      ::= "state" "." <stateMaterialItem>
+                             | "state" "." <stateLightItem>
+                             | "state" "." <stateLightModelItem>
+                             | "state" "." <stateLightProdItem>
+                             | "state" "." <stateTexGenItem>
+                             | "state" "." <stateFogItem>
+                             | "state" "." <stateClipPlaneItem>
+                             | "state" "." <statePointItem>
+                             | "state" "." <stateMatrixRow>
+*/
+fp_stateSingleItem
+    "state" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
+vp_stateSingleItem
+    "state" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;
+fp_stateSingleItem_1
+    stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
+    stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;
+vp_stateSingleItem_1
+    stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or
+    stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or
+    stateSingleItem_11;
+stateSingleItem_1
+    stateMaterialItem .emit STATE_MATERIAL;
+stateSingleItem_2
+    stateLightItem .emit STATE_LIGHT;
+stateSingleItem_3
+    stateLightModelItem .emit STATE_LIGHT_MODEL;
+stateSingleItem_4
+    stateLightProdItem .emit STATE_LIGHT_PROD;
+stateSingleItem_5
+    stateTexEnvItem .emit STATE_TEX_ENV;
+stateSingleItem_6
+    stateTexGenItem .emit STATE_TEX_GEN;
+stateSingleItem_7
+    stateFogItem .emit STATE_FOG;
+stateSingleItem_8
+    stateDepthItem .emit STATE_DEPTH;
+stateSingleItem_9
+    stateClipPlaneItem .emit STATE_CLIP_PLANE;
+stateSingleItem_10
+    statePointItem .emit STATE_POINT;
+stateSingleItem_11
+    stateMatrixRow .emit STATE_MATRIX_ROWS;
+
+/*
+    <stateMaterialItem>    ::= "material" <optFaceType> "." <stateMatProperty>
+*/
+stateMaterialItem
+    "material" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;
+
+/*
+    <stateMatProperty>     ::= "ambient"
+                             | "diffuse"
+                             | "specular"
+                             | "emission"
+                             | "shininess"
+*/
+stateMatProperty
+    "ambient" .emit MATERIAL_AMBIENT .or
+    "diffuse" .emit MATERIAL_DIFFUSE .or
+    "specular" .emit MATERIAL_SPECULAR .or
+    "emission" .emit MATERIAL_EMISSION .or
+    "shininess" .emit MATERIAL_SHININESS;
+
+/*
+    <stateLightItem>       ::= "light" "[" <stateLightNumber> "]" "." 
+                                 <stateLightProperty>
+*/
+stateLightItem
+    "light" .and lbracket .and stateLightNumber .and rbracket .and dot .and
+    stateLightProperty .error INVALID_LIGHT_PROPERTY;
+
+/*
+    <stateLightProperty>   ::= "ambient"
+                             | "diffuse" 
+                             | "specular"
+                             | "position"
+                             | "attenuation"
+                             | "spot" "." <stateSpotProperty>
+                             | "half"
+*/
+stateLightProperty
+    "ambient" .emit LIGHT_AMBIENT .or
+    "diffuse" .emit LIGHT_DIFFUSE .or
+    "specular" .emit LIGHT_SPECULAR .or
+    "position" .emit LIGHT_POSITION .or
+    "attenuation" .emit LIGHT_ATTENUATION .or
+    stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or
+    "half" .emit LIGHT_HALF;
+stateLightProperty_1
+    "spot" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;
+
+/*
+    <stateSpotProperty>    ::= "direction" 
+*/
+stateSpotProperty
+    "direction";
+
+/*
+    <stateLightModelItem>  ::= "lightmodel" <stateLModProperty>
+*/
+stateLightModelItem
+    "lightmodel" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;
+
+/*
+    <stateLModProperty>    ::= "." "ambient"
+                             | <optFaceType> "." "scenecolor"
+*/
+stateLModProperty
+    stateLModProperty_1 .or stateLModProperty_2;
+stateLModProperty_1
+    dot .and "ambient" .emit LIGHT_MODEL_AMBIENT;
+stateLModProperty_2
+    stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;
+stateLModProperty_3
+    optFaceType .and dot .and "scenecolor";
+
+/*
+    <stateLightProdItem>   ::= "lightprod" "[" <stateLightNumber> "]"
+                                 <optFaceType> "." <stateLProdProperty>
+*/
+stateLightProdItem
+    "lightprod" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and
+    stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;
+
+/*
+    <stateLProdProperty>   ::= "ambient"
+                             | "diffuse"
+                             | "specular"
+*/
+stateLProdProperty
+    "ambient" .emit LIGHT_PROD_AMBIENT .or
+    "diffuse" .emit LIGHT_PROD_DIFFUSE .or
+    "specular" .emit LIGHT_PROD_SPECULAR;
+
+/*
+    <stateLightNumber>     ::= <integer> from 0 to MAX_LIGHTS-1
+*/
+stateLightNumber
+    integer;
+
+/*
+fragment program
+    <stateTexEnvItem>      ::= "texenv" <optLegacyTexUnitNum> "." 
+                                 <stateTexEnvProperty>
+*/
+stateTexEnvItem
+    "texenv" .and optLegacyTexUnitNum .and dot .and
+    stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;
+
+/*
+fragment program
+    <stateTexEnvProperty>  ::= "color"
+*/
+stateTexEnvProperty
+    "color" .emit TEX_ENV_COLOR;
+
+/*
+fragment program
+    <optLegacyTexUnitNum>  ::= ""
+                             | "[" <legacyTexUnitNum> "]"
+
+NOTE: <optLegaceTexUnitNum> is not optional.
+*/
+optLegacyTexUnitNum
+    lbracket_ne .and legacyTexUnitNum .and rbracket;
+
+/*
+fragment program
+    <legacyTexUnitNum>     ::= <integer> from 0 to MAX_TEXTURE_UNITS-1
+*/
+legacyTexUnitNum
+    integer;
+
+/*
+vertex program
+    <stateTexGenItem>      ::= "texgen" <optTexCoordNum> "."
+                                 <stateTexGenType> "." <stateTexGenCoord>
+*/
+stateTexGenItem
+    "texgen" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and
+    dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;
+
+/*
+vertex program
+    <stateTexGenType>      ::= "eye"
+                             | "object"
+*/
+stateTexGenType
+    "eye" .emit TEX_GEN_EYE .or
+    "object" .emit TEX_GEN_OBJECT;
+
+/*
+vertex program
+    <stateTexGenCoord>     ::= "s"
+                             | "t"
+                             | "r"
+                             | "q"
+*/
+stateTexGenCoord
+    "s" .emit COMPONENT_X .or
+    "t" .emit COMPONENT_Y .or
+    "r" .emit COMPONENT_Z .or
+    "q" .emit COMPONENT_W;
+
+/*
+    <stateFogItem>         ::= "fog" "." <stateFogProperty>
+*/
+stateFogItem
+    "fog" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;
+
+/*
+    <stateFogProperty>     ::= "color"
+                             | "params"
+*/
+stateFogProperty
+    "color" .emit FOG_COLOR .or
+    "params" .emit FOG_PARAMS;
+
+/*
+fragment program
+    <stateDepthItem>       ::= "depth" "." <stateDepthProperty>
+*/
+stateDepthItem
+    "depth" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;
+
+/*
+fragment program
+    <stateDepthProperty>   ::= "range"
+*/
+stateDepthProperty
+    "range" .emit DEPTH_RANGE;
+
+/*
+vertex program
+    <stateClipPlaneItem>   ::= "clip" "[" <stateClipPlaneNum> "]" "." "plane"
+*/
+stateClipPlaneItem
+    "clip" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and
+    "plane" .error INVALID_CLIPPLANE_PROPERTY;
+
+/*
+vertex program
+    <stateClipPlaneNum>    ::= <integer> from 0 to MAX_CLIP_PLANES-1
+*/
+stateClipPlaneNum
+    integer;
+
+/*
+vertex program
+    <statePointItem>       ::= "point" . <statePointProperty>
+*/
+statePointItem
+    "point" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;
+
+/*
+vertex program
+    <statePointProperty>   ::= "size"
+                             | "attenuation"
+*/
+statePointProperty
+    "size" .emit POINT_SIZE .or
+    .if (point_parameters != 0x00) "attenuation" .emit POINT_ATTENUATION;
+
+/*
+    <stateMatrixRow>       ::= <stateMatrixItem> "." "row" "[" 
+                                  <stateMatrixRowNum> "]"
+*/
+stateMatrixRow
+    stateMatrixItem .and dot .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and
+    lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;
+
+/*
+    <stateMatrixRows>      ::= <stateMatrixItem> <optMatrixRows>
+*/
+stateMatrixRows
+    stateMatrixItem .and optMatrixRows;
+
+/*
+    <optMatrixRows>        ::= ""
+                             | "." "row" "[" <stateMatrixRowNum> ".." 
+                                  <stateMatrixRowNum> "]"
+*/
+optMatrixRows
+    optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;
+optMatrixRows_1
+    dot_ne .and "row" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and
+    stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;
+
+/*
+    <stateMatrixItem>      ::= "matrix" . <stateMatrixName> 
+                               <stateOptMatModifier>
+*/
+stateMatrixItem
+    "matrix" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;
+
+/*
+    <stateOptMatModifier>  ::= ""
+                             | "." <stateMatModifier>
+*/
+stateOptMatModifier
+    stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;
+stateOptMatModifier_1
+    dot_ne .and stateMatModifier;
+
+/*
+    <stateMatModifier>     ::= "inverse" 
+                             | "transpose" 
+                             | "invtrans"
+*/
+stateMatModifier
+    "inverse" .emit MATRIX_MODIFIER_INVERSE .or
+    "transpose" .emit MATRIX_MODIFIER_TRANSPOSE .or
+    "invtrans" .emit MATRIX_MODIFIER_INVTRANS;
+
+/*
+    <stateMatrixRowNum>    ::= <integer> from 0 to 3
+*/
+stateMatrixRowNum
+    integer_0_3;
+
+/*
+    <stateMatrixName>      ::= "modelview" <stateOptModMatNum>
+                             | "projection"
+                             | "mvp"
+                             | "texture" <optTexCoordNum>
+                             | "palette" "[" <statePaletteMatNum> "]"
+                             | "program" "[" <stateProgramMatNum> "]"
+*/
+stateMatrixName
+    stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or
+    "projection" .emit MATRIX_PROJECTION .or
+    "mvp" .emit MATRIX_MVP .or
+    stateMatrixName_1_2 .emit MATRIX_TEXTURE .or
+    .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or
+    stateMatrixName_1_4 .emit MATRIX_PROGRAM;
+stateMatrixName_1_1
+    "modelview" .and stateOptModMatNum;
+stateMatrixName_1_2
+    "texture" .and optTexCoordNum;
+stateMatrixName_1_3
+    "palette" .and lbracket .and statePaletteMatNum .and rbracket;
+stateMatrixName_1_4
+    "program" .and lbracket .and stateProgramMatNum .and rbracket;
+
+/*
+    <stateOptModMatNum>    ::= ""
+                             | "[" <stateModMatNum> "]"
+*/
+stateOptModMatNum
+    .if (vertex_blend != 0x00) stateOptModMatNum_1 .or
+    .true .emit 0x00;
+stateOptModMatNum_1
+    lbracket_ne .and stateModMatNum .and rbracket;
+
+/*
+    <stateModMatNum>       ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1
+*/
+stateModMatNum
+    integer;
+
+/*
+    <optTexCoordNum>       ::= ""
+                             | "[" <texCoordNum> "]"
+*/
+optTexCoordNum
+    optTexCoordNum_1 .or .true .emit 0x00;
+optTexCoordNum_1
+    lbracket_ne .and texCoordNum .and rbracket;
+
+/*
+    <texCoordNum>          ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1
+*/
+texCoordNum
+    integer;
+
+/*
+    <statePaletteMatNum>   ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1
+*/
+statePaletteMatNum
+    integer;
+
+/*
+    <stateProgramMatNum>   ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1
+*/
+stateProgramMatNum
+    integer;
+
+/*
+    <programSingleItem>    ::= <progEnvParam>
+                             | <progLocalParam>
+
+NOTE: <programSingleItem> has been modified for correct error handling. If program property
+      is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
+*/
+programSingleItem
+    "program" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;
+programSingleItem_1
+    progEnvParam .or progLocalParam;
+
+/*
+    <programMultipleItem>  ::= <progEnvParams>
+                             | <progLocalParams>
+
+NOTE: <programMultipleItem> has been modified for correct error handling. If program property
+      is neither "env" nor "local" INVALID_PROGRAM_PROPERTY is generated.
+*/
+programMultipleItem
+    "program" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;
+programMultipleItem_1
+    progEnvParams .or progLocalParams;
+
+/*
+    <progEnvParams>        ::= "program" "." "env" 
+                                 "[" <progEnvParamNums> "]"
+
+NOTE: "program" "." has been moved to <programMultipleItem>.
+*/
+progEnvParams
+    "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;
+
+/*
+    <progEnvParamNums>     ::= <progEnvParamNum>
+                             | <progEnvParamNum> ".." <progEnvParamNum>
+*/
+progEnvParamNums
+    progEnvParamNums_1 .or progEnvParamNums_2;
+progEnvParamNums_1
+    progEnvParamNum .and dotdot_ne .and progEnvParamNum;
+progEnvParamNums_2
+    progEnvParamNum .and .true .emit 0x00;
+
+/*
+    <progEnvParam>         ::= "program" "." "env" 
+                                 "[" <progEnvParamNum> "]"
+
+NOTE: "program" "." has been moved to <programSingleItem>.
+*/
+progEnvParam
+    "env" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;
+
+/*
+    <progLocalParams>      ::= "program" "." "local" 
+                                 "[" <progLocalParamNums> "]"
+
+NOTE: "program" "." has been moved to <programMultipleItem>.
+*/
+progLocalParams
+    "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;
+
+/*
+    <progLocalParamNums>   ::= <progLocalParamNum>
+                             | <progLocalParamNum> ".." <progLocalParamNum>
+*/
+progLocalParamNums
+    progLocalParamNums_1 .or progLocalParamNums_2;
+progLocalParamNums_1
+    progLocalParamNum .and dotdot_ne .and progLocalParamNum;
+progLocalParamNums_2
+    progLocalParamNum .and .true .emit 0x00;
+
+/*
+    <progLocalParam>       ::= "program" "." "local" 
+                                 "[" <progLocalParamNum> "]"
+
+NOTE: "program" "." has been moved to <programSingleItem>.
+*/
+progLocalParam
+    "local" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;
+
+/*
+    <progEnvParamNum>      ::= <integer> from 0 to
+                               MAX_PROGRAM_ENV_PARAMETERS_ARB - 1
+*/
+progEnvParamNum
+    integer;
+
+/*
+    <progLocalParamNum>    ::= <integer> from 0 to
+                               MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1
+*/
+progLocalParamNum
+    integer;
+
+/*
+    <paramConstDecl>       ::= <paramConstScalarDecl>
+                             | <paramConstVector>
+*/
+paramConstDecl
+    paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
+
+/*
+    <paramConstUse>        ::= <paramConstScalarUse>
+                             | <paramConstVector>
+*/
+paramConstUse
+    paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;
+
+/*
+    <paramConstScalarDecl> ::= <signedFloatConstant>
+*/
+paramConstScalarDecl
+    signedFloatConstant;
+
+/*
+    <paramConstScalarUse>  ::= <floatConstant>
+*/
+paramConstScalarUse
+    floatConstant;
+
+/*
+    <paramConstVector>     ::= "{" <signedFloatConstant> "}"
+                             | "{" <signedFloatConstant> "," 
+                                   <signedFloatConstant> "}"
+                             | "{" <signedFloatConstant> "," 
+                                   <signedFloatConstant> ","
+                                   <signedFloatConstant> "}"
+                             | "{" <signedFloatConstant> "," 
+                                   <signedFloatConstant> ","
+                                   <signedFloatConstant> "," 
+                                   <signedFloatConstant> "}"
+*/
+paramConstVector
+    paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or
+    paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;
+paramConstVector_1
+    lbrace_ne .and signedFloatConstant .and rbrace;
+paramConstVector_2
+    lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
+paramConstVector_3
+    lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
+    signedFloatConstant .and rbrace;
+paramConstVector_4
+    lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and
+    signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;
+
+/*
+    <signedFloatConstant>  ::= <optionalSign> <floatConstant>
+*/
+signedFloatConstant
+    optionalSign .and floatConstant;
+
+/*
+    <floatConstant>        ::= see text
+    The <floatConstant> rule matches a floating-point constant consisting
+    of an integer part, a decimal point, a fraction part, an "e" or
+    "E", and an optionally signed integer exponent.  The integer and
+    fraction parts both consist of a sequence of one or more digits ("0"
+    through "9").  Either the integer part or the fraction parts (not
+    both) may be missing; either the decimal point or the "e" (or "E")
+    and the exponent (not both) may be missing.
+*/
+floatConstant
+    float;
+
+/*
+    <optionalSign>         ::= ""
+                             | "-"
+                             | "+"
+*/
+optionalSign
+    optional_sign_ne;
+
+/*
+    <TEMP_statement>       ::= "TEMP" <varNameList>
+*/
+fp_TEMP_statement
+    "TEMP" .and space .and fp_varNameList .and .true .emit 0x00;
+vp_TEMP_statement
+    "TEMP" .and space .and vp_varNameList .and .true .emit 0x00;
+
+/*
+vertex program
+    <ADDRESS_statement>    ::= "ADDRESS" <varNameList>
+*/
+ADDRESS_statement
+    "ADDRESS" .and space .and vp_varNameList .and .true .emit 0x00;
+
+/*
+    <varNameList>          ::= <establishName>
+                             | <establishName> "," <varNameList>
+*/
+fp_varNameList
+    fp_varNameList_1 .or fp_establishName;
+vp_varNameList
+    vp_varNameList_1 .or vp_establishName;
+fp_varNameList_1
+    fp_establishName .and comma_ne .and fp_varNameList;
+vp_varNameList_1
+    vp_establishName .and comma_ne .and vp_varNameList;
+
+/*
+    <OUTPUT_statement>     ::= "OUTPUT" <establishName> "="
+                                 <resultBinding>
+*/
+fp_OUTPUT_statement
+    "OUTPUT" .and space .and fp_establishName .and equal .and
+    fp_resultBinding .error RESULT_EXPECTED;
+vp_OUTPUT_statement
+    "OUTPUT" .and space .and vp_establishName .and equal .and
+    vp_resultBinding .error RESULT_EXPECTED;
+
+/*
+fragment program
+    <resultBinding>        ::= "result" "." "color"
+                             | "result" "." "depth"
+
+vertex program
+    <resultBinding>        ::= "result" "." "position"
+                             | "result" "." <resultColBinding>
+                             | "result" "." "fogcoord"
+                             | "result" "." "pointsize"
+                             | "result" "." "texcoord" <optTexCoordNum>
+*/
+fp_resultBinding
+    "result" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
+vp_resultBinding
+    "result" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;
+fp_resultBinding_1
+    "color" .emit FRAGMENT_RESULT_COLOR .or
+    "depth" .emit FRAGMENT_RESULT_DEPTH;
+vp_resultBinding_1
+    .if (ARB_position_invariant == 0x00) "position" .emit VERTEX_RESULT_POSITION .or
+    resultColBinding .emit VERTEX_RESULT_COLOR .or
+    "fogcoord" .emit VERTEX_RESULT_FOGCOORD .or
+    "pointsize" .emit VERTEX_RESULT_POINTSIZE .or
+    vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;
+vp_resultBinding_2
+    "texcoord" .and optTexCoordNum;
+
+/*
+vertex program
+    <resultColBinding>     ::= "color" <optFaceType> <optColorType>
+*/
+resultColBinding
+    "color" .and optFaceType .and optColorType;
+
+/*
+    <optFaceType>          ::= ""
+                             | "." "front"
+                             | "." "back"
+*/
+optFaceType
+    FaceType .or .true .emit FACE_FRONT;
+FaceType
+    dot_ne .and FaceProperty;
+FaceProperty
+    "front" .emit FACE_FRONT .or "back" .emit FACE_BACK;
+
+/*
+    <optColorType>         ::= ""
+                             | "." "primary"
+                             | "." "secondary"
+*/
+optColorType
+    ColorType .or .true .emit COLOR_PRIMARY;
+ColorType
+    dot_ne .and ColorProperty;
+ColorProperty
+    "primary" .emit COLOR_PRIMARY .or
+    .if (secondary_color != 0x00) "secondary" .emit COLOR_SECONDARY;
+
+/*
+    <ALIAS_statement>      ::= "ALIAS" <establishName> "="
+                                 <establishedName>
+*/
+fp_ALIAS_statement
+    "ALIAS" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;
+vp_ALIAS_statement
+    "ALIAS" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;
+fp_ALIAS_statement_1
+    space .and fp_establishName;
+vp_ALIAS_statement_1
+    space .and vp_establishName;
+
+/*
+    <establishName>        ::= <identifier>
+*/
+fp_establishName
+    fp_identifier;
+vp_establishName
+    vp_identifier;
+
+/*
+    <establishedName>      ::= <identifier>
+*/
+fp_establishedName
+    fp_identifier;
+vp_establishedName
+    vp_identifier;
+fp_establishedName_no_error_on_identifier
+    fp_identifier_ne;
+vp_establishedName_no_error_on_identifier
+    vp_identifier_ne;
+
+/*
+fragment program
+    <identifier>           ::= see text
+    The <identifier> rule matches a sequence of one or more letters ("A"
+    through "Z", "a" through "z"), digits ("0" through "9), underscores 
+    ("_"), or dollar signs ("$"); the first character must not be a 
+    number.  Upper and lower case letters are considered different 
+    (names are case-sensitive).  The following strings are reserved 
+    keywords and may not be used as identifiers:
+
+        ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,
+        COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT, 
+        END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2, 
+        LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT, 
+        MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM, 
+        POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS, 
+        SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT, 
+        TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT, 
+        fragment, program, result, state, and texture.
+
+vertex program
+    <identifier>           ::= see text
+    The <identifier> rule matches a sequence of one or more letters ("A"
+    through "Z", "a" through "z"), digits ("0" through "9), underscores ("_"),
+    or dollar signs ("$"); the first character must not be a number.  Upper
+    and lower case letters are considered different (names are
+    case-sensitive).  The following strings are reserved keywords and may not
+    be used as identifiers:
+
+        ABS, ADD, ADDRESS, ALIAS, ARL, ATTRIB, DP3, DP4, DPH, DST, END, EX2,
+        EXP, FLR, FRC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, OPTION, OUTPUT,
+        PARAM, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, TEMP, XPD, program, result,
+        state, and vertex.
+*/
+fp_identifier
+    fp_identifier_ne .error IDENTIFIER_EXPECTED;
+vp_identifier
+    vp_identifier_ne .error IDENTIFIER_EXPECTED;
+fp_identifier_ne
+    fp_not_reserved_identifier .and identifier_ne;
+vp_identifier_ne
+    vp_not_reserved_identifier .and identifier_ne;
+
+fp_not_reserved_identifier
+    fp_not_reserved_identifier_1 .or .true;
+fp_not_reserved_identifier_1
+    fp_reserved_identifier .and .false .error RESERVED_KEYWORD;
+vp_not_reserved_identifier
+    vp_not_reserved_identifier_1 .or .true;
+vp_not_reserved_identifier_1
+    vp_reserved_identifier .and .false .error RESERVED_KEYWORD;
+
+fp_reserved_identifier
+    "ABS" .or "ABS_SAT" .or "ADD" .or "ADD_SAT" .or "ALIAS" .or "ATTRIB" .or "CMP" .or "CMP_SAT" .or
+    "COS" .or "COS_SAT" .or "DP3" .or "DP3_SAT" .or "DP4" .or "DP4_SAT" .or "DPH" .or "DPH_SAT" .or
+    "DST" .or "DST_SAT" .or "END" .or "EX2" .or "EX2_SAT" .or "FLR" .or "FLR_SAT" .or "FRC" .or
+    "FRC_SAT" .or "KIL" .or "LG2" .or "LG2_SAT" .or "LIT" .or "LIT_SAT" .or "LRP" .or "LRP_SAT" .or
+    "MAD" .or "MAD_SAT" .or "MAX" .or "MAX_SAT" .or "MIN" .or "MIN_SAT" .or "MOV" .or "MOV_SAT" .or
+    "MUL" .or "MUL_SAT" .or "OPTION" .or "OUTPUT" .or "PARAM" .or "POW" .or "POW_SAT" .or "RCP" .or
+    "RCP_SAT" .or "RSQ" .or "RSQ_SAT" .or "SIN" .or "SIN_SAT" .or "SCS" .or "SCS_SAT" .or "SGE" .or
+    "SGE_SAT" .or "SLT" .or "SLT_SAT" .or "SUB" .or "SUB_SAT" .or "SWZ" .or "SWZ_SAT" .or "TEMP" .or
+    "TEX" .or "TEX_SAT" .or "TXB" .or "TXB_SAT" .or "TXP" .or "TXP_SAT" .or "XPD" .or "XPD_SAT" .or
+    "fragment" .or "program" .or "result" .or "state" .or "texture";
+vp_reserved_identifier
+    "ABS" .or "ADD" .or "ADDRESS" .or "ALIAS" .or "ARL" .or "ATTRIB" .or "DP3" .or "DP4" .or
+    "DPH" .or "DST" .or "END" .or "EX2" .or "EXP" .or "FLR" .or "FRC" .or "LG2" .or "LIT" .or
+    "LOG" .or "MAD" .or "MAX" .or "MIN" .or "MOV" .or "MUL" .or "OPTION" .or "OUTPUT" .or
+    "PARAM" .or "POW" .or "RCP" .or "RSQ" .or "SGE" .or "SLT" .or "SUB" .or "SWZ" .or "TEMP" .or
+    "XPD" .or "program" .or "result" .or "state" .or "vertex";
+
+/*
+    The <integer> rule matches an integer constant.  The integer consists
+    of a sequence of one or more digits ("0" through "9").
+*/
+integer
+    integer_ne .error INTEGER_EXPECTED;
+
+zero
+    '0';
+
+leading_zeroes
+    .loop zero;
+
+no_digit
+    no_digit_1 .or .true;
+no_digit_1
+    digit10 .and .false .error INTEGER_OUT_OF_RANGE;
+
+all_zeroes
+    all_zeroes_1 .or no_digit_1;
+all_zeroes_1
+    '0' .and .loop zero .and no_digit;
+
+integer_0_3
+    integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
+integer_0_3_1
+    integer_0_3_2 .or all_zeroes .emit '0';
+integer_0_3_2       /* [1, 3] */
+    leading_zeroes .and '1'-'3' .emit * .and no_digit;
+
+integer_0_63
+    integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
+integer_0_63_1
+    integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or
+    all_zeroes .emit '0';
+integer_0_63_2      /* [7, 9] */
+    leading_zeroes .and '7'-'9' .emit * .and no_digit;
+integer_0_63_3      /* [10, 59] */
+    leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
+integer_0_63_4      /* [60, 63] */
+    leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;
+integer_0_63_5      /* [1, 6] */
+    leading_zeroes .and '1'-'6' .emit * .and no_digit;
+
+integer_0_64
+    integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;
+integer_0_64_1
+    integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or
+    all_zeroes .emit '0';
+integer_0_64_2      /* [7, 9] */
+    leading_zeroes .and '7'-'9' .emit * .and no_digit;
+integer_0_64_3      /* [10, 59] */
+    leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;
+integer_0_64_4      /* [60, 64] */
+    leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;
+integer_0_64_5      /* [1, 6] */
+    leading_zeroes .and '1'-'6' .emit * .and no_digit;
+
+optional_space
+    space .or .true;
+
+space_dst
+    space .error OPERATION_NEEDS_DESTINATION_VARIABLE;
+
+space_src
+    space .error OPERATION_NEEDS_SOURCE_VARIABLE;
+
+space
+    single_space .and .loop single_space;
+
+single_space
+    white_char .or comment_block;
+
+white_char
+    ' ' .or '\t' .or '\n' .or '\r';
+
+comment_block
+    '#' .and .loop comment_char .and new_line;
+
+/* All ASCII characters except '\r', '\n' and '\0' */
+comment_char
+    '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+new_line
+    '\n' .or crlf .or '\0';
+
+crlf
+    '\r' .and '\n';
+
+semicolon
+    optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;
+
+comma
+    optional_space .and ',' .error MISSING_COMMA .and optional_space;
+
+comma_ne
+    optional_space .and ',' .and optional_space;
+
+lbracket
+    optional_space .and '[' .error MISSING_LBRACKET .and optional_space;
+
+lbracket_ne
+    optional_space .and '[' .and optional_space;
+
+rbracket
+    optional_space .and ']' .error MISSING_RBRACKET .and optional_space;
+
+dot
+    optional_space .and '.' .error MISSING_DOT .and optional_space;
+
+dot_ne
+    optional_space .and '.' .and optional_space;
+
+equal
+    optional_space .and '=' .error MISSING_EQUAL .and optional_space;
+
+lbrace
+    optional_space .and '{' .error MISSING_LBRACE .and optional_space;
+
+lbrace_ne
+    optional_space .and '{' .and optional_space;
+
+rbrace
+    optional_space .and '}' .error MISSING_RBRACE .and optional_space;
+
+dotdot
+    optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;
+
+dotdot_ne
+    optional_space .and '.' .and '.' .and optional_space;
+
+/*
+    The definition below accepts the following floating point number formats:
+    .99 .99e99 99. 99.99 99.99e99 99.e99 99e99
+    Also 99 format was considered and accepted because of a large number of existing program
+    strings with such a format.
+*/
+float
+    float_1 .or float_2 .or float_legacy;
+float_1
+    '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
+float_2
+    integer_ne .and float_3;
+float_3
+    float_4 .or float_5;
+float_4
+    '.' .and optional_integer .and optional_exponent;
+float_5
+    exponent .emit 0x00;
+float_legacy
+    integer_ne .and .true .emit 0x00 .emit 0x00;
+
+/*
+    Below is a correct version of <float> definiton.
+*/
+/*
+float
+    float_1 .or float_2;
+float_1
+    '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;
+float_2
+    integer_ne .and float_3 .error MISSING_DOT_OR_EXPONENT;
+float_3
+    float_4 .or float_5;
+float_4
+    '.' .and optional_integer .and optional_exponent;
+float_5
+    exponent .emit 0x00;
+*/
+
+integer_ne
+    integer_ne_1 .and .true .emit 0x00 .emit $;
+integer_ne_1
+    digit10 .emit * .and .loop digit10 .emit *;
+
+optional_integer
+    integer_ne .or .true .emit 0x00;
+
+/*
+NOTE: If exponent part is omited we treat it as if it was "E+1".
+*/
+optional_exponent
+    exponent .or .true .emit 0x00;
+
+exponent
+    exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;
+exponent_1
+    'e' .or 'E';
+
+optional_sign_ne
+    minus_ne .or plus_ne .or .true;
+
+plus_ne
+    optional_space .and '+' .and optional_space;
+
+minus_ne
+    optional_space .and '-' .emit '-' .and optional_space;
+
+identifier_ne
+    first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;
+
+follow_idchar
+    first_idchar .or digit10;
+
+first_idchar
+    'a'-'z' .or 'A'-'Z' .or '_' .or '$';
+
+digit10
+    '0'-'9';
+
+/*
+    string filtering - if a string is encountered in grammar ("blabla"), the symbol below is
+    executed to create the string. The symbol must not throw any errors and emit bytes - it should
+    stop if it encounters invalid character. After this the resulting string (from starting
+    position up to the invalid character (but without it) is compared with the grammar string.
+*/
+.string __string_filter;
+
+__string_filter
+    .loop __identifier_char;
+
+__identifier_char
+    'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';
+
+/*
+    error token filtering
+*/
+e_signature
+    e_signature_char .and .loop e_signature_char;
+e_signature_char
+    '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';
+
+e_statement
+    .loop e_statement_not_term;
+/* All ASCII characters to one of '\r', '\n', '\0' and ';' */
+e_statement_not_term
+    '\x3C'-'\xFF' .or '\x0E'-'\x3A' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+e_identifier
+    e_identifier_first .and .loop e_identifier_next;
+e_identifier_first
+    'a'-'z' .or 'A'-'Z' .or '_' .or '$';
+e_identifier_next
+    e_identifier_first .or '0'-'9';
+
+e_token
+    e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or
+    '-' .or ',' .or ';';
+e_token_number
+    e_token_digit .and .loop e_token_digit;
+e_token_digit
+    '0'-'9';
+
+e_charordigit
+    'A'-'Z' .or 'a'-'z' .or '0'-'9';
+
diff --git a/src/mesa/shader/arbprogram_syn.h b/src/mesa/shader/arbprogram_syn.h
index fe89b5f..71ccd20 100644
--- a/src/mesa/shader/arbprogram_syn.h
+++ b/src/mesa/shader/arbprogram_syn.h
@@ -1,1314 +1,1344 @@
-".syntax program;\n"

-".emtcode REVISION 0x07\n"

-".emtcode FRAGMENT_PROGRAM 0x01\n"

-".emtcode VERTEX_PROGRAM 0x02\n"

-".emtcode OPTION 0x01\n"

-".emtcode INSTRUCTION 0x02\n"

-".emtcode DECLARATION 0x03\n"

-".emtcode END 0x04\n"

-".emtcode ARB_PRECISION_HINT_FASTEST 0x01\n"

-".emtcode ARB_PRECISION_HINT_NICEST 0x02\n"

-".emtcode ARB_FOG_EXP 0x04\n"

-".emtcode ARB_FOG_EXP2 0x08\n"

-".emtcode ARB_FOG_LINEAR 0x10\n"

-".emtcode ARB_POSITION_INVARIANT 0x20\n"

-".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40\n"

-".emtcode OP_ALU_INST 0x00\n"

-".emtcode OP_TEX_INST 0x01\n"

-".emtcode OP_ALU_VECTOR 0x00\n"

-".emtcode OP_ALU_SCALAR 0x01\n"

-".emtcode OP_ALU_BINSC 0x02\n"

-".emtcode OP_ALU_BIN 0x03\n"

-".emtcode OP_ALU_TRI 0x04\n"

-".emtcode OP_ALU_SWZ 0x05\n"

-".emtcode OP_TEX_SAMPLE 0x06\n"

-".emtcode OP_TEX_KIL 0x07\n"

-".emtcode OP_ALU_ARL 0x08\n"

-".emtcode OP_ABS 0x00\n"

-".emtcode OP_ABS_SAT 0x1B\n"

-".emtcode OP_FLR 0x09\n"

-".emtcode OP_FLR_SAT 0x26\n"

-".emtcode OP_FRC 0x0A\n"

-".emtcode OP_FRC_SAT 0x27\n"

-".emtcode OP_LIT 0x0C\n"

-".emtcode OP_LIT_SAT 0x2A\n"

-".emtcode OP_MOV 0x11\n"

-".emtcode OP_MOV_SAT 0x30\n"

-".emtcode OP_COS 0x1F\n"

-".emtcode OP_COS_SAT 0x20\n"

-".emtcode OP_EX2 0x07\n"

-".emtcode OP_EX2_SAT 0x25\n"

-".emtcode OP_LG2 0x0B\n"

-".emtcode OP_LG2_SAT 0x29\n"

-".emtcode OP_RCP 0x14\n"

-".emtcode OP_RCP_SAT 0x33\n"

-".emtcode OP_RSQ 0x15\n"

-".emtcode OP_RSQ_SAT 0x34\n"

-".emtcode OP_SIN 0x38\n"

-".emtcode OP_SIN_SAT 0x39\n"

-".emtcode OP_SCS 0x35\n"

-".emtcode OP_SCS_SAT 0x36\n"

-".emtcode OP_POW 0x13\n"

-".emtcode OP_POW_SAT 0x32\n"

-".emtcode OP_ADD 0x01\n"

-".emtcode OP_ADD_SAT 0x1C\n"

-".emtcode OP_DP3 0x03\n"

-".emtcode OP_DP3_SAT 0x21\n"

-".emtcode OP_DP4 0x04\n"

-".emtcode OP_DP4_SAT 0x22\n"

-".emtcode OP_DPH 0x05\n"

-".emtcode OP_DPH_SAT 0x23\n"

-".emtcode OP_DST 0x06\n"

-".emtcode OP_DST_SAT 0x24\n"

-".emtcode OP_MAX 0x0F\n"

-".emtcode OP_MAX_SAT 0x2E\n"

-".emtcode OP_MIN 0x10\n"

-".emtcode OP_MIN_SAT 0x2F\n"

-".emtcode OP_MUL 0x12\n"

-".emtcode OP_MUL_SAT 0x31\n"

-".emtcode OP_SGE 0x16\n"

-".emtcode OP_SGE_SAT 0x37\n"

-".emtcode OP_SLT 0x17\n"

-".emtcode OP_SLT_SAT 0x3A\n"

-".emtcode OP_SUB 0x18\n"

-".emtcode OP_SUB_SAT 0x3B\n"

-".emtcode OP_XPD 0x1A\n"

-".emtcode OP_XPD_SAT 0x43\n"

-".emtcode OP_CMP 0x1D\n"

-".emtcode OP_CMP_SAT 0x1E\n"

-".emtcode OP_LRP 0x2B\n"

-".emtcode OP_LRP_SAT 0x2C\n"

-".emtcode OP_MAD 0x0E\n"

-".emtcode OP_MAD_SAT 0x2D\n"

-".emtcode OP_SWZ 0x19\n"

-".emtcode OP_SWZ_SAT 0x3C\n"

-".emtcode OP_TEX 0x3D\n"

-".emtcode OP_TEX_SAT 0x3E\n"

-".emtcode OP_TXB 0x3F\n"

-".emtcode OP_TXB_SAT 0x40\n"

-".emtcode OP_TXP 0x41\n"

-".emtcode OP_TXP_SAT 0x42\n"

-".emtcode OP_KIL 0x28\n"

-".emtcode OP_ARL 0x02\n"

-".emtcode OP_EXP 0x08\n"

-".emtcode OP_LOG 0x0D\n"

-".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n"

-".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n"

-".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n"

-".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n"

-".emtcode VERTEX_ATTRIB_POSITION 0x01\n"

-".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n"

-".emtcode VERTEX_ATTRIB_NORMAL 0x03\n"

-".emtcode VERTEX_ATTRIB_COLOR 0x04\n"

-".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n"

-".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n"

-".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n"

-".emtcode VERTEX_ATTRIB_GENERIC 0x08\n"

-".emtcode FRAGMENT_RESULT_COLOR 0x01\n"

-".emtcode FRAGMENT_RESULT_DEPTH 0x02\n"

-".emtcode VERTEX_RESULT_POSITION 0x01\n"

-".emtcode VERTEX_RESULT_COLOR 0x02\n"

-".emtcode VERTEX_RESULT_FOGCOORD 0x03\n"

-".emtcode VERTEX_RESULT_POINTSIZE 0x04\n"

-".emtcode VERTEX_RESULT_TEXCOORD 0x05\n"

-".emtcode TEXTARGET_1D 0x01\n"

-".emtcode TEXTARGET_2D 0x02\n"

-".emtcode TEXTARGET_3D 0x03\n"

-".emtcode TEXTARGET_RECT 0x04\n"

-".emtcode TEXTARGET_CUBE 0x05\n"

-".emtcode TEXTARGET_SHADOW1D 0x06\n"

-".emtcode TEXTARGET_SHADOW2D 0x07\n"

-".emtcode TEXTARGET_SHADOWRECT 0x08\n"

-".emtcode FACE_FRONT 0x00\n"

-".emtcode FACE_BACK 0x01\n"

-".emtcode COLOR_PRIMARY 0x00\n"

-".emtcode COLOR_SECONDARY 0x01\n"

-".emtcode COMPONENT_X 0x00\n"

-".emtcode COMPONENT_Y 0x01\n"

-".emtcode COMPONENT_Z 0x02\n"

-".emtcode COMPONENT_W 0x03\n"

-".emtcode COMPONENT_0 0x04\n"

-".emtcode COMPONENT_1 0x05\n"

-".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n"

-".emtcode ARRAY_INDEX_RELATIVE 0x01\n"

-".emtcode MATRIX_MODELVIEW 0x01\n"

-".emtcode MATRIX_PROJECTION 0x02\n"

-".emtcode MATRIX_MVP 0x03\n"

-".emtcode MATRIX_TEXTURE 0x04\n"

-".emtcode MATRIX_PALETTE 0x05\n"

-".emtcode MATRIX_PROGRAM 0x06\n"

-".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n"

-".emtcode MATRIX_MODIFIER_INVERSE 0x01\n"

-".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n"

-".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n"

-".emtcode CONSTANT_SCALAR 0x01\n"

-".emtcode CONSTANT_VECTOR 0x02\n"

-".emtcode PROGRAM_PARAM_ENV 0x01\n"

-".emtcode PROGRAM_PARAM_LOCAL 0x02\n"

-".emtcode REGISTER_ATTRIB 0x01\n"

-".emtcode REGISTER_PARAM 0x02\n"

-".emtcode REGISTER_RESULT 0x03\n"

-".emtcode REGISTER_ESTABLISHED_NAME 0x04\n"

-".emtcode PARAM_NULL 0x00\n"

-".emtcode PARAM_ARRAY_ELEMENT 0x01\n"

-".emtcode PARAM_STATE_ELEMENT 0x02\n"

-".emtcode PARAM_PROGRAM_ELEMENT 0x03\n"

-".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n"

-".emtcode PARAM_CONSTANT 0x05\n"

-".emtcode STATE_MATERIAL 0x01\n"

-".emtcode STATE_LIGHT 0x02\n"

-".emtcode STATE_LIGHT_MODEL 0x03\n"

-".emtcode STATE_LIGHT_PROD 0x04\n"

-".emtcode STATE_FOG 0x05\n"

-".emtcode STATE_MATRIX_ROWS 0x06\n"

-".emtcode STATE_TEX_ENV 0x07\n"

-".emtcode STATE_DEPTH 0x08\n"

-".emtcode STATE_TEX_GEN 0x09\n"

-".emtcode STATE_CLIP_PLANE 0x0A\n"

-".emtcode STATE_POINT 0x0B\n"

-".emtcode MATERIAL_AMBIENT 0x01\n"

-".emtcode MATERIAL_DIFFUSE 0x02\n"

-".emtcode MATERIAL_SPECULAR 0x03\n"

-".emtcode MATERIAL_EMISSION 0x04\n"

-".emtcode MATERIAL_SHININESS 0x05\n"

-".emtcode LIGHT_AMBIENT 0x01\n"

-".emtcode LIGHT_DIFFUSE 0x02\n"

-".emtcode LIGHT_SPECULAR 0x03\n"

-".emtcode LIGHT_POSITION 0x04\n"

-".emtcode LIGHT_ATTENUATION 0x05\n"

-".emtcode LIGHT_HALF 0x06\n"

-".emtcode LIGHT_SPOT_DIRECTION 0x07\n"

-".emtcode LIGHT_MODEL_AMBIENT 0x01\n"

-".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n"

-".emtcode LIGHT_PROD_AMBIENT 0x01\n"

-".emtcode LIGHT_PROD_DIFFUSE 0x02\n"

-".emtcode LIGHT_PROD_SPECULAR 0x03\n"

-".emtcode TEX_ENV_COLOR 0x01\n"

-".emtcode TEX_GEN_EYE 0x01\n"

-".emtcode TEX_GEN_OBJECT 0x02\n"

-".emtcode FOG_COLOR 0x01\n"

-".emtcode FOG_PARAMS 0x02\n"

-".emtcode DEPTH_RANGE 0x01\n"

-".emtcode POINT_SIZE 0x01\n"

-".emtcode POINT_ATTENUATION 0x02\n"

-".emtcode ATTRIB 0x01\n"

-".emtcode PARAM 0x02\n"

-".emtcode TEMP 0x03\n"

-".emtcode OUTPUT 0x04\n"

-".emtcode ALIAS 0x05\n"

-".emtcode ADDRESS 0x06\n"

-".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n"

-".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n"

-".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n"

-".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n"

-".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n"

-".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n"

-".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n"

-".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n"

-".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n"

-".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n"

-".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n"

-".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n"

-".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n"

-".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n"

-".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n"

-".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n"

-".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n"

-".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n"

-".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n"

-".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n"

-".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n"

-".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n"

-".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n"

-".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n"

-".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n"

-".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n"

-".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n"

-".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n"

-".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n"

-".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n"

-".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n"

-".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n"

-".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n"

-".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n"

-".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n"

-".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n"

-".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n"

-".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n"

-".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n"

-".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n"

-".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n"

-".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n"

-".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n"

-".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n"

-".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n"

-".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n"

-".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n"

-".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n"

-".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n"

-".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n"

-".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n"

-".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n"

-".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n"

-".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n"

-".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n"

-".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n"

-".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n"

-".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n"

-".regbyte vertex_blend 0x00\n"

-".regbyte matrix_palette 0x00\n"

-".regbyte point_parameters 0x01\n"

-".regbyte secondary_color 0x01\n"

-".regbyte fog_coord 0x01\n"

-".regbyte texture_rectangle 0x01\n"

-".regbyte fragment_program_shadow 0x00\n"

-".regbyte ARB_precision_hint_fastest 0x00\n"

-".regbyte ARB_precision_hint_nicest 0x00\n"

-".regbyte ARB_fog_exp 0x00\n"

-".regbyte ARB_fog_exp2 0x00\n"

-".regbyte ARB_fog_linear 0x00\n"

-".regbyte ARB_position_invariant 0x00\n"

-".regbyte ARB_fragment_program_shadow 0x00\n"

-".regbyte program_target 0x00\n"

-"program\n"

-" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n"

-"programs\n"

-" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n"

-" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n"

-"frag_program_1_0\n"

-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n"

-" optional_space .and fp_optionSequence .and fp_statementSequence .and\n"

-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"

-" '\\0' .error CODE_AFTER_END;\n"

-"vert_program_1_0\n"

-" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n"

-" optional_space .and vp_optionSequence .and vp_statementSequence .and\n"

-" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"

-" '\\0' .error CODE_AFTER_END;\n"

-"fp_optionSequence\n"

-" .loop fp_option;\n"

-"vp_optionSequence\n"

-" .loop vp_option;\n"

-"fp_option\n"

-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"

-" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"

-"vp_option\n"

-" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"

-" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"

-"fp_optionString\n"

-" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n"

-" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n"

-" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n"

-" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n"

-" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n"

-" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n"

-" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n"

-" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n"

-" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;\n"

-"vp_optionString\n"

-" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n"

-"fp_ARB_fog_exp\n"

-" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n"

-"fp_ARB_fog_exp2\n"

-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n"

-"fp_ARB_fog_linear\n"

-" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n"

-"fp_statementSequence\n"

-" .loop fp_statement;\n"

-"vp_statementSequence\n"

-" .loop vp_statement;\n"

-"fp_statement\n"

-" fp_statement_1 .or fp_statement_2;\n"

-"vp_statement\n"

-" vp_statement_1 .or vp_statement_2;\n"

-"fp_statement_1\n"

-" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"

-"fp_statement_2\n"

-" fp_namingStatement .emit DECLARATION .and semicolon;\n"

-"vp_statement_1\n"

-" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"

-"vp_statement_2\n"

-" vp_namingStatement .emit DECLARATION .and semicolon;\n"

-"fp_instruction\n"

-" ALUInstruction .emit OP_ALU_INST .or\n"

-" TexInstruction .emit OP_TEX_INST;\n"

-"vp_instruction\n"

-" ARL_instruction .emit OP_ALU_ARL .or\n"

-" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"

-" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"

-" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"

-" vp_BINop_instruction .emit OP_ALU_BIN .or\n"

-" vp_TRIop_instruction .emit OP_ALU_TRI .or\n"

-" vp_SWZ_instruction .emit OP_ALU_SWZ;\n"

-"ALUInstruction\n"

-" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"

-" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"

-" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"

-" fp_BINop_instruction .emit OP_ALU_BIN .or\n"

-" fp_TRIop_instruction .emit OP_ALU_TRI .or\n"

-" fp_SWZ_instruction .emit OP_ALU_SWZ;\n"

-"TexInstruction\n"

-" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n"

-" KIL_instruction .emit OP_TEX_KIL;\n"

-"ARL_instruction\n"

-" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n"

-"fp_VECTORop_instruction\n"

-" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n"

-"vp_VECTORop_instruction\n"

-" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n"

-"fp_VECTORop\n"

-" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n"

-" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n"

-" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n"

-" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n"

-" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n"

-"vp_VECTORop\n"

-" \"ABS\" .emit OP_ABS .or\n"

-" \"FLR\" .emit OP_FLR .or\n"

-" \"FRC\" .emit OP_FRC .or\n"

-" \"LIT\" .emit OP_LIT .or\n"

-" \"MOV\" .emit OP_MOV;\n"

-"fp_SCALARop_instruction\n"

-" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n"

-"vp_SCALARop_instruction\n"

-" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n"

-"fp_SCALARop\n"

-" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n"

-" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n"

-" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n"

-" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n"

-" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n"

-" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n"

-" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n"

-"vp_SCALARop\n"

-" \"EX2\" .emit OP_EX2 .or\n"

-" \"EXP\" .emit OP_EXP .or\n"

-" \"LG2\" .emit OP_LG2 .or\n"

-" \"LOG\" .emit OP_LOG .or\n"

-" \"RCP\" .emit OP_RCP .or\n"

-" \"RSQ\" .emit OP_RSQ;\n"

-"fp_BINSCop_instruction\n"

-" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n"

-" fp_scalarSrcReg;\n"

-"vp_BINSCop_instruction\n"

-" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n"

-" vp_scalarSrcReg;\n"

-"fp_BINSCop\n"

-" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n"

-"vp_BINSCop\n"

-" \"POW\" .emit OP_POW;\n"

-"fp_BINop_instruction\n"

-" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"

-" vectorSrcReg;\n"

-"vp_BINop_instruction\n"

-" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"

-" swizzleSrcReg;\n"

-"fp_BINop\n"

-" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n"

-" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n"

-" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n"

-" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n"

-" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n"

-" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n"

-" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n"

-" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n"

-" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n"

-" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n"

-" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n"

-" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n"

-"vp_BINop\n"

-" \"ADD\" .emit OP_ADD .or\n"

-" \"DP3\" .emit OP_DP3 .or\n"

-" \"DP4\" .emit OP_DP4 .or\n"

-" \"DPH\" .emit OP_DPH .or\n"

-" \"DST\" .emit OP_DST .or\n"

-" \"MAX\" .emit OP_MAX .or\n"

-" \"MIN\" .emit OP_MIN .or\n"

-" \"MUL\" .emit OP_MUL .or\n"

-" \"SGE\" .emit OP_SGE .or\n"

-" \"SLT\" .emit OP_SLT .or\n"

-" \"SUB\" .emit OP_SUB .or\n"

-" \"XPD\" .emit OP_XPD;\n"

-"fp_TRIop_instruction\n"

-" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"

-" vectorSrcReg .and comma .and vectorSrcReg;\n"

-"vp_TRIop_instruction\n"

-" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"

-" swizzleSrcReg .and comma .and swizzleSrcReg;\n"

-"fp_TRIop\n"

-" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n"

-" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n"

-" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n"

-"vp_TRIop\n"

-" \"MAD\" .emit OP_MAD;\n"

-"fp_SWZ_instruction\n"

-" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n"

-" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"

-"vp_SWZ_instruction\n"

-" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n"

-" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"

-"SWZop\n"

-" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n"

-"SAMPLE_instruction\n"

-" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"

-" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n"

-"SAMPLEop\n"

-" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n"

-" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n"

-" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n"

-"KIL_instruction\n"

-" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n"

-"texImageUnit\n"

-" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n"

-"texTarget\n"

-" \"1D\" .emit TEXTARGET_1D .or\n"

-" \"2D\" .emit TEXTARGET_2D .or\n"

-" \"3D\" .emit TEXTARGET_3D .or\n"

-" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n"

-" \"CUBE\" .emit TEXTARGET_CUBE .or\n"

-" .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\n"

-"shadowTarget\n"

-" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n"

-" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n"

-" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT;\n"

-"optTexImageUnitNum\n"

-" optTexImageUnitNum_1 .or .true .emit 0x00;\n"

-"optTexImageUnitNum_1\n"

-" lbracket_ne .and texImageUnitNum .and rbracket;\n"

-"texImageUnitNum\n"

-" integer;\n"

-"fp_scalarSrcReg\n"

-" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n"

-"vp_scalarSrcReg\n"

-" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n"

-"swizzleSrcReg\n"

-" optionalSign .and vp_srcReg .and swizzleSuffix;\n"

-"vectorSrcReg\n"

-" optionalSign .and fp_srcReg .and optionalSuffix;\n"

-"fp_maskedDstReg\n"

-" fp_dstReg .and fp_optionalMask;\n"

-"vp_maskedDstReg\n"

-" vp_dstReg .and vp_optionalMask;\n"

-"maskedAddrReg\n"

-" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n"

-"fp_extendedSwizzle\n"

-" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n"

-"vp_extendedSwizzle\n"

-" extSwizComp .and comma .and\n"

-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"

-"xyzwExtendedSwizzle\n"

-" xyzwExtSwizComp .and comma .and\n"

-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"

-"rgbaExtendedSwizzle\n"

-" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n"

-" rgbaExtendedSwizzle_4;\n"

-"rgbaExtendedSwizzle_1\n"

-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"

-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n"

-"rgbaExtendedSwizzle_2\n"

-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"

-" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"

-"rgbaExtendedSwizzle_3\n"

-" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n"

-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"

-"rgbaExtendedSwizzle_4\n"

-" rgbaExtSwizComp_alpha .and comma .and \n"

-"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"

-" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"

-"xyzwExtSwizComp\n"

-" optionalSign .and xyzwExtSwizSel;\n"

-"rgbaExtSwizComp\n"

-" optionalSign .and rgbaExtSwizSel;\n"

-"rgbaExtSwizComp_digit\n"

-" optionalSign .and rgbaExtSwizSel_digit;\n"

-"rgbaExtSwizComp_alpha\n"

-" optionalSign .and rgbaExtSwizSel_alpha;\n"

-"extSwizComp\n"

-" optionalSign .and extSwizSel;\n"

-"xyzwExtSwizSel\n"

-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n"

-"rgbaExtSwizSel\n"

-" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n"

-"rgbaExtSwizSel_digit\n"

-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n"

-"rgbaExtSwizSel_alpha\n"

-" rgbaComponent_single;\n"

-"extSwizSel\n"

-" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n"

-"fp_srcReg\n"

-" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"

-"vp_srcReg\n"

-" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"

-"fp_srcReg_1\n"

-" fragmentAttribReg .emit REGISTER_ATTRIB .or\n"

-" fp_progParamReg .emit REGISTER_PARAM .or\n"

-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"

-"vp_srcReg_1\n"

-" vertexAttribReg .emit REGISTER_ATTRIB .or\n"

-" vp_progParamReg .emit REGISTER_PARAM .or\n"

-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"

-"fp_dstReg\n"

-" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"

-"vp_dstReg\n"

-" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"

-"fp_dstReg_1\n"

-" fragmentResultReg .emit REGISTER_RESULT .or\n"

-" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"

-"vp_dstReg_1\n"

-" vertexResultReg .emit REGISTER_RESULT .or\n"

-" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"

-"fragmentAttribReg\n"

-" fragAttribBinding;\n"

-"vertexAttribReg\n"

-" vtxAttribBinding;\n"

-"fp_temporaryReg\n"

-" fp_establishedName_no_error_on_identifier;\n"

-"vp_temporaryReg\n"

-" vp_establishedName_no_error_on_identifier;\n"

-"fp_progParamReg\n"

-" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n"

-"vp_progParamReg\n"

-" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n"

-"fp_progParamReg_1\n"

-" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n"

-" rbracket;\n"

-"vp_progParamReg_1\n"

-" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n"

-" rbracket;\n"

-"fp_progParamSingle\n"

-" .false;\n"

-"vp_progParamSingle\n"

-" .false;\n"

-"fp_progParamArray\n"

-" fp_establishedName_no_error_on_identifier;\n"

-"vp_progParamArray\n"

-" vp_establishedName_no_error_on_identifier;\n"

-"progParamArrayMem\n"

-" progParamArrayAbs .or progParamArrayRel;\n"

-"progParamArrayAbs\n"

-" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n"

-"progParamArrayRel\n"

-" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n"

-" addrComponent .and addrRegRelOffset;\n"

-"addrRegRelOffset\n"

-" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n"

-"addrRegRelOffset_1\n"

-" plus_ne .and addrRegPosOffset;\n"

-"addrRegRelOffset_2\n"

-" minus_ne .and addrRegNegOffset;\n"

-"addrRegPosOffset\n"

-" integer_0_63;\n"

-"addrRegNegOffset\n"

-" integer_0_64;\n"

-"fragmentResultReg\n"

-" fp_resultBinding;\n"

-"vertexResultReg\n"

-" vp_resultBinding;\n"

-"addrReg\n"

-" vp_establishedName_no_error_on_identifier;\n"

-"addrComponent\n"

-" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n"

-" .emit COMPONENT_X .emit COMPONENT_X;\n"

-"addrWriteMask\n"

-" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n"

-"fp_scalarSuffix\n"

-" dot .and fp_component_single .error INVALID_COMPONENT;\n"

-"vp_scalarSuffix\n"

-" dot .and vp_component_single .error INVALID_COMPONENT;\n"

-"swizzleSuffix\n"

-" swizzleSuffix_1 .or\n"

-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"

-"swizzleSuffix_1\n"

-" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n"

-"swizzleSuffix_2\n"

-" swizzleSuffix_3 .or swizzleSuffix_4;\n"

-"swizzleSuffix_3\n"

-" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n"

-" vp_component_multi .error INVALID_COMPONENT;\n"

-"swizzleSuffix_4\n"

-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"

-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"

-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"

-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"

-"optionalSuffix\n"

-" optionalSuffix_1 .or\n"

-" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"

-"optionalSuffix_1\n"

-" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n"

-"optionalSuffix_2\n"

-" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n"

-"optionalSuffix_3\n"

-" xyzwComponent_multi .and xyzwComponent_multi .and\n"

-" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n"

-"optionalSuffix_4\n"

-" rgbaComponent_multi .and rgbaComponent_multi .and\n"

-" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n"

-"optionalSuffix_5\n"

-" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"

-" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"

-" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"

-" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n"

-" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"

-" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"

-" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"

-" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"

-"fp_component_single\n"

-" xyzwComponent_single .or rgbaComponent_single;\n"

-"vp_component_multi\n"

-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"

-" 'w' .emit COMPONENT_W;\n"

-"vp_component_single\n"

-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"

-" \"w\" .emit COMPONENT_W;\n"

-"xyzwComponent_multi\n"

-" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"

-" 'w' .emit COMPONENT_W;\n"

-"xyzwComponent_single\n"

-" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"

-" \"w\" .emit COMPONENT_W;\n"

-"rgbaComponent_multi\n"

-" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n"

-" 'a' .emit COMPONENT_W;\n"

-"rgbaComponent_single\n"

-" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n"

-" \"a\" .emit COMPONENT_W;\n"

-"fp_optionalMask\n"

-" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n"

-"vp_optionalMask\n"

-" xyzwMask .or .true .emit 0x0F;\n"

-"xyzwMask\n"

-" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n"

-"xyzwMask_1\n"

-" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n"

-" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n"

-" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n"

-" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n"

-"rgbaMask\n"

-" dot_ne .and rgbaMask_1;\n"

-"rgbaMask_1\n"

-" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n"

-" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n"

-" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n"

-" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n"

-"fp_namingStatement\n"

-" fp_ATTRIB_statement .emit ATTRIB .or\n"

-" fp_PARAM_statement .emit PARAM .or\n"

-" fp_TEMP_statement .emit TEMP .or\n"

-" fp_OUTPUT_statement .emit OUTPUT .or\n"

-" fp_ALIAS_statement .emit ALIAS;\n"

-"vp_namingStatement\n"

-" vp_ATTRIB_statement .emit ATTRIB .or\n"

-" vp_PARAM_statement .emit PARAM .or\n"

-" vp_TEMP_statement .emit TEMP .or\n"

-" ADDRESS_statement .emit ADDRESS .or\n"

-" vp_OUTPUT_statement .emit OUTPUT .or\n"

-" vp_ALIAS_statement .emit ALIAS;\n"

-"fp_ATTRIB_statement\n"

-" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n"

-" fragAttribBinding .error FRAGMENT_EXPECTED;\n"

-"vp_ATTRIB_statement\n"

-" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n"

-" vtxAttribBinding .error VERTEX_EXPECTED;\n"

-"fragAttribBinding\n"

-" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n"

-"vtxAttribBinding\n"

-" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n"

-"fragAttribItem\n"

-" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n"

-" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n"

-" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n"

-" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n"

-"fragAttribItem_1\n"

-" \"color\" .and optColorType;\n"

-"fragAttribItem_2\n"

-" \"texcoord\" .and optTexCoordNum;\n"

-"vtxAttribItem\n"

-" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n"

-" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n"

-" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n"

-" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n"

-" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n"

-" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n"

-" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n"

-" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n"

-"vtxAttribItem_1\n"

-" \"weight\" .and vtxOptWeightNum;\n"

-"vtxAttribItem_2\n"

-" \"color\" .and optColorType;\n"

-"vtxAttribItem_3\n"

-" \"texcoord\" .and optTexCoordNum;\n"

-"vtxAttribItem_4\n"

-" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n"

-"vtxAttribItem_5\n"

-" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n"

-"vtxAttribNum\n"

-" integer;\n"

-"vtxOptWeightNum\n"

-" vtxOptWeightNum_1 .or .true .emit 0x00;\n"

-"vtxOptWeightNum_1\n"

-" lbracket_ne .and vtxWeightNum .and rbracket;\n"

-"vtxWeightNum\n"

-" integer;\n"

-"fp_PARAM_statement\n"

-" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n"

-"vp_PARAM_statement\n"

-" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n"

-"fp_PARAM_singleStmt\n"

-" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n"

-" .true .emit PARAM_NULL;\n"

-"vp_PARAM_singleStmt\n"

-" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n"

-" .true .emit PARAM_NULL;\n"

-"fp_PARAM_multipleStmt\n"

-" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"

-" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n"

-"vp_PARAM_multipleStmt\n"

-" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"

-" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n"

-"optArraySize\n"

-" optional_integer;\n"

-"fp_paramSingleInit\n"

-" equal .and fp_paramSingleItemDecl;\n"

-"vp_paramSingleInit\n"

-" equal .and vp_paramSingleItemDecl;\n"

-"fp_paramMultipleInit\n"

-" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n"

-"vp_paramMultipleInit\n"

-" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n"

-"fp_paramMultInitList\n"

-" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n"

-"vp_paramMultInitList\n"

-" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n"

-"fp_paramMultInitList_1\n"

-" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n"

-"vp_paramMultInitList_1\n"

-" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n"

-"fp_paramSingleItemDecl\n"

-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"

-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"

-" paramConstDecl .emit PARAM_CONSTANT;\n"

-"vp_paramSingleItemDecl\n"

-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"

-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"

-" paramConstDecl .emit PARAM_CONSTANT;\n"

-"fp_paramSingleItemUse\n"

-" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"

-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"

-" paramConstUse .emit PARAM_CONSTANT;\n"

-"vp_paramSingleItemUse\n"

-" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"

-" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"

-" paramConstUse .emit PARAM_CONSTANT;\n"

-"fp_paramMultipleItem\n"

-" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"

-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"

-" paramConstDecl .emit PARAM_CONSTANT;\n"

-"vp_paramMultipleItem\n"

-" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"

-" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"

-" paramConstDecl .emit PARAM_CONSTANT;\n"

-"fp_stateMultipleItem\n"

-" stateMultipleItem_1 .or fp_stateSingleItem;\n"

-"vp_stateMultipleItem\n"

-" stateMultipleItem_1 .or vp_stateSingleItem;\n"

-"stateMultipleItem_1\n"

-" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n"

-"fp_stateSingleItem\n"

-" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"

-"vp_stateSingleItem\n"

-" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"

-"fp_stateSingleItem_1\n"

-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"

-" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n"

-"vp_stateSingleItem_1\n"

-" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"

-" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n"

-" stateSingleItem_11;\n"

-"stateSingleItem_1\n"

-" stateMaterialItem .emit STATE_MATERIAL;\n"

-"stateSingleItem_2\n"

-" stateLightItem .emit STATE_LIGHT;\n"

-"stateSingleItem_3\n"

-" stateLightModelItem .emit STATE_LIGHT_MODEL;\n"

-"stateSingleItem_4\n"

-" stateLightProdItem .emit STATE_LIGHT_PROD;\n"

-"stateSingleItem_5\n"

-" stateTexEnvItem .emit STATE_TEX_ENV;\n"

-"stateSingleItem_6\n"

-" stateTexGenItem .emit STATE_TEX_GEN;\n"

-"stateSingleItem_7\n"

-" stateFogItem .emit STATE_FOG;\n"

-"stateSingleItem_8\n"

-" stateDepthItem .emit STATE_DEPTH;\n"

-"stateSingleItem_9\n"

-" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n"

-"stateSingleItem_10\n"

-" statePointItem .emit STATE_POINT;\n"

-"stateSingleItem_11\n"

-" stateMatrixRow .emit STATE_MATRIX_ROWS;\n"

-"stateMaterialItem\n"

-" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n"

-"stateMatProperty\n"

-" \"ambient\" .emit MATERIAL_AMBIENT .or\n"

-" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n"

-" \"specular\" .emit MATERIAL_SPECULAR .or\n"

-" \"emission\" .emit MATERIAL_EMISSION .or\n"

-" \"shininess\" .emit MATERIAL_SHININESS;\n"

-"stateLightItem\n"

-" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n"

-" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n"

-"stateLightProperty\n"

-" \"ambient\" .emit LIGHT_AMBIENT .or\n"

-" \"diffuse\" .emit LIGHT_DIFFUSE .or\n"

-" \"specular\" .emit LIGHT_SPECULAR .or\n"

-" \"position\" .emit LIGHT_POSITION .or\n"

-" \"attenuation\" .emit LIGHT_ATTENUATION .or\n"

-" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n"

-" \"half\" .emit LIGHT_HALF;\n"

-"stateLightProperty_1\n"

-" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n"

-"stateSpotProperty\n"

-" \"direction\";\n"

-"stateLightModelItem\n"

-" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n"

-"stateLModProperty\n"

-" stateLModProperty_1 .or stateLModProperty_2;\n"

-"stateLModProperty_1\n"

-" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n"

-"stateLModProperty_2\n"

-" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n"

-"stateLModProperty_3\n"

-" optFaceType .and dot .and \"scenecolor\";\n"

-"stateLightProdItem\n"

-" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n"

-" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n"

-"stateLProdProperty\n"

-" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n"

-" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n"

-" \"specular\" .emit LIGHT_PROD_SPECULAR;\n"

-"stateLightNumber\n"

-" integer;\n"

-"stateTexEnvItem\n"

-" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n"

-" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n"

-"stateTexEnvProperty\n"

-" \"color\" .emit TEX_ENV_COLOR;\n"

-"optLegacyTexUnitNum\n"

-" lbracket_ne .and legacyTexUnitNum .and rbracket;\n"

-"legacyTexUnitNum\n"

-" integer;\n"

-"stateTexGenItem\n"

-" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n"

-" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n"

-"stateTexGenType\n"

-" \"eye\" .emit TEX_GEN_EYE .or\n"

-" \"object\" .emit TEX_GEN_OBJECT;\n"

-"stateTexGenCoord\n"

-" \"s\" .emit COMPONENT_X .or\n"

-" \"t\" .emit COMPONENT_Y .or\n"

-" \"r\" .emit COMPONENT_Z .or\n"

-" \"q\" .emit COMPONENT_W;\n"

-"stateFogItem\n"

-" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n"

-"stateFogProperty\n"

-" \"color\" .emit FOG_COLOR .or\n"

-" \"params\" .emit FOG_PARAMS;\n"

-"stateDepthItem\n"

-" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n"

-"stateDepthProperty\n"

-" \"range\" .emit DEPTH_RANGE;\n"

-"stateClipPlaneItem\n"

-" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n"

-" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n"

-"stateClipPlaneNum\n"

-" integer;\n"

-"statePointItem\n"

-" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n"

-"statePointProperty\n"

-" \"size\" .emit POINT_SIZE .or\n"

-" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n"

-"stateMatrixRow\n"

-" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n"

-" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n"

-"stateMatrixRows\n"

-" stateMatrixItem .and optMatrixRows;\n"

-"optMatrixRows\n"

-" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n"

-"optMatrixRows_1\n"

-" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n"

-" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n"

-"stateMatrixItem\n"

-" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n"

-"stateOptMatModifier\n"

-" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n"

-"stateOptMatModifier_1\n"

-" dot_ne .and stateMatModifier;\n"

-"stateMatModifier\n"

-" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n"

-" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n"

-" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n"

-"stateMatrixRowNum\n"

-" integer_0_3;\n"

-"stateMatrixName\n"

-" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n"

-" \"projection\" .emit MATRIX_PROJECTION .or\n"

-" \"mvp\" .emit MATRIX_MVP .or\n"

-" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n"

-" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n"

-" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n"

-"stateMatrixName_1_1\n"

-" \"modelview\" .and stateOptModMatNum;\n"

-"stateMatrixName_1_2\n"

-" \"texture\" .and optTexCoordNum;\n"

-"stateMatrixName_1_3\n"

-" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n"

-"stateMatrixName_1_4\n"

-" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n"

-"stateOptModMatNum\n"

-" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n"

-" .true .emit 0x00;\n"

-"stateOptModMatNum_1\n"

-" lbracket_ne .and stateModMatNum .and rbracket;\n"

-"stateModMatNum\n"

-" integer;\n"

-"optTexCoordNum\n"

-" optTexCoordNum_1 .or .true .emit 0x00;\n"

-"optTexCoordNum_1\n"

-" lbracket_ne .and texCoordNum .and rbracket;\n"

-"texCoordNum\n"

-" integer;\n"

-"statePaletteMatNum\n"

-" integer;\n"

-"stateProgramMatNum\n"

-" integer;\n"

-"programSingleItem\n"

-" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"

-"programSingleItem_1\n"

-" progEnvParam .or progLocalParam;\n"

-"programMultipleItem\n"

-" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"

-"programMultipleItem_1\n"

-" progEnvParams .or progLocalParams;\n"

-"progEnvParams\n"

-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n"

-"progEnvParamNums\n"

-" progEnvParamNums_1 .or progEnvParamNums_2;\n"

-"progEnvParamNums_1\n"

-" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n"

-"progEnvParamNums_2\n"

-" progEnvParamNum .and .true .emit 0x00;\n"

-"progEnvParam\n"

-" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n"

-"progLocalParams\n"

-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n"

-"progLocalParamNums\n"

-" progLocalParamNums_1 .or progLocalParamNums_2;\n"

-"progLocalParamNums_1\n"

-" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n"

-"progLocalParamNums_2\n"

-" progLocalParamNum .and .true .emit 0x00;\n"

-"progLocalParam\n"

-" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n"

-"progEnvParamNum\n"

-" integer;\n"

-"progLocalParamNum\n"

-" integer;\n"

-"paramConstDecl\n"

-" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"

-"paramConstUse\n"

-" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"

-"paramConstScalarDecl\n"

-" signedFloatConstant;\n"

-"paramConstScalarUse\n"

-" floatConstant;\n"

-"paramConstVector\n"

-" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n"

-" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n"

-"paramConstVector_1\n"

-" lbrace_ne .and signedFloatConstant .and rbrace;\n"

-"paramConstVector_2\n"

-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"

-"paramConstVector_3\n"

-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"

-" signedFloatConstant .and rbrace;\n"

-"paramConstVector_4\n"

-" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"

-" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"

-"signedFloatConstant\n"

-" optionalSign .and floatConstant;\n"

-"floatConstant\n"

-" float;\n"

-"optionalSign\n"

-" optional_sign_ne;\n"

-"fp_TEMP_statement\n"

-" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n"

-"vp_TEMP_statement\n"

-" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n"

-"ADDRESS_statement\n"

-" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n"

-"fp_varNameList\n"

-" fp_varNameList_1 .or fp_establishName;\n"

-"vp_varNameList\n"

-" vp_varNameList_1 .or vp_establishName;\n"

-"fp_varNameList_1\n"

-" fp_establishName .and comma_ne .and fp_varNameList;\n"

-"vp_varNameList_1\n"

-" vp_establishName .and comma_ne .and vp_varNameList;\n"

-"fp_OUTPUT_statement\n"

-" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n"

-" fp_resultBinding .error RESULT_EXPECTED;\n"

-"vp_OUTPUT_statement\n"

-" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n"

-" vp_resultBinding .error RESULT_EXPECTED;\n"

-"fp_resultBinding\n"

-" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"

-"vp_resultBinding\n"

-" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"

-"fp_resultBinding_1\n"

-" \"color\" .emit FRAGMENT_RESULT_COLOR .or\n"

-" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n"

-"vp_resultBinding_1\n"

-" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n"

-" resultColBinding .emit VERTEX_RESULT_COLOR .or\n"

-" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n"

-" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n"

-" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n"

-"vp_resultBinding_2\n"

-" \"texcoord\" .and optTexCoordNum;\n"

-"resultColBinding\n"

-" \"color\" .and optFaceType .and optColorType;\n"

-"optFaceType\n"

-" FaceType .or .true .emit FACE_FRONT;\n"

-"FaceType\n"

-" dot_ne .and FaceProperty;\n"

-"FaceProperty\n"

-" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n"

-"optColorType\n"

-" ColorType .or .true .emit COLOR_PRIMARY;\n"

-"ColorType\n"

-" dot_ne .and ColorProperty;\n"

-"ColorProperty\n"

-" \"primary\" .emit COLOR_PRIMARY .or\n"

-" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n"

-"fp_ALIAS_statement\n"

-" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n"

-"vp_ALIAS_statement\n"

-" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n"

-"fp_ALIAS_statement_1\n"

-" space .and fp_establishName;\n"

-"vp_ALIAS_statement_1\n"

-" space .and vp_establishName;\n"

-"fp_establishName\n"

-" fp_identifier;\n"

-"vp_establishName\n"

-" vp_identifier;\n"

-"fp_establishedName\n"

-" fp_identifier;\n"

-"vp_establishedName\n"

-" vp_identifier;\n"

-"fp_establishedName_no_error_on_identifier\n"

-" fp_identifier_ne;\n"

-"vp_establishedName_no_error_on_identifier\n"

-" vp_identifier_ne;\n"

-"fp_identifier\n"

-" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n"

-"vp_identifier\n"

-" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n"

-"fp_identifier_ne\n"

-" fp_not_reserved_identifier .and identifier_ne;\n"

-"vp_identifier_ne\n"

-" vp_not_reserved_identifier .and identifier_ne;\n"

-"fp_not_reserved_identifier\n"

-" fp_not_reserved_identifier_1 .or .true;\n"

-"fp_not_reserved_identifier_1\n"

-" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"

-"vp_not_reserved_identifier\n"

-" vp_not_reserved_identifier_1 .or .true;\n"

-"vp_not_reserved_identifier_1\n"

-" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"

-"fp_reserved_identifier\n"

-" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n"

-" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n"

-" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n"

-" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n"

-" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n"

-" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n"

-" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n"

-" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n"

-" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n"

-" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n"

-"vp_reserved_identifier\n"

-" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n"

-" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n"

-" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n"

-" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n"

-" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n"

-"integer\n"

-" integer_ne .error INTEGER_EXPECTED;\n"

-"zero\n"

-" '0';\n"

-"leading_zeroes\n"

-" .loop zero;\n"

-"no_digit\n"

-" no_digit_1 .or .true;\n"

-"no_digit_1\n"

-" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n"

-"all_zeroes\n"

-" all_zeroes_1 .or no_digit_1;\n"

-"all_zeroes_1\n"

-" '0' .and .loop zero .and no_digit;\n"

-"integer_0_3\n"

-" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"

-"integer_0_3_1\n"

-" integer_0_3_2 .or all_zeroes .emit '0';\n"

-"integer_0_3_2 \n"

-" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n"

-"integer_0_63\n"

-" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"

-"integer_0_63_1\n"

-" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n"

-" all_zeroes .emit '0';\n"

-"integer_0_63_2 \n"

-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"

-"integer_0_63_3 \n"

-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"

-"integer_0_63_4 \n"

-" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n"

-"integer_0_63_5 \n"

-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"

-"integer_0_64\n"

-" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"

-"integer_0_64_1\n"

-" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n"

-" all_zeroes .emit '0';\n"

-"integer_0_64_2 \n"

-" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"

-"integer_0_64_3 \n"

-" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"

-"integer_0_64_4 \n"

-" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n"

-"integer_0_64_5 \n"

-" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"

-"optional_space\n"

-" space .or .true;\n"

-"space_dst\n"

-" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n"

-"space_src\n"

-" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n"

-"space\n"

-" single_space .and .loop single_space;\n"

-"single_space\n"

-" white_char .or comment_block;\n"

-"white_char\n"

-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"

-"comment_block\n"

-" '#' .and .loop comment_char .and new_line;\n"

-"comment_char\n"

-" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"

-"new_line\n"

-" '\\n' .or crlf .or '\\0';\n"

-"crlf\n"

-" '\\r' .and '\\n';\n"

-"semicolon\n"

-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"

-"comma\n"

-" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n"

-"comma_ne\n"

-" optional_space .and ',' .and optional_space;\n"

-"lbracket\n"

-" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n"

-"lbracket_ne\n"

-" optional_space .and '[' .and optional_space;\n"

-"rbracket\n"

-" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n"

-"dot\n"

-" optional_space .and '.' .error MISSING_DOT .and optional_space;\n"

-"dot_ne\n"

-" optional_space .and '.' .and optional_space;\n"

-"equal\n"

-" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n"

-"lbrace\n"

-" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n"

-"lbrace_ne\n"

-" optional_space .and '{' .and optional_space;\n"

-"rbrace\n"

-" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n"

-"dotdot\n"

-" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n"

-"dotdot_ne\n"

-" optional_space .and '.' .and '.' .and optional_space;\n"

-"float\n"

-" float_1 .or float_2 .or float_legacy;\n"

-"float_1\n"

-" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n"

-"float_2\n"

-" integer_ne .and float_3;\n"

-"float_3\n"

-" float_4 .or float_5;\n"

-"float_4\n"

-" '.' .and optional_integer .and optional_exponent;\n"

-"float_5\n"

-" exponent .emit 0x00;\n"

-"float_legacy\n"

-" integer_ne .and .true .emit 0x00 .emit 0x00;\n"

-"integer_ne\n"

-" integer_ne_1 .and .true .emit 0x00 .emit $;\n"

-"integer_ne_1\n"

-" digit10 .emit * .and .loop digit10 .emit *;\n"

-"optional_integer\n"

-" integer_ne .or .true .emit 0x00;\n"

-"optional_exponent\n"

-" exponent .or .true .emit 0x00;\n"

-"exponent\n"

-" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n"

-"exponent_1\n"

-" 'e' .or 'E';\n"

-"optional_sign_ne\n"

-" minus_ne .or plus_ne .or .true;\n"

-"plus_ne\n"

-" optional_space .and '+' .and optional_space;\n"

-"minus_ne\n"

-" optional_space .and '-' .emit '-' .and optional_space;\n"

-"identifier_ne\n"

-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n"

-"follow_idchar\n"

-" first_idchar .or digit10;\n"

-"first_idchar\n"

-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"

-"digit10\n"

-" '0'-'9';\n"

-".string __string_filter;\n"

-"__string_filter\n"

-" .loop __identifier_char;\n"

-"__identifier_char\n"

-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n"

-"e_signature\n"

-" e_signature_char .and .loop e_signature_char;\n"

-"e_signature_char\n"

-" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"

-"e_statement\n"

-" .loop e_statement_not_term;\n"

-"e_statement_not_term\n"

-" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"

-"e_identifier\n"

-" e_identifier_first .and .loop e_identifier_next;\n"

-"e_identifier_first\n"

-" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"

-"e_identifier_next\n"

-" e_identifier_first .or '0'-'9';\n"

-"e_token\n"

-" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n"

-" '-' .or ',' .or ';';\n"

-"e_token_number\n"

-" e_token_digit .and .loop e_token_digit;\n"

-"e_token_digit\n"

-" '0'-'9';\n"

-"e_charordigit\n"

-" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"

-""
\ No newline at end of file
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file arbprogram_syn.h
+ * ARB_fragment_program/ARB_vertex_program syntax
+ * \author Michal Krol
+ */
+
+".syntax program;\n"
+".emtcode REVISION 0x07\n"
+".emtcode FRAGMENT_PROGRAM 0x01\n"
+".emtcode VERTEX_PROGRAM 0x02\n"
+".emtcode OPTION 0x01\n"
+".emtcode INSTRUCTION 0x02\n"
+".emtcode DECLARATION 0x03\n"
+".emtcode END 0x04\n"
+".emtcode ARB_PRECISION_HINT_FASTEST 0x01\n"
+".emtcode ARB_PRECISION_HINT_NICEST 0x02\n"
+".emtcode ARB_FOG_EXP 0x04\n"
+".emtcode ARB_FOG_EXP2 0x08\n"
+".emtcode ARB_FOG_LINEAR 0x10\n"
+".emtcode ARB_POSITION_INVARIANT 0x20\n"
+".emtcode ARB_FRAGMENT_PROGRAM_SHADOW 0x40\n"
+".emtcode OP_ALU_INST 0x00\n"
+".emtcode OP_TEX_INST 0x01\n"
+".emtcode OP_ALU_VECTOR 0x00\n"
+".emtcode OP_ALU_SCALAR 0x01\n"
+".emtcode OP_ALU_BINSC 0x02\n"
+".emtcode OP_ALU_BIN 0x03\n"
+".emtcode OP_ALU_TRI 0x04\n"
+".emtcode OP_ALU_SWZ 0x05\n"
+".emtcode OP_TEX_SAMPLE 0x06\n"
+".emtcode OP_TEX_KIL 0x07\n"
+".emtcode OP_ALU_ARL 0x08\n"
+".emtcode OP_ABS 0x00\n"
+".emtcode OP_ABS_SAT 0x1B\n"
+".emtcode OP_FLR 0x09\n"
+".emtcode OP_FLR_SAT 0x26\n"
+".emtcode OP_FRC 0x0A\n"
+".emtcode OP_FRC_SAT 0x27\n"
+".emtcode OP_LIT 0x0C\n"
+".emtcode OP_LIT_SAT 0x2A\n"
+".emtcode OP_MOV 0x11\n"
+".emtcode OP_MOV_SAT 0x30\n"
+".emtcode OP_COS 0x1F\n"
+".emtcode OP_COS_SAT 0x20\n"
+".emtcode OP_EX2 0x07\n"
+".emtcode OP_EX2_SAT 0x25\n"
+".emtcode OP_LG2 0x0B\n"
+".emtcode OP_LG2_SAT 0x29\n"
+".emtcode OP_RCP 0x14\n"
+".emtcode OP_RCP_SAT 0x33\n"
+".emtcode OP_RSQ 0x15\n"
+".emtcode OP_RSQ_SAT 0x34\n"
+".emtcode OP_SIN 0x38\n"
+".emtcode OP_SIN_SAT 0x39\n"
+".emtcode OP_SCS 0x35\n"
+".emtcode OP_SCS_SAT 0x36\n"
+".emtcode OP_POW 0x13\n"
+".emtcode OP_POW_SAT 0x32\n"
+".emtcode OP_ADD 0x01\n"
+".emtcode OP_ADD_SAT 0x1C\n"
+".emtcode OP_DP3 0x03\n"
+".emtcode OP_DP3_SAT 0x21\n"
+".emtcode OP_DP4 0x04\n"
+".emtcode OP_DP4_SAT 0x22\n"
+".emtcode OP_DPH 0x05\n"
+".emtcode OP_DPH_SAT 0x23\n"
+".emtcode OP_DST 0x06\n"
+".emtcode OP_DST_SAT 0x24\n"
+".emtcode OP_MAX 0x0F\n"
+".emtcode OP_MAX_SAT 0x2E\n"
+".emtcode OP_MIN 0x10\n"
+".emtcode OP_MIN_SAT 0x2F\n"
+".emtcode OP_MUL 0x12\n"
+".emtcode OP_MUL_SAT 0x31\n"
+".emtcode OP_SGE 0x16\n"
+".emtcode OP_SGE_SAT 0x37\n"
+".emtcode OP_SLT 0x17\n"
+".emtcode OP_SLT_SAT 0x3A\n"
+".emtcode OP_SUB 0x18\n"
+".emtcode OP_SUB_SAT 0x3B\n"
+".emtcode OP_XPD 0x1A\n"
+".emtcode OP_XPD_SAT 0x43\n"
+".emtcode OP_CMP 0x1D\n"
+".emtcode OP_CMP_SAT 0x1E\n"
+".emtcode OP_LRP 0x2B\n"
+".emtcode OP_LRP_SAT 0x2C\n"
+".emtcode OP_MAD 0x0E\n"
+".emtcode OP_MAD_SAT 0x2D\n"
+".emtcode OP_SWZ 0x19\n"
+".emtcode OP_SWZ_SAT 0x3C\n"
+".emtcode OP_TEX 0x3D\n"
+".emtcode OP_TEX_SAT 0x3E\n"
+".emtcode OP_TXB 0x3F\n"
+".emtcode OP_TXB_SAT 0x40\n"
+".emtcode OP_TXP 0x41\n"
+".emtcode OP_TXP_SAT 0x42\n"
+".emtcode OP_KIL 0x28\n"
+".emtcode OP_ARL 0x02\n"
+".emtcode OP_EXP 0x08\n"
+".emtcode OP_LOG 0x0D\n"
+".emtcode FRAGMENT_ATTRIB_COLOR 0x01\n"
+".emtcode FRAGMENT_ATTRIB_TEXCOORD 0x02\n"
+".emtcode FRAGMENT_ATTRIB_FOGCOORD 0x03\n"
+".emtcode FRAGMENT_ATTRIB_POSITION 0x04\n"
+".emtcode VERTEX_ATTRIB_POSITION 0x01\n"
+".emtcode VERTEX_ATTRIB_WEIGHT 0x02\n"
+".emtcode VERTEX_ATTRIB_NORMAL 0x03\n"
+".emtcode VERTEX_ATTRIB_COLOR 0x04\n"
+".emtcode VERTEX_ATTRIB_FOGCOORD 0x05\n"
+".emtcode VERTEX_ATTRIB_TEXCOORD 0x06\n"
+".emtcode VERTEX_ATTRIB_MATRIXINDEX 0x07\n"
+".emtcode VERTEX_ATTRIB_GENERIC 0x08\n"
+".emtcode FRAGMENT_RESULT_COLOR 0x01\n"
+".emtcode FRAGMENT_RESULT_DEPTH 0x02\n"
+".emtcode VERTEX_RESULT_POSITION 0x01\n"
+".emtcode VERTEX_RESULT_COLOR 0x02\n"
+".emtcode VERTEX_RESULT_FOGCOORD 0x03\n"
+".emtcode VERTEX_RESULT_POINTSIZE 0x04\n"
+".emtcode VERTEX_RESULT_TEXCOORD 0x05\n"
+".emtcode TEXTARGET_1D 0x01\n"
+".emtcode TEXTARGET_2D 0x02\n"
+".emtcode TEXTARGET_3D 0x03\n"
+".emtcode TEXTARGET_RECT 0x04\n"
+".emtcode TEXTARGET_CUBE 0x05\n"
+".emtcode TEXTARGET_SHADOW1D 0x06\n"
+".emtcode TEXTARGET_SHADOW2D 0x07\n"
+".emtcode TEXTARGET_SHADOWRECT 0x08\n"
+".emtcode FACE_FRONT 0x00\n"
+".emtcode FACE_BACK 0x01\n"
+".emtcode COLOR_PRIMARY 0x00\n"
+".emtcode COLOR_SECONDARY 0x01\n"
+".emtcode COMPONENT_X 0x00\n"
+".emtcode COMPONENT_Y 0x01\n"
+".emtcode COMPONENT_Z 0x02\n"
+".emtcode COMPONENT_W 0x03\n"
+".emtcode COMPONENT_0 0x04\n"
+".emtcode COMPONENT_1 0x05\n"
+".emtcode ARRAY_INDEX_ABSOLUTE 0x00\n"
+".emtcode ARRAY_INDEX_RELATIVE 0x01\n"
+".emtcode MATRIX_MODELVIEW 0x01\n"
+".emtcode MATRIX_PROJECTION 0x02\n"
+".emtcode MATRIX_MVP 0x03\n"
+".emtcode MATRIX_TEXTURE 0x04\n"
+".emtcode MATRIX_PALETTE 0x05\n"
+".emtcode MATRIX_PROGRAM 0x06\n"
+".emtcode MATRIX_MODIFIER_IDENTITY 0x00\n"
+".emtcode MATRIX_MODIFIER_INVERSE 0x01\n"
+".emtcode MATRIX_MODIFIER_TRANSPOSE 0x02\n"
+".emtcode MATRIX_MODIFIER_INVTRANS 0x03\n"
+".emtcode CONSTANT_SCALAR 0x01\n"
+".emtcode CONSTANT_VECTOR 0x02\n"
+".emtcode PROGRAM_PARAM_ENV 0x01\n"
+".emtcode PROGRAM_PARAM_LOCAL 0x02\n"
+".emtcode REGISTER_ATTRIB 0x01\n"
+".emtcode REGISTER_PARAM 0x02\n"
+".emtcode REGISTER_RESULT 0x03\n"
+".emtcode REGISTER_ESTABLISHED_NAME 0x04\n"
+".emtcode PARAM_NULL 0x00\n"
+".emtcode PARAM_ARRAY_ELEMENT 0x01\n"
+".emtcode PARAM_STATE_ELEMENT 0x02\n"
+".emtcode PARAM_PROGRAM_ELEMENT 0x03\n"
+".emtcode PARAM_PROGRAM_ELEMENTS 0x04\n"
+".emtcode PARAM_CONSTANT 0x05\n"
+".emtcode STATE_MATERIAL 0x01\n"
+".emtcode STATE_LIGHT 0x02\n"
+".emtcode STATE_LIGHT_MODEL 0x03\n"
+".emtcode STATE_LIGHT_PROD 0x04\n"
+".emtcode STATE_FOG 0x05\n"
+".emtcode STATE_MATRIX_ROWS 0x06\n"
+".emtcode STATE_TEX_ENV 0x07\n"
+".emtcode STATE_DEPTH 0x08\n"
+".emtcode STATE_TEX_GEN 0x09\n"
+".emtcode STATE_CLIP_PLANE 0x0A\n"
+".emtcode STATE_POINT 0x0B\n"
+".emtcode MATERIAL_AMBIENT 0x01\n"
+".emtcode MATERIAL_DIFFUSE 0x02\n"
+".emtcode MATERIAL_SPECULAR 0x03\n"
+".emtcode MATERIAL_EMISSION 0x04\n"
+".emtcode MATERIAL_SHININESS 0x05\n"
+".emtcode LIGHT_AMBIENT 0x01\n"
+".emtcode LIGHT_DIFFUSE 0x02\n"
+".emtcode LIGHT_SPECULAR 0x03\n"
+".emtcode LIGHT_POSITION 0x04\n"
+".emtcode LIGHT_ATTENUATION 0x05\n"
+".emtcode LIGHT_HALF 0x06\n"
+".emtcode LIGHT_SPOT_DIRECTION 0x07\n"
+".emtcode LIGHT_MODEL_AMBIENT 0x01\n"
+".emtcode LIGHT_MODEL_SCENECOLOR 0x02\n"
+".emtcode LIGHT_PROD_AMBIENT 0x01\n"
+".emtcode LIGHT_PROD_DIFFUSE 0x02\n"
+".emtcode LIGHT_PROD_SPECULAR 0x03\n"
+".emtcode TEX_ENV_COLOR 0x01\n"
+".emtcode TEX_GEN_EYE 0x01\n"
+".emtcode TEX_GEN_OBJECT 0x02\n"
+".emtcode FOG_COLOR 0x01\n"
+".emtcode FOG_PARAMS 0x02\n"
+".emtcode DEPTH_RANGE 0x01\n"
+".emtcode POINT_SIZE 0x01\n"
+".emtcode POINT_ATTENUATION 0x02\n"
+".emtcode ATTRIB 0x01\n"
+".emtcode PARAM 0x02\n"
+".emtcode TEMP 0x03\n"
+".emtcode OUTPUT 0x04\n"
+".emtcode ALIAS 0x05\n"
+".emtcode ADDRESS 0x06\n"
+".errtext UNKNOWN_PROGRAM_SIGNATURE \"1001: '$e_signature$': unknown program signature\"\n"
+".errtext MISSING_END_OR_INVALID_STATEMENT \"1002: '$e_statement$': invalid statement\"\n"
+".errtext CODE_AFTER_END \"1003: '$e_statement$': code after 'END' keyword\"\n"
+".errtext INVALID_PROGRAM_OPTION \"1004: '$e_identifier$': invalid program option\"\n"
+".errtext EXT_SWIZ_COMP_EXPECTED \"1005: extended swizzle component expected but '$e_token$' found\"\n"
+".errtext TEX_TARGET_EXPECTED \"1006: texture target expected but '$e_token$' found\"\n"
+".errtext TEXTURE_EXPECTED \"1007: 'texture' expected but '$e_identifier$' found\"\n"
+".errtext SOURCE_REGISTER_EXPECTED \"1008: source register expected but '$e_token$' found\"\n"
+".errtext DESTINATION_REGISTER_EXPECTED \"1009: destination register expected but '$e_token$' found\"\n"
+".errtext INVALID_ADDRESS_COMPONENT \"1010: '$e_identifier$': invalid address component\"\n"
+".errtext INVALID_ADDRESS_WRITEMASK \"1011: '$e_identifier$': invalid address writemask\"\n"
+".errtext INVALID_COMPONENT \"1012: '$e_charordigit$': invalid component\"\n"
+".errtext INVALID_SUFFIX \"1013: '$e_identifier$': invalid suffix\"\n"
+".errtext INVALID_WRITEMASK \"1014: '$e_identifier$': invalid writemask\"\n"
+".errtext FRAGMENT_EXPECTED \"1015: 'fragment' expected but '$e_identifier$' found\"\n"
+".errtext VERTEX_EXPECTED \"1016: 'vertex' expected but '$e_identifier$' found\"\n"
+".errtext INVALID_FRAGMENT_PROPERTY \"1017: '$e_identifier$': invalid fragment property\"\n"
+".errtext INVALID_VERTEX_PROPERTY \"1018: '$e_identifier$': invalid vertex property\"\n"
+".errtext INVALID_STATE_PROPERTY \"1019: '$e_identifier$': invalid state property\"\n"
+".errtext INVALID_MATERIAL_PROPERTY \"1020: '$e_identifier$': invalid material property\"\n"
+".errtext INVALID_LIGHT_PROPERTY \"1021: '$e_identifier$': invalid light property\"\n"
+".errtext INVALID_SPOT_PROPERTY \"1022: '$e_identifier$': invalid spot property\"\n"
+".errtext INVALID_LIGHTMODEL_PROPERTY \"1023: '$e_identifier$': invalid light model property\"\n"
+".errtext INVALID_LIGHTPROD_PROPERTY \"1024: '$e_identifier$': invalid light product property\"\n"
+".errtext INVALID_TEXENV_PROPERTY \"1025: '$e_identifier$': invalid texture environment property\"\n"
+".errtext INVALID_TEXGEN_PROPERTY \"1026: '$e_identifier$': invalid texture generating property\"\n"
+".errtext INVALID_TEXGEN_COORD \"1027: '$e_identifier$': invalid texture generating coord\"\n"
+".errtext INVALID_FOG_PROPERTY \"1028: '$e_identifier$': invalid fog property\"\n"
+".errtext INVALID_DEPTH_PROPERTY \"1029: '$e_identifier$': invalid depth property\"\n"
+".errtext INVALID_CLIPPLANE_PROPERTY \"1030: '$e_identifier$': invalid clip plane property\"\n"
+".errtext INVALID_POINT_PROPERTY \"1031: '$e_identifier$': invalid point property\"\n"
+".errtext MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED \"1032: matrix row selector or modifier expected but '$e_token$' found\"\n"
+".errtext INVALID_MATRIX_NAME \"1033: '$e_identifier$': invalid matrix name\"\n"
+".errtext INVALID_PROGRAM_PROPERTY \"1034: '$e_identifier$': invalid program property\"\n"
+".errtext RESULT_EXPECTED \"1035: 'result' expected but '$e_token$' found\"\n"
+".errtext INVALID_RESULT_PROPERTY \"1036: '$e_identifier$': invalid result property\"\n"
+".errtext INVALID_FACE_PROPERTY \"1037: '$e_identifier$': invalid face property\"\n"
+".errtext INVALID_COLOR_PROPERTY \"1038: '$e_identifier$': invalid color property\"\n"
+".errtext IDENTIFIER_EXPECTED \"1039: identifier expected but '$e_token$' found\"\n"
+".errtext RESERVED_KEYWORD \"1040: use of reserved keyword as an identifier\"\n"
+".errtext INTEGER_EXPECTED \"1041: integer value expected but '$e_token$' found\"\n"
+".errtext MISSING_SEMICOLON \"1042: ';' expected but '$e_token$' found\"\n"
+".errtext MISSING_COMMA \"1043: ',' expected but '$e_token$' found\"\n"
+".errtext MISSING_LBRACKET \"1044: '[' expected but '$e_token$' found\"\n"
+".errtext MISSING_RBRACKET \"1045: ']' expected but '$e_token$' found\"\n"
+".errtext MISSING_DOT \"1046: '.' expected but '$e_token$' found\"\n"
+".errtext MISSING_EQUAL \"1047: '=' expected but '$e_token$' found\"\n"
+".errtext MISSING_LBRACE \"1048: '{' expected but '$e_token$' found\"\n"
+".errtext MISSING_RBRACE \"1049: '}' expected but '$e_token$' found\"\n"
+".errtext MISSING_DOTDOT \"1050: '..' expected but '$e_token$' found\"\n"
+".errtext MISSING_FRACTION_OR_EXPONENT \"1051: missing fraction part or exponent\"\n"
+".errtext MISSING_DOT_OR_EXPONENT \"1052: missing '.' or exponent\"\n"
+".errtext EXPONENT_VALUE_EXPECTED \"1053: exponent value expected\"\n"
+".errtext INTEGER_OUT_OF_RANGE \"1054: integer value out of range\"\n"
+".errtext OPERATION_NEEDS_DESTINATION_VARIABLE \"1055: operation needs destination variable\"\n"
+".errtext OPERATION_NEEDS_SOURCE_VARIABLE \"1056: operation needs source variable\"\n"
+".errtext ADDRESS_REGISTER_EXPECTED \"1057: address register expected but '$e_token$' found\"\n"
+".errtext ADDRESS_REGISTER_OR_INTEGER_EXPECTED \"1058: address register or integer literal expected but '$e_token$' found\"\n"
+".regbyte vertex_blend 0x00\n"
+".regbyte matrix_palette 0x00\n"
+".regbyte point_parameters 0x00\n"
+".regbyte secondary_color 0x00\n"
+".regbyte fog_coord 0x00\n"
+".regbyte texture_rectangle 0x00\n"
+".regbyte fragment_program_shadow 0x00\n"
+".regbyte ARB_precision_hint_fastest 0x00\n"
+".regbyte ARB_precision_hint_nicest 0x00\n"
+".regbyte ARB_fog_exp 0x00\n"
+".regbyte ARB_fog_exp2 0x00\n"
+".regbyte ARB_fog_linear 0x00\n"
+".regbyte ARB_position_invariant 0x00\n"
+".regbyte ARB_fragment_program_shadow 0x00\n"
+".regbyte program_target 0x00\n"
+"program\n"
+" programs .error UNKNOWN_PROGRAM_SIGNATURE .emit REVISION;\n"
+"programs\n"
+" .if (program_target == 0x10) frag_program_1_0 .emit FRAGMENT_PROGRAM .emit 0x01 .emit 0x00 .or\n"
+" .if (program_target == 0x20) vert_program_1_0 .emit VERTEX_PROGRAM .emit 0x01 .emit 0x00;\n"
+"frag_program_1_0\n"
+" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'f' .and 'p' .and '1' .and '.' .and '0' .and\n"
+" optional_space .and fp_optionSequence .and fp_statementSequence .and\n"
+" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
+" '\\0' .error CODE_AFTER_END;\n"
+"vert_program_1_0\n"
+" '!' .and '!' .and 'A' .and 'R' .and 'B' .and 'v' .and 'p' .and '1' .and '.' .and '0' .and\n"
+" optional_space .and vp_optionSequence .and vp_statementSequence .and\n"
+" \"END\" .error MISSING_END_OR_INVALID_STATEMENT .emit END .and optional_space .and\n"
+" '\\0' .error CODE_AFTER_END;\n"
+"fp_optionSequence\n"
+" .loop fp_option;\n"
+"vp_optionSequence\n"
+" .loop vp_option;\n"
+"fp_option\n"
+" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
+" fp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
+"vp_option\n"
+" \"OPTION\" .emit OPTION .and space .error IDENTIFIER_EXPECTED .and\n"
+" vp_optionString .error INVALID_PROGRAM_OPTION .and semicolon;\n"
+"fp_optionString\n"
+" .if (ARB_precision_hint_nicest == 0x00) \"ARB_precision_hint_fastest\"\n"
+" .emit ARB_PRECISION_HINT_FASTEST .load ARB_precision_hint_fastest 0x01 .or\n"
+" .if (ARB_precision_hint_fastest == 0x00) \"ARB_precision_hint_nicest\"\n"
+" .emit ARB_PRECISION_HINT_NICEST .load ARB_precision_hint_nicest 0x01 .or\n"
+" fp_ARB_fog_exp .emit ARB_FOG_EXP .load ARB_fog_exp 0x01 .or\n"
+" fp_ARB_fog_exp2 .emit ARB_FOG_EXP2 .load ARB_fog_exp2 0x01 .or\n"
+" fp_ARB_fog_linear .emit ARB_FOG_LINEAR .load ARB_fog_linear 0x01 .or\n"
+" .if (fragment_program_shadow != 0x00) \"ARB_fragment_program_shadow\"\n"
+" .emit ARB_FRAGMENT_PROGRAM_SHADOW .load ARB_fragment_program_shadow 0x01;\n"
+"vp_optionString\n"
+" \"ARB_position_invariant\" .emit ARB_POSITION_INVARIANT .load ARB_position_invariant 0x01;\n"
+"fp_ARB_fog_exp\n"
+" .if (ARB_fog_exp2 == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp\";\n"
+"fp_ARB_fog_exp2\n"
+" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_linear == 0x00) \"ARB_fog_exp2\";\n"
+"fp_ARB_fog_linear\n"
+" .if (ARB_fog_exp == 0x00) .true .and .if (ARB_fog_exp2 == 0x00) \"ARB_fog_linear\";\n"
+"fp_statementSequence\n"
+" .loop fp_statement;\n"
+"vp_statementSequence\n"
+" .loop vp_statement;\n"
+"fp_statement\n"
+" fp_statement_1 .or fp_statement_2;\n"
+"vp_statement\n"
+" vp_statement_1 .or vp_statement_2;\n"
+"fp_statement_1\n"
+" fp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
+"fp_statement_2\n"
+" fp_namingStatement .emit DECLARATION .and semicolon;\n"
+"vp_statement_1\n"
+" vp_instruction .emit INSTRUCTION .emit $ .and semicolon;\n"
+"vp_statement_2\n"
+" vp_namingStatement .emit DECLARATION .and semicolon;\n"
+"fp_instruction\n"
+" ALUInstruction .emit OP_ALU_INST .or\n"
+" TexInstruction .emit OP_TEX_INST;\n"
+"vp_instruction\n"
+" ARL_instruction .emit OP_ALU_ARL .or\n"
+" vp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
+" vp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
+" vp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
+" vp_BINop_instruction .emit OP_ALU_BIN .or\n"
+" vp_TRIop_instruction .emit OP_ALU_TRI .or\n"
+" vp_SWZ_instruction .emit OP_ALU_SWZ;\n"
+"ALUInstruction\n"
+" fp_VECTORop_instruction .emit OP_ALU_VECTOR .or\n"
+" fp_SCALARop_instruction .emit OP_ALU_SCALAR .or\n"
+" fp_BINSCop_instruction .emit OP_ALU_BINSC .or\n"
+" fp_BINop_instruction .emit OP_ALU_BIN .or\n"
+" fp_TRIop_instruction .emit OP_ALU_TRI .or\n"
+" fp_SWZ_instruction .emit OP_ALU_SWZ;\n"
+"TexInstruction\n"
+" SAMPLE_instruction .emit OP_TEX_SAMPLE .or\n"
+" KIL_instruction .emit OP_TEX_KIL;\n"
+"ARL_instruction\n"
+" \"ARL\" .emit OP_ARL .and space_dst .and maskedAddrReg .and comma .and vp_scalarSrcReg;\n"
+"fp_VECTORop_instruction\n"
+" fp_VECTORop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg;\n"
+"vp_VECTORop_instruction\n"
+" vp_VECTORop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg;\n"
+"fp_VECTORop\n"
+" \"ABS\" .emit OP_ABS .or \"ABS_SAT\" .emit OP_ABS_SAT .or\n"
+" \"FLR\" .emit OP_FLR .or \"FLR_SAT\" .emit OP_FLR_SAT .or\n"
+" \"FRC\" .emit OP_FRC .or \"FRC_SAT\" .emit OP_FRC_SAT .or\n"
+" \"LIT\" .emit OP_LIT .or \"LIT_SAT\" .emit OP_LIT_SAT .or\n"
+" \"MOV\" .emit OP_MOV .or \"MOV_SAT\" .emit OP_MOV_SAT;\n"
+"vp_VECTORop\n"
+" \"ABS\" .emit OP_ABS .or\n"
+" \"FLR\" .emit OP_FLR .or\n"
+" \"FRC\" .emit OP_FRC .or\n"
+" \"LIT\" .emit OP_LIT .or\n"
+" \"MOV\" .emit OP_MOV;\n"
+"fp_SCALARop_instruction\n"
+" fp_SCALARop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg;\n"
+"vp_SCALARop_instruction\n"
+" vp_SCALARop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg;\n"
+"fp_SCALARop\n"
+" \"COS\" .emit OP_COS .or \"COS_SAT\" .emit OP_COS_SAT .or\n"
+" \"EX2\" .emit OP_EX2 .or \"EX2_SAT\" .emit OP_EX2_SAT .or\n"
+" \"LG2\" .emit OP_LG2 .or \"LG2_SAT\" .emit OP_LG2_SAT .or\n"
+" \"RCP\" .emit OP_RCP .or \"RCP_SAT\" .emit OP_RCP_SAT .or\n"
+" \"RSQ\" .emit OP_RSQ .or \"RSQ_SAT\" .emit OP_RSQ_SAT .or\n"
+" \"SIN\" .emit OP_SIN .or \"SIN_SAT\" .emit OP_SIN_SAT .or\n"
+" \"SCS\" .emit OP_SCS .or \"SCS_SAT\" .emit OP_SCS_SAT;\n"
+"vp_SCALARop\n"
+" \"EX2\" .emit OP_EX2 .or\n"
+" \"EXP\" .emit OP_EXP .or\n"
+" \"LG2\" .emit OP_LG2 .or\n"
+" \"LOG\" .emit OP_LOG .or\n"
+" \"RCP\" .emit OP_RCP .or\n"
+" \"RSQ\" .emit OP_RSQ;\n"
+"fp_BINSCop_instruction\n"
+" fp_BINSCop .and space_dst .and fp_maskedDstReg .and comma .and fp_scalarSrcReg .and comma .and\n"
+" fp_scalarSrcReg;\n"
+"vp_BINSCop_instruction\n"
+" vp_BINSCop .and space_dst .and vp_maskedDstReg .and comma .and vp_scalarSrcReg .and comma .and\n"
+" vp_scalarSrcReg;\n"
+"fp_BINSCop\n"
+" \"POW\" .emit OP_POW .or \"POW_SAT\" .emit OP_POW_SAT;\n"
+"vp_BINSCop\n"
+" \"POW\" .emit OP_POW;\n"
+"fp_BINop_instruction\n"
+" fp_BINop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
+" vectorSrcReg;\n"
+"vp_BINop_instruction\n"
+" vp_BINop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
+" swizzleSrcReg;\n"
+"fp_BINop\n"
+" \"ADD\" .emit OP_ADD .or \"ADD_SAT\" .emit OP_ADD_SAT .or\n"
+" \"DP3\" .emit OP_DP3 .or \"DP3_SAT\" .emit OP_DP3_SAT .or\n"
+" \"DP4\" .emit OP_DP4 .or \"DP4_SAT\" .emit OP_DP4_SAT .or\n"
+" \"DPH\" .emit OP_DPH .or \"DPH_SAT\" .emit OP_DPH_SAT .or\n"
+" \"DST\" .emit OP_DST .or \"DST_SAT\" .emit OP_DST_SAT .or\n"
+" \"MAX\" .emit OP_MAX .or \"MAX_SAT\" .emit OP_MAX_SAT .or\n"
+" \"MIN\" .emit OP_MIN .or \"MIN_SAT\" .emit OP_MIN_SAT .or\n"
+" \"MUL\" .emit OP_MUL .or \"MUL_SAT\" .emit OP_MUL_SAT .or\n"
+" \"SGE\" .emit OP_SGE .or \"SGE_SAT\" .emit OP_SGE_SAT .or\n"
+" \"SLT\" .emit OP_SLT .or \"SLT_SAT\" .emit OP_SLT_SAT .or\n"
+" \"SUB\" .emit OP_SUB .or \"SUB_SAT\" .emit OP_SUB_SAT .or\n"
+" \"XPD\" .emit OP_XPD .or \"XPD_SAT\" .emit OP_XPD_SAT;\n"
+"vp_BINop\n"
+" \"ADD\" .emit OP_ADD .or\n"
+" \"DP3\" .emit OP_DP3 .or\n"
+" \"DP4\" .emit OP_DP4 .or\n"
+" \"DPH\" .emit OP_DPH .or\n"
+" \"DST\" .emit OP_DST .or\n"
+" \"MAX\" .emit OP_MAX .or\n"
+" \"MIN\" .emit OP_MIN .or\n"
+" \"MUL\" .emit OP_MUL .or\n"
+" \"SGE\" .emit OP_SGE .or\n"
+" \"SLT\" .emit OP_SLT .or\n"
+" \"SUB\" .emit OP_SUB .or\n"
+" \"XPD\" .emit OP_XPD;\n"
+"fp_TRIop_instruction\n"
+" fp_TRIop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
+" vectorSrcReg .and comma .and vectorSrcReg;\n"
+"vp_TRIop_instruction\n"
+" vp_TRIop .and space_dst .and vp_maskedDstReg .and comma .and swizzleSrcReg .and comma .and\n"
+" swizzleSrcReg .and comma .and swizzleSrcReg;\n"
+"fp_TRIop\n"
+" \"CMP\" .emit OP_CMP .or \"CMP_SAT\" .emit OP_CMP_SAT .or\n"
+" \"LRP\" .emit OP_LRP .or \"LRP_SAT\" .emit OP_LRP_SAT .or\n"
+" \"MAD\" .emit OP_MAD .or \"MAD_SAT\" .emit OP_MAD_SAT;\n"
+"vp_TRIop\n"
+" \"MAD\" .emit OP_MAD;\n"
+"fp_SWZ_instruction\n"
+" SWZop .and space_dst .and fp_maskedDstReg .and comma .and fp_srcReg .and comma .and\n"
+" fp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
+"vp_SWZ_instruction\n"
+" \"SWZ\" .emit OP_SWZ .and space_dst .and vp_maskedDstReg .and comma .and vp_srcReg .and comma .and\n"
+" vp_extendedSwizzle .error EXT_SWIZ_COMP_EXPECTED;\n"
+"SWZop\n"
+" \"SWZ\" .emit OP_SWZ .or \"SWZ_SAT\" .emit OP_SWZ_SAT;\n"
+"SAMPLE_instruction\n"
+" SAMPLEop .and space_dst .and fp_maskedDstReg .and comma .and vectorSrcReg .and comma .and\n"
+" texImageUnit .and comma .and texTarget .error TEX_TARGET_EXPECTED;\n"
+"SAMPLEop\n"
+" \"TEX\" .emit OP_TEX .or \"TEX_SAT\" .emit OP_TEX_SAT .or\n"
+" \"TXB\" .emit OP_TXB .or \"TXB_SAT\" .emit OP_TXB_SAT .or\n"
+" \"TXP\" .emit OP_TXP .or \"TXP_SAT\" .emit OP_TXP_SAT;\n"
+"KIL_instruction\n"
+" \"KIL\" .emit OP_KIL .and space_src .and vectorSrcReg;\n"
+"texImageUnit\n"
+" \"texture\" .error TEXTURE_EXPECTED .and optTexImageUnitNum;\n"
+"texTarget\n"
+" \"1D\" .emit TEXTARGET_1D .or\n"
+" \"2D\" .emit TEXTARGET_2D .or\n"
+" \"3D\" .emit TEXTARGET_3D .or\n"
+" .if (texture_rectangle != 0x00) \"RECT\" .emit TEXTARGET_RECT .or\n"
+" \"CUBE\" .emit TEXTARGET_CUBE .or\n"
+" .if (ARB_fragment_program_shadow != 0x00) shadowTarget;\n"
+"shadowTarget\n"
+" \"SHADOW1D\" .emit TEXTARGET_SHADOW1D .or\n"
+" \"SHADOW2D\" .emit TEXTARGET_SHADOW2D .or\n"
+" .if (texture_rectangle != 0x00) \"SHADOWRECT\" .emit TEXTARGET_SHADOWRECT;\n"
+"optTexImageUnitNum\n"
+" optTexImageUnitNum_1 .or .true .emit 0x00;\n"
+"optTexImageUnitNum_1\n"
+" lbracket_ne .and texImageUnitNum .and rbracket;\n"
+"texImageUnitNum\n"
+" integer;\n"
+"fp_scalarSrcReg\n"
+" optionalSign .and fp_srcReg .and fp_scalarSuffix;\n"
+"vp_scalarSrcReg\n"
+" optionalSign .and vp_srcReg .and vp_scalarSuffix;\n"
+"swizzleSrcReg\n"
+" optionalSign .and vp_srcReg .and swizzleSuffix;\n"
+"vectorSrcReg\n"
+" optionalSign .and fp_srcReg .and optionalSuffix;\n"
+"fp_maskedDstReg\n"
+" fp_dstReg .and fp_optionalMask;\n"
+"vp_maskedDstReg\n"
+" vp_dstReg .and vp_optionalMask;\n"
+"maskedAddrReg\n"
+" addrReg .error ADDRESS_REGISTER_EXPECTED .and addrWriteMask;\n"
+"fp_extendedSwizzle\n"
+" rgbaExtendedSwizzle .or xyzwExtendedSwizzle;\n"
+"vp_extendedSwizzle\n"
+" extSwizComp .and comma .and\n"
+" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" extSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" extSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"xyzwExtendedSwizzle\n"
+" xyzwExtSwizComp .and comma .and\n"
+" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" xyzwExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"rgbaExtendedSwizzle\n"
+" rgbaExtendedSwizzle_1 .or rgbaExtendedSwizzle_2 .or rgbaExtendedSwizzle_3 .or\n"
+" rgbaExtendedSwizzle_4;\n"
+"rgbaExtendedSwizzle_1\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp;\n"
+"rgbaExtendedSwizzle_2\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_digit .and comma .and\n"
+" rgbaExtSwizComp_alpha .and comma .and rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"rgbaExtendedSwizzle_3\n"
+" rgbaExtSwizComp_digit .and comma .and rgbaExtSwizComp_alpha .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"rgbaExtendedSwizzle_4\n"
+" rgbaExtSwizComp_alpha .and comma .and \n"
+"rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED .and comma .and\n"
+" rgbaExtSwizComp .error EXT_SWIZ_COMP_EXPECTED;\n"
+"xyzwExtSwizComp\n"
+" optionalSign .and xyzwExtSwizSel;\n"
+"rgbaExtSwizComp\n"
+" optionalSign .and rgbaExtSwizSel;\n"
+"rgbaExtSwizComp_digit\n"
+" optionalSign .and rgbaExtSwizSel_digit;\n"
+"rgbaExtSwizComp_alpha\n"
+" optionalSign .and rgbaExtSwizSel_alpha;\n"
+"extSwizComp\n"
+" optionalSign .and extSwizSel;\n"
+"xyzwExtSwizSel\n"
+" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or xyzwComponent_single;\n"
+"rgbaExtSwizSel\n"
+" rgbaExtSwizSel_digit .or rgbaExtSwizSel_alpha;\n"
+"rgbaExtSwizSel_digit\n"
+" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1;\n"
+"rgbaExtSwizSel_alpha\n"
+" rgbaComponent_single;\n"
+"extSwizSel\n"
+" \"0\" .emit COMPONENT_0 .or \"1\" .emit COMPONENT_1 .or vp_component_single;\n"
+"fp_srcReg\n"
+" fp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
+"vp_srcReg\n"
+" vp_srcReg_1 .error SOURCE_REGISTER_EXPECTED;\n"
+"fp_srcReg_1\n"
+" fragmentAttribReg .emit REGISTER_ATTRIB .or\n"
+" fp_progParamReg .emit REGISTER_PARAM .or\n"
+" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"vp_srcReg_1\n"
+" vertexAttribReg .emit REGISTER_ATTRIB .or\n"
+" vp_progParamReg .emit REGISTER_PARAM .or\n"
+" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"fp_dstReg\n"
+" fp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
+"vp_dstReg\n"
+" vp_dstReg_1 .error DESTINATION_REGISTER_EXPECTED;\n"
+"fp_dstReg_1\n"
+" fragmentResultReg .emit REGISTER_RESULT .or\n"
+" fp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"vp_dstReg_1\n"
+" vertexResultReg .emit REGISTER_RESULT .or\n"
+" vp_temporaryReg .emit REGISTER_ESTABLISHED_NAME;\n"
+"fragmentAttribReg\n"
+" fragAttribBinding;\n"
+"vertexAttribReg\n"
+" vtxAttribBinding;\n"
+"fp_temporaryReg\n"
+" fp_establishedName_no_error_on_identifier;\n"
+"vp_temporaryReg\n"
+" vp_establishedName_no_error_on_identifier;\n"
+"fp_progParamReg\n"
+" fp_paramSingleItemUse .or fp_progParamReg_1 .or fp_progParamSingle;\n"
+"vp_progParamReg\n"
+" vp_paramSingleItemUse .or vp_progParamReg_1 .or vp_progParamSingle;\n"
+"fp_progParamReg_1\n"
+" fp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayAbs .and\n"
+" rbracket;\n"
+"vp_progParamReg_1\n"
+" vp_progParamArray .emit PARAM_ARRAY_ELEMENT .and lbracket_ne .and progParamArrayMem .and\n"
+" rbracket;\n"
+"fp_progParamSingle\n"
+" .false;\n"
+"vp_progParamSingle\n"
+" .false;\n"
+"fp_progParamArray\n"
+" fp_establishedName_no_error_on_identifier;\n"
+"vp_progParamArray\n"
+" vp_establishedName_no_error_on_identifier;\n"
+"progParamArrayMem\n"
+" progParamArrayAbs .or progParamArrayRel;\n"
+"progParamArrayAbs\n"
+" integer_ne .emit ARRAY_INDEX_ABSOLUTE;\n"
+"progParamArrayRel\n"
+" addrReg .error ADDRESS_REGISTER_OR_INTEGER_EXPECTED .emit ARRAY_INDEX_RELATIVE .and\n"
+" addrComponent .and addrRegRelOffset;\n"
+"addrRegRelOffset\n"
+" addrRegRelOffset_1 .or addrRegRelOffset_2 .or .true .emit 0x00;\n"
+"addrRegRelOffset_1\n"
+" plus_ne .and addrRegPosOffset;\n"
+"addrRegRelOffset_2\n"
+" minus_ne .and addrRegNegOffset;\n"
+"addrRegPosOffset\n"
+" integer_0_63;\n"
+"addrRegNegOffset\n"
+" integer_0_64;\n"
+"fragmentResultReg\n"
+" fp_resultBinding;\n"
+"vertexResultReg\n"
+" vp_resultBinding;\n"
+"addrReg\n"
+" vp_establishedName_no_error_on_identifier;\n"
+"addrComponent\n"
+" dot .and \"x\" .error INVALID_ADDRESS_COMPONENT .emit COMPONENT_X .emit COMPONENT_X\n"
+" .emit COMPONENT_X .emit COMPONENT_X;\n"
+"addrWriteMask\n"
+" dot .and \"x\" .error INVALID_ADDRESS_WRITEMASK .emit 0x08;\n"
+"fp_scalarSuffix\n"
+" dot .and fp_component_single .error INVALID_COMPONENT;\n"
+"vp_scalarSuffix\n"
+" dot .and vp_component_single .error INVALID_COMPONENT;\n"
+"swizzleSuffix\n"
+" swizzleSuffix_1 .or\n"
+" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
+"swizzleSuffix_1\n"
+" dot_ne .and swizzleSuffix_2 .error INVALID_SUFFIX;\n"
+"swizzleSuffix_2\n"
+" swizzleSuffix_3 .or swizzleSuffix_4;\n"
+"swizzleSuffix_3\n"
+" vp_component_multi .and vp_component_multi .and vp_component_multi .error INVALID_COMPONENT .and\n"
+" vp_component_multi .error INVALID_COMPONENT;\n"
+"swizzleSuffix_4\n"
+" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
+" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
+" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
+"optionalSuffix\n"
+" optionalSuffix_1 .or\n"
+" .true .emit COMPONENT_X .emit COMPONENT_Y .emit COMPONENT_Z .emit COMPONENT_W;\n"
+"optionalSuffix_1\n"
+" dot_ne .and optionalSuffix_2 .error INVALID_SUFFIX;\n"
+"optionalSuffix_2\n"
+" optionalSuffix_3 .or optionalSuffix_4 .or optionalSuffix_5;\n"
+"optionalSuffix_3\n"
+" xyzwComponent_multi .and xyzwComponent_multi .and\n"
+" xyzwComponent_multi .error INVALID_COMPONENT .and xyzwComponent_multi .error INVALID_COMPONENT;\n"
+"optionalSuffix_4\n"
+" rgbaComponent_multi .and rgbaComponent_multi .and\n"
+" rgbaComponent_multi .error INVALID_COMPONENT .and rgbaComponent_multi .error INVALID_COMPONENT;\n"
+"optionalSuffix_5\n"
+" \"x\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
+" \"y\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
+" \"z\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .or\n"
+" \"r\" .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .emit COMPONENT_X .or\n"
+" \"g\" .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .emit COMPONENT_Y .or\n"
+" \"b\" .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .emit COMPONENT_Z .or\n"
+" \"a\" .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W .emit COMPONENT_W;\n"
+"fp_component_single\n"
+" xyzwComponent_single .or rgbaComponent_single;\n"
+"vp_component_multi\n"
+" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
+" 'w' .emit COMPONENT_W;\n"
+"vp_component_single\n"
+" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W;\n"
+"xyzwComponent_multi\n"
+" 'x' .emit COMPONENT_X .or 'y' .emit COMPONENT_Y .or 'z' .emit COMPONENT_Z .or\n"
+" 'w' .emit COMPONENT_W;\n"
+"xyzwComponent_single\n"
+" \"x\" .emit COMPONENT_X .or \"y\" .emit COMPONENT_Y .or \"z\" .emit COMPONENT_Z .or\n"
+" \"w\" .emit COMPONENT_W;\n"
+"rgbaComponent_multi\n"
+" 'r' .emit COMPONENT_X .or 'g' .emit COMPONENT_Y .or 'b' .emit COMPONENT_Z .or\n"
+" 'a' .emit COMPONENT_W;\n"
+"rgbaComponent_single\n"
+" \"r\" .emit COMPONENT_X .or \"g\" .emit COMPONENT_Y .or \"b\" .emit COMPONENT_Z .or\n"
+" \"a\" .emit COMPONENT_W;\n"
+"fp_optionalMask\n"
+" rgbaMask .or xyzwMask .or .true .emit 0x0F;\n"
+"vp_optionalMask\n"
+" xyzwMask .or .true .emit 0x0F;\n"
+"xyzwMask\n"
+" dot_ne .and xyzwMask_1 .error INVALID_WRITEMASK;\n"
+"xyzwMask_1\n"
+" \"xyzw\" .emit 0x0F .or \"xyz\" .emit 0x0E .or \"xyw\" .emit 0x0D .or \"xy\" .emit 0x0C .or\n"
+" \"xzw\" .emit 0x0B .or \"xz\" .emit 0x0A .or \"xw\" .emit 0x09 .or \"x\" .emit 0x08 .or\n"
+" \"yzw\" .emit 0x07 .or \"yz\" .emit 0x06 .or \"yw\" .emit 0x05 .or \"y\" .emit 0x04 .or\n"
+" \"zw\" .emit 0x03 .or \"z\" .emit 0x02 .or \"w\" .emit 0x01;\n"
+"rgbaMask\n"
+" dot_ne .and rgbaMask_1;\n"
+"rgbaMask_1\n"
+" \"rgba\" .emit 0x0F .or \"rgb\" .emit 0x0E .or \"rga\" .emit 0x0D .or \"rg\" .emit 0x0C .or\n"
+" \"rba\" .emit 0x0B .or \"rb\" .emit 0x0A .or \"ra\" .emit 0x09 .or \"r\" .emit 0x08 .or\n"
+" \"gba\" .emit 0x07 .or \"gb\" .emit 0x06 .or \"ga\" .emit 0x05 .or \"g\" .emit 0x04 .or\n"
+" \"ba\" .emit 0x03 .or \"b\" .emit 0x02 .or \"a\" .emit 0x01;\n"
+"fp_namingStatement\n"
+" fp_ATTRIB_statement .emit ATTRIB .or\n"
+" fp_PARAM_statement .emit PARAM .or\n"
+" fp_TEMP_statement .emit TEMP .or\n"
+" fp_OUTPUT_statement .emit OUTPUT .or\n"
+" fp_ALIAS_statement .emit ALIAS;\n"
+"vp_namingStatement\n"
+" vp_ATTRIB_statement .emit ATTRIB .or\n"
+" vp_PARAM_statement .emit PARAM .or\n"
+" vp_TEMP_statement .emit TEMP .or\n"
+" ADDRESS_statement .emit ADDRESS .or\n"
+" vp_OUTPUT_statement .emit OUTPUT .or\n"
+" vp_ALIAS_statement .emit ALIAS;\n"
+"fp_ATTRIB_statement\n"
+" \"ATTRIB\" .and space .and fp_establishName .and equal .and\n"
+" fragAttribBinding .error FRAGMENT_EXPECTED;\n"
+"vp_ATTRIB_statement\n"
+" \"ATTRIB\" .and space .and vp_establishName .and equal .and\n"
+" vtxAttribBinding .error VERTEX_EXPECTED;\n"
+"fragAttribBinding\n"
+" \"fragment\" .and dot .and fragAttribItem .error INVALID_FRAGMENT_PROPERTY;\n"
+"vtxAttribBinding\n"
+" \"vertex\" .and dot .and vtxAttribItem .error INVALID_VERTEX_PROPERTY;\n"
+"fragAttribItem\n"
+" fragAttribItem_1 .emit FRAGMENT_ATTRIB_COLOR .or\n"
+" fragAttribItem_2 .emit FRAGMENT_ATTRIB_TEXCOORD .or\n"
+" .if (fog_coord != 0x00) \"fogcoord\" .emit FRAGMENT_ATTRIB_FOGCOORD .or\n"
+" \"position\" .emit FRAGMENT_ATTRIB_POSITION;\n"
+"fragAttribItem_1\n"
+" \"color\" .and optColorType;\n"
+"fragAttribItem_2\n"
+" \"texcoord\" .and optTexCoordNum;\n"
+"vtxAttribItem\n"
+" \"position\" .emit VERTEX_ATTRIB_POSITION .or\n"
+" .if (vertex_blend != 0x00) vtxAttribItem_1 .emit VERTEX_ATTRIB_WEIGHT .or\n"
+" \"normal\" .emit VERTEX_ATTRIB_NORMAL .or\n"
+" vtxAttribItem_2 .emit VERTEX_ATTRIB_COLOR .or\n"
+" \"fogcoord\" .emit VERTEX_ATTRIB_FOGCOORD .or\n"
+" vtxAttribItem_3 .emit VERTEX_ATTRIB_TEXCOORD .or\n"
+" .if (matrix_palette != 0x00) vtxAttribItem_4 .emit VERTEX_ATTRIB_MATRIXINDEX .or\n"
+" vtxAttribItem_5 .emit VERTEX_ATTRIB_GENERIC;\n"
+"vtxAttribItem_1\n"
+" \"weight\" .and vtxOptWeightNum;\n"
+"vtxAttribItem_2\n"
+" \"color\" .and optColorType;\n"
+"vtxAttribItem_3\n"
+" \"texcoord\" .and optTexCoordNum;\n"
+"vtxAttribItem_4\n"
+" \"matrixindex\" .and lbracket .and vtxWeightNum .and rbracket;\n"
+"vtxAttribItem_5\n"
+" \"attrib\" .and lbracket .and vtxAttribNum .and rbracket;\n"
+"vtxAttribNum\n"
+" integer;\n"
+"vtxOptWeightNum\n"
+" vtxOptWeightNum_1 .or .true .emit 0x00;\n"
+"vtxOptWeightNum_1\n"
+" lbracket_ne .and vtxWeightNum .and rbracket;\n"
+"vtxWeightNum\n"
+" integer;\n"
+"fp_PARAM_statement\n"
+" fp_PARAM_multipleStmt .or fp_PARAM_singleStmt;\n"
+"vp_PARAM_statement\n"
+" vp_PARAM_multipleStmt .or vp_PARAM_singleStmt;\n"
+"fp_PARAM_singleStmt\n"
+" \"PARAM\" .and space .and fp_establishName .and .true .emit 0x00 .and fp_paramSingleInit .and\n"
+" .true .emit PARAM_NULL;\n"
+"vp_PARAM_singleStmt\n"
+" \"PARAM\" .and space .and vp_establishName .and .true .emit 0x00 .and vp_paramSingleInit .and\n"
+" .true .emit PARAM_NULL;\n"
+"fp_PARAM_multipleStmt\n"
+" \"PARAM\" .and space .and fp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
+" fp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
+"vp_PARAM_multipleStmt\n"
+" \"PARAM\" .and space .and vp_establishName .and lbracket_ne .and optArraySize .and rbracket .and\n"
+" vp_paramMultipleInit .and .true .emit PARAM_NULL;\n"
+"optArraySize\n"
+" optional_integer;\n"
+"fp_paramSingleInit\n"
+" equal .and fp_paramSingleItemDecl;\n"
+"vp_paramSingleInit\n"
+" equal .and vp_paramSingleItemDecl;\n"
+"fp_paramMultipleInit\n"
+" equal .and lbrace .and fp_paramMultInitList .and rbrace;\n"
+"vp_paramMultipleInit\n"
+" equal .and lbrace .and vp_paramMultInitList .and rbrace;\n"
+"fp_paramMultInitList\n"
+" fp_paramMultInitList_1 .or fp_paramMultipleItem;\n"
+"vp_paramMultInitList\n"
+" vp_paramMultInitList_1 .or vp_paramMultipleItem;\n"
+"fp_paramMultInitList_1\n"
+" fp_paramMultipleItem .and comma_ne .and fp_paramMultInitList;\n"
+"vp_paramMultInitList_1\n"
+" vp_paramMultipleItem .and comma_ne .and vp_paramMultInitList;\n"
+"fp_paramSingleItemDecl\n"
+" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"vp_paramSingleItemDecl\n"
+" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"fp_paramSingleItemUse\n"
+" fp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstUse .emit PARAM_CONSTANT;\n"
+"vp_paramSingleItemUse\n"
+" vp_stateSingleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programSingleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstUse .emit PARAM_CONSTANT;\n"
+"fp_paramMultipleItem\n"
+" fp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"vp_paramMultipleItem\n"
+" vp_stateMultipleItem .emit PARAM_STATE_ELEMENT .or\n"
+" programMultipleItem .emit PARAM_PROGRAM_ELEMENT .or\n"
+" paramConstDecl .emit PARAM_CONSTANT;\n"
+"fp_stateMultipleItem\n"
+" stateMultipleItem_1 .or fp_stateSingleItem;\n"
+"vp_stateMultipleItem\n"
+" stateMultipleItem_1 .or vp_stateSingleItem;\n"
+"stateMultipleItem_1\n"
+" \"state\" .and dot .and stateMatrixRows .emit STATE_MATRIX_ROWS;\n"
+"fp_stateSingleItem\n"
+" \"state\" .and dot .and fp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
+"vp_stateSingleItem\n"
+" \"state\" .and dot .and vp_stateSingleItem_1 .error INVALID_STATE_PROPERTY;\n"
+"fp_stateSingleItem_1\n"
+" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
+" stateSingleItem_5 .or stateSingleItem_7 .or stateSingleItem_8 .or stateSingleItem_11;\n"
+"vp_stateSingleItem_1\n"
+" stateSingleItem_1 .or stateSingleItem_2 .or stateSingleItem_3 .or stateSingleItem_4 .or\n"
+" stateSingleItem_6 .or stateSingleItem_7 .or stateSingleItem_9 .or stateSingleItem_10 .or\n"
+" stateSingleItem_11;\n"
+"stateSingleItem_1\n"
+" stateMaterialItem .emit STATE_MATERIAL;\n"
+"stateSingleItem_2\n"
+" stateLightItem .emit STATE_LIGHT;\n"
+"stateSingleItem_3\n"
+" stateLightModelItem .emit STATE_LIGHT_MODEL;\n"
+"stateSingleItem_4\n"
+" stateLightProdItem .emit STATE_LIGHT_PROD;\n"
+"stateSingleItem_5\n"
+" stateTexEnvItem .emit STATE_TEX_ENV;\n"
+"stateSingleItem_6\n"
+" stateTexGenItem .emit STATE_TEX_GEN;\n"
+"stateSingleItem_7\n"
+" stateFogItem .emit STATE_FOG;\n"
+"stateSingleItem_8\n"
+" stateDepthItem .emit STATE_DEPTH;\n"
+"stateSingleItem_9\n"
+" stateClipPlaneItem .emit STATE_CLIP_PLANE;\n"
+"stateSingleItem_10\n"
+" statePointItem .emit STATE_POINT;\n"
+"stateSingleItem_11\n"
+" stateMatrixRow .emit STATE_MATRIX_ROWS;\n"
+"stateMaterialItem\n"
+" \"material\" .and optFaceType .and dot .and stateMatProperty .error INVALID_MATERIAL_PROPERTY;\n"
+"stateMatProperty\n"
+" \"ambient\" .emit MATERIAL_AMBIENT .or\n"
+" \"diffuse\" .emit MATERIAL_DIFFUSE .or\n"
+" \"specular\" .emit MATERIAL_SPECULAR .or\n"
+" \"emission\" .emit MATERIAL_EMISSION .or\n"
+" \"shininess\" .emit MATERIAL_SHININESS;\n"
+"stateLightItem\n"
+" \"light\" .and lbracket .and stateLightNumber .and rbracket .and dot .and\n"
+" stateLightProperty .error INVALID_LIGHT_PROPERTY;\n"
+"stateLightProperty\n"
+" \"ambient\" .emit LIGHT_AMBIENT .or\n"
+" \"diffuse\" .emit LIGHT_DIFFUSE .or\n"
+" \"specular\" .emit LIGHT_SPECULAR .or\n"
+" \"position\" .emit LIGHT_POSITION .or\n"
+" \"attenuation\" .emit LIGHT_ATTENUATION .or\n"
+" stateLightProperty_1 .emit LIGHT_SPOT_DIRECTION .or\n"
+" \"half\" .emit LIGHT_HALF;\n"
+"stateLightProperty_1\n"
+" \"spot\" .and dot .and stateSpotProperty .error INVALID_SPOT_PROPERTY;\n"
+"stateSpotProperty\n"
+" \"direction\";\n"
+"stateLightModelItem\n"
+" \"lightmodel\" .and stateLModProperty .error INVALID_LIGHTMODEL_PROPERTY;\n"
+"stateLModProperty\n"
+" stateLModProperty_1 .or stateLModProperty_2;\n"
+"stateLModProperty_1\n"
+" dot .and \"ambient\" .emit LIGHT_MODEL_AMBIENT;\n"
+"stateLModProperty_2\n"
+" stateLModProperty_3 .emit LIGHT_MODEL_SCENECOLOR;\n"
+"stateLModProperty_3\n"
+" optFaceType .and dot .and \"scenecolor\";\n"
+"stateLightProdItem\n"
+" \"lightprod\" .and lbracket .and stateLightNumber .and rbracket .and optFaceType .and dot .and\n"
+" stateLProdProperty .error INVALID_LIGHTPROD_PROPERTY;\n"
+"stateLProdProperty\n"
+" \"ambient\" .emit LIGHT_PROD_AMBIENT .or\n"
+" \"diffuse\" .emit LIGHT_PROD_DIFFUSE .or\n"
+" \"specular\" .emit LIGHT_PROD_SPECULAR;\n"
+"stateLightNumber\n"
+" integer;\n"
+"stateTexEnvItem\n"
+" \"texenv\" .and optLegacyTexUnitNum .and dot .and\n"
+" stateTexEnvProperty .error INVALID_TEXENV_PROPERTY;\n"
+"stateTexEnvProperty\n"
+" \"color\" .emit TEX_ENV_COLOR;\n"
+"optLegacyTexUnitNum\n"
+" lbracket_ne .and legacyTexUnitNum .and rbracket;\n"
+"legacyTexUnitNum\n"
+" integer;\n"
+"stateTexGenItem\n"
+" \"texgen\" .and optTexCoordNum .and dot .and stateTexGenType .error INVALID_TEXGEN_PROPERTY .and\n"
+" dot .and stateTexGenCoord .error INVALID_TEXGEN_COORD;\n"
+"stateTexGenType\n"
+" \"eye\" .emit TEX_GEN_EYE .or\n"
+" \"object\" .emit TEX_GEN_OBJECT;\n"
+"stateTexGenCoord\n"
+" \"s\" .emit COMPONENT_X .or\n"
+" \"t\" .emit COMPONENT_Y .or\n"
+" \"r\" .emit COMPONENT_Z .or\n"
+" \"q\" .emit COMPONENT_W;\n"
+"stateFogItem\n"
+" \"fog\" .and dot .and stateFogProperty .error INVALID_FOG_PROPERTY;\n"
+"stateFogProperty\n"
+" \"color\" .emit FOG_COLOR .or\n"
+" \"params\" .emit FOG_PARAMS;\n"
+"stateDepthItem\n"
+" \"depth\" .and dot .and stateDepthProperty .error INVALID_DEPTH_PROPERTY;\n"
+"stateDepthProperty\n"
+" \"range\" .emit DEPTH_RANGE;\n"
+"stateClipPlaneItem\n"
+" \"clip\" .and lbracket .and stateClipPlaneNum .and rbracket .and dot .and\n"
+" \"plane\" .error INVALID_CLIPPLANE_PROPERTY;\n"
+"stateClipPlaneNum\n"
+" integer;\n"
+"statePointItem\n"
+" \"point\" .and dot .and statePointProperty .error INVALID_POINT_PROPERTY;\n"
+"statePointProperty\n"
+" \"size\" .emit POINT_SIZE .or\n"
+" .if (point_parameters != 0x00) \"attenuation\" .emit POINT_ATTENUATION;\n"
+"stateMatrixRow\n"
+" stateMatrixItem .and dot .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and\n"
+" lbracket .and stateMatrixRowNum .and rbracket .emit 0x0;\n"
+"stateMatrixRows\n"
+" stateMatrixItem .and optMatrixRows;\n"
+"optMatrixRows\n"
+" optMatrixRows_1 .or .true .emit 0x0 .emit '3' .emit 0x0 .emit $;\n"
+"optMatrixRows_1\n"
+" dot_ne .and \"row\" .error MATRIX_ROW_SELECTOR_OR_MODIFIER_EXPECTED .and lbracket .and\n"
+" stateMatrixRowNum .and dotdot .and stateMatrixRowNum .and rbracket;\n"
+"stateMatrixItem\n"
+" \"matrix\" .and dot .and stateMatrixName .error INVALID_MATRIX_NAME .and stateOptMatModifier;\n"
+"stateOptMatModifier\n"
+" stateOptMatModifier_1 .or .true .emit MATRIX_MODIFIER_IDENTITY;\n"
+"stateOptMatModifier_1\n"
+" dot_ne .and stateMatModifier;\n"
+"stateMatModifier\n"
+" \"inverse\" .emit MATRIX_MODIFIER_INVERSE .or\n"
+" \"transpose\" .emit MATRIX_MODIFIER_TRANSPOSE .or\n"
+" \"invtrans\" .emit MATRIX_MODIFIER_INVTRANS;\n"
+"stateMatrixRowNum\n"
+" integer_0_3;\n"
+"stateMatrixName\n"
+" stateMatrixName_1_1 .emit MATRIX_MODELVIEW .or\n"
+" \"projection\" .emit MATRIX_PROJECTION .or\n"
+" \"mvp\" .emit MATRIX_MVP .or\n"
+" stateMatrixName_1_2 .emit MATRIX_TEXTURE .or\n"
+" .if (matrix_palette != 0x00) stateMatrixName_1_3 .emit MATRIX_PALETTE .or\n"
+" stateMatrixName_1_4 .emit MATRIX_PROGRAM;\n"
+"stateMatrixName_1_1\n"
+" \"modelview\" .and stateOptModMatNum;\n"
+"stateMatrixName_1_2\n"
+" \"texture\" .and optTexCoordNum;\n"
+"stateMatrixName_1_3\n"
+" \"palette\" .and lbracket .and statePaletteMatNum .and rbracket;\n"
+"stateMatrixName_1_4\n"
+" \"program\" .and lbracket .and stateProgramMatNum .and rbracket;\n"
+"stateOptModMatNum\n"
+" .if (vertex_blend != 0x00) stateOptModMatNum_1 .or\n"
+" .true .emit 0x00;\n"
+"stateOptModMatNum_1\n"
+" lbracket_ne .and stateModMatNum .and rbracket;\n"
+"stateModMatNum\n"
+" integer;\n"
+"optTexCoordNum\n"
+" optTexCoordNum_1 .or .true .emit 0x00;\n"
+"optTexCoordNum_1\n"
+" lbracket_ne .and texCoordNum .and rbracket;\n"
+"texCoordNum\n"
+" integer;\n"
+"statePaletteMatNum\n"
+" integer;\n"
+"stateProgramMatNum\n"
+" integer;\n"
+"programSingleItem\n"
+" \"program\" .and dot .and programSingleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
+"programSingleItem_1\n"
+" progEnvParam .or progLocalParam;\n"
+"programMultipleItem\n"
+" \"program\" .and dot .and programMultipleItem_1 .error INVALID_PROGRAM_PROPERTY;\n"
+"programMultipleItem_1\n"
+" progEnvParams .or progLocalParams;\n"
+"progEnvParams\n"
+" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNums .and rbracket;\n"
+"progEnvParamNums\n"
+" progEnvParamNums_1 .or progEnvParamNums_2;\n"
+"progEnvParamNums_1\n"
+" progEnvParamNum .and dotdot_ne .and progEnvParamNum;\n"
+"progEnvParamNums_2\n"
+" progEnvParamNum .and .true .emit 0x00;\n"
+"progEnvParam\n"
+" \"env\" .emit PROGRAM_PARAM_ENV .and lbracket .and progEnvParamNum .and rbracket .emit 0x00;\n"
+"progLocalParams\n"
+" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNums .and rbracket;\n"
+"progLocalParamNums\n"
+" progLocalParamNums_1 .or progLocalParamNums_2;\n"
+"progLocalParamNums_1\n"
+" progLocalParamNum .and dotdot_ne .and progLocalParamNum;\n"
+"progLocalParamNums_2\n"
+" progLocalParamNum .and .true .emit 0x00;\n"
+"progLocalParam\n"
+" \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum .and rbracket .emit 0x00;\n"
+"progEnvParamNum\n"
+" integer;\n"
+"progLocalParamNum\n"
+" integer;\n"
+"paramConstDecl\n"
+" paramConstScalarDecl .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
+"paramConstUse\n"
+" paramConstScalarUse .emit CONSTANT_SCALAR .or paramConstVector .emit CONSTANT_VECTOR;\n"
+"paramConstScalarDecl\n"
+" signedFloatConstant;\n"
+"paramConstScalarUse\n"
+" floatConstant;\n"
+"paramConstVector\n"
+" paramConstVector_4 .emit 0x04 .or paramConstVector_3 .emit 0x03 .or\n"
+" paramConstVector_2 .emit 0x02 .or paramConstVector_1 .emit 0x01;\n"
+"paramConstVector_1\n"
+" lbrace_ne .and signedFloatConstant .and rbrace;\n"
+"paramConstVector_2\n"
+" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
+"paramConstVector_3\n"
+" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
+" signedFloatConstant .and rbrace;\n"
+"paramConstVector_4\n"
+" lbrace_ne .and signedFloatConstant .and comma_ne .and signedFloatConstant .and comma_ne .and\n"
+" signedFloatConstant .and comma_ne .and signedFloatConstant .and rbrace;\n"
+"signedFloatConstant\n"
+" optionalSign .and floatConstant;\n"
+"floatConstant\n"
+" float;\n"
+"optionalSign\n"
+" optional_sign_ne;\n"
+"fp_TEMP_statement\n"
+" \"TEMP\" .and space .and fp_varNameList .and .true .emit 0x00;\n"
+"vp_TEMP_statement\n"
+" \"TEMP\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
+"ADDRESS_statement\n"
+" \"ADDRESS\" .and space .and vp_varNameList .and .true .emit 0x00;\n"
+"fp_varNameList\n"
+" fp_varNameList_1 .or fp_establishName;\n"
+"vp_varNameList\n"
+" vp_varNameList_1 .or vp_establishName;\n"
+"fp_varNameList_1\n"
+" fp_establishName .and comma_ne .and fp_varNameList;\n"
+"vp_varNameList_1\n"
+" vp_establishName .and comma_ne .and vp_varNameList;\n"
+"fp_OUTPUT_statement\n"
+" \"OUTPUT\" .and space .and fp_establishName .and equal .and\n"
+" fp_resultBinding .error RESULT_EXPECTED;\n"
+"vp_OUTPUT_statement\n"
+" \"OUTPUT\" .and space .and vp_establishName .and equal .and\n"
+" vp_resultBinding .error RESULT_EXPECTED;\n"
+"fp_resultBinding\n"
+" \"result\" .and dot .and fp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
+"vp_resultBinding\n"
+" \"result\" .and dot .and vp_resultBinding_1 .error INVALID_RESULT_PROPERTY;\n"
+"fp_resultBinding_1\n"
+" \"color\" .emit FRAGMENT_RESULT_COLOR .or\n"
+" \"depth\" .emit FRAGMENT_RESULT_DEPTH;\n"
+"vp_resultBinding_1\n"
+" .if (ARB_position_invariant == 0x00) \"position\" .emit VERTEX_RESULT_POSITION .or\n"
+" resultColBinding .emit VERTEX_RESULT_COLOR .or\n"
+" \"fogcoord\" .emit VERTEX_RESULT_FOGCOORD .or\n"
+" \"pointsize\" .emit VERTEX_RESULT_POINTSIZE .or\n"
+" vp_resultBinding_2 .emit VERTEX_RESULT_TEXCOORD;\n"
+"vp_resultBinding_2\n"
+" \"texcoord\" .and optTexCoordNum;\n"
+"resultColBinding\n"
+" \"color\" .and optFaceType .and optColorType;\n"
+"optFaceType\n"
+" FaceType .or .true .emit FACE_FRONT;\n"
+"FaceType\n"
+" dot_ne .and FaceProperty;\n"
+"FaceProperty\n"
+" \"front\" .emit FACE_FRONT .or \"back\" .emit FACE_BACK;\n"
+"optColorType\n"
+" ColorType .or .true .emit COLOR_PRIMARY;\n"
+"ColorType\n"
+" dot_ne .and ColorProperty;\n"
+"ColorProperty\n"
+" \"primary\" .emit COLOR_PRIMARY .or\n"
+" .if (secondary_color != 0x00) \"secondary\" .emit COLOR_SECONDARY;\n"
+"fp_ALIAS_statement\n"
+" \"ALIAS\" .and fp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and fp_establishedName;\n"
+"vp_ALIAS_statement\n"
+" \"ALIAS\" .and vp_ALIAS_statement_1 .error IDENTIFIER_EXPECTED .and equal .and vp_establishedName;\n"
+"fp_ALIAS_statement_1\n"
+" space .and fp_establishName;\n"
+"vp_ALIAS_statement_1\n"
+" space .and vp_establishName;\n"
+"fp_establishName\n"
+" fp_identifier;\n"
+"vp_establishName\n"
+" vp_identifier;\n"
+"fp_establishedName\n"
+" fp_identifier;\n"
+"vp_establishedName\n"
+" vp_identifier;\n"
+"fp_establishedName_no_error_on_identifier\n"
+" fp_identifier_ne;\n"
+"vp_establishedName_no_error_on_identifier\n"
+" vp_identifier_ne;\n"
+"fp_identifier\n"
+" fp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"vp_identifier\n"
+" vp_identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"fp_identifier_ne\n"
+" fp_not_reserved_identifier .and identifier_ne;\n"
+"vp_identifier_ne\n"
+" vp_not_reserved_identifier .and identifier_ne;\n"
+"fp_not_reserved_identifier\n"
+" fp_not_reserved_identifier_1 .or .true;\n"
+"fp_not_reserved_identifier_1\n"
+" fp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
+"vp_not_reserved_identifier\n"
+" vp_not_reserved_identifier_1 .or .true;\n"
+"vp_not_reserved_identifier_1\n"
+" vp_reserved_identifier .and .false .error RESERVED_KEYWORD;\n"
+"fp_reserved_identifier\n"
+" \"ABS\" .or \"ABS_SAT\" .or \"ADD\" .or \"ADD_SAT\" .or \"ALIAS\" .or \"ATTRIB\" .or \"CMP\" .or \"CMP_SAT\" .or\n"
+" \"COS\" .or \"COS_SAT\" .or \"DP3\" .or \"DP3_SAT\" .or \"DP4\" .or \"DP4_SAT\" .or \"DPH\" .or \"DPH_SAT\" .or\n"
+" \"DST\" .or \"DST_SAT\" .or \"END\" .or \"EX2\" .or \"EX2_SAT\" .or \"FLR\" .or \"FLR_SAT\" .or \"FRC\" .or\n"
+" \"FRC_SAT\" .or \"KIL\" .or \"LG2\" .or \"LG2_SAT\" .or \"LIT\" .or \"LIT_SAT\" .or \"LRP\" .or \"LRP_SAT\" .or\n"
+" \"MAD\" .or \"MAD_SAT\" .or \"MAX\" .or \"MAX_SAT\" .or \"MIN\" .or \"MIN_SAT\" .or \"MOV\" .or \"MOV_SAT\" .or\n"
+" \"MUL\" .or \"MUL_SAT\" .or \"OPTION\" .or \"OUTPUT\" .or \"PARAM\" .or \"POW\" .or \"POW_SAT\" .or \"RCP\" .or\n"
+" \"RCP_SAT\" .or \"RSQ\" .or \"RSQ_SAT\" .or \"SIN\" .or \"SIN_SAT\" .or \"SCS\" .or \"SCS_SAT\" .or \"SGE\" .or\n"
+" \"SGE_SAT\" .or \"SLT\" .or \"SLT_SAT\" .or \"SUB\" .or \"SUB_SAT\" .or \"SWZ\" .or \"SWZ_SAT\" .or \"TEMP\" .or\n"
+" \"TEX\" .or \"TEX_SAT\" .or \"TXB\" .or \"TXB_SAT\" .or \"TXP\" .or \"TXP_SAT\" .or \"XPD\" .or \"XPD_SAT\" .or\n"
+" \"fragment\" .or \"program\" .or \"result\" .or \"state\" .or \"texture\";\n"
+"vp_reserved_identifier\n"
+" \"ABS\" .or \"ADD\" .or \"ADDRESS\" .or \"ALIAS\" .or \"ARL\" .or \"ATTRIB\" .or \"DP3\" .or \"DP4\" .or\n"
+" \"DPH\" .or \"DST\" .or \"END\" .or \"EX2\" .or \"EXP\" .or \"FLR\" .or \"FRC\" .or \"LG2\" .or \"LIT\" .or\n"
+" \"LOG\" .or \"MAD\" .or \"MAX\" .or \"MIN\" .or \"MOV\" .or \"MUL\" .or \"OPTION\" .or \"OUTPUT\" .or\n"
+" \"PARAM\" .or \"POW\" .or \"RCP\" .or \"RSQ\" .or \"SGE\" .or \"SLT\" .or \"SUB\" .or \"SWZ\" .or \"TEMP\" .or\n"
+" \"XPD\" .or \"program\" .or \"result\" .or \"state\" .or \"vertex\";\n"
+"integer\n"
+" integer_ne .error INTEGER_EXPECTED;\n"
+"zero\n"
+" '0';\n"
+"leading_zeroes\n"
+" .loop zero;\n"
+"no_digit\n"
+" no_digit_1 .or .true;\n"
+"no_digit_1\n"
+" digit10 .and .false .error INTEGER_OUT_OF_RANGE;\n"
+"all_zeroes\n"
+" all_zeroes_1 .or no_digit_1;\n"
+"all_zeroes_1\n"
+" '0' .and .loop zero .and no_digit;\n"
+"integer_0_3\n"
+" integer_0_3_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
+"integer_0_3_1\n"
+" integer_0_3_2 .or all_zeroes .emit '0';\n"
+"integer_0_3_2 \n"
+" leading_zeroes .and '1'-'3' .emit * .and no_digit;\n"
+"integer_0_63\n"
+" integer_0_63_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
+"integer_0_63_1\n"
+" integer_0_63_2 .or integer_0_63_3 .or integer_0_63_4 .or integer_0_63_5 .or\n"
+" all_zeroes .emit '0';\n"
+"integer_0_63_2 \n"
+" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
+"integer_0_63_3 \n"
+" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
+"integer_0_63_4 \n"
+" leading_zeroes .and '6' .emit * .and '0'-'3' .emit * .and no_digit;\n"
+"integer_0_63_5 \n"
+" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
+"integer_0_64\n"
+" integer_0_64_1 .error INTEGER_EXPECTED .and .true .emit 0x00 .emit $;\n"
+"integer_0_64_1\n"
+" integer_0_64_2 .or integer_0_64_3 .or integer_0_64_4 .or integer_0_64_5 .or\n"
+" all_zeroes .emit '0';\n"
+"integer_0_64_2 \n"
+" leading_zeroes .and '7'-'9' .emit * .and no_digit;\n"
+"integer_0_64_3 \n"
+" leading_zeroes .and '1'-'5' .emit * .and '0'-'9' .emit * .and no_digit;\n"
+"integer_0_64_4 \n"
+" leading_zeroes .and '6' .emit * .and '0'-'4' .emit * .and no_digit;\n"
+"integer_0_64_5 \n"
+" leading_zeroes .and '1'-'6' .emit * .and no_digit;\n"
+"optional_space\n"
+" space .or .true;\n"
+"space_dst\n"
+" space .error OPERATION_NEEDS_DESTINATION_VARIABLE;\n"
+"space_src\n"
+" space .error OPERATION_NEEDS_SOURCE_VARIABLE;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" white_char .or comment_block;\n"
+"white_char\n"
+" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
+"comment_block\n"
+" '#' .and .loop comment_char .and new_line;\n"
+"comment_char\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"new_line\n"
+" '\\n' .or crlf .or '\\0';\n"
+"crlf\n"
+" '\\r' .and '\\n';\n"
+"semicolon\n"
+" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
+"comma\n"
+" optional_space .and ',' .error MISSING_COMMA .and optional_space;\n"
+"comma_ne\n"
+" optional_space .and ',' .and optional_space;\n"
+"lbracket\n"
+" optional_space .and '[' .error MISSING_LBRACKET .and optional_space;\n"
+"lbracket_ne\n"
+" optional_space .and '[' .and optional_space;\n"
+"rbracket\n"
+" optional_space .and ']' .error MISSING_RBRACKET .and optional_space;\n"
+"dot\n"
+" optional_space .and '.' .error MISSING_DOT .and optional_space;\n"
+"dot_ne\n"
+" optional_space .and '.' .and optional_space;\n"
+"equal\n"
+" optional_space .and '=' .error MISSING_EQUAL .and optional_space;\n"
+"lbrace\n"
+" optional_space .and '{' .error MISSING_LBRACE .and optional_space;\n"
+"lbrace_ne\n"
+" optional_space .and '{' .and optional_space;\n"
+"rbrace\n"
+" optional_space .and '}' .error MISSING_RBRACE .and optional_space;\n"
+"dotdot\n"
+" optional_space .and '.' .and '.' .error MISSING_DOTDOT .and optional_space;\n"
+"dotdot_ne\n"
+" optional_space .and '.' .and '.' .and optional_space;\n"
+"float\n"
+" float_1 .or float_2 .or float_legacy;\n"
+"float_1\n"
+" '.' .emit 0x00 .and integer_ne .error MISSING_FRACTION_OR_EXPONENT .and optional_exponent;\n"
+"float_2\n"
+" integer_ne .and float_3;\n"
+"float_3\n"
+" float_4 .or float_5;\n"
+"float_4\n"
+" '.' .and optional_integer .and optional_exponent;\n"
+"float_5\n"
+" exponent .emit 0x00;\n"
+"float_legacy\n"
+" integer_ne .and .true .emit 0x00 .emit 0x00;\n"
+"integer_ne\n"
+" integer_ne_1 .and .true .emit 0x00 .emit $;\n"
+"integer_ne_1\n"
+" digit10 .emit * .and .loop digit10 .emit *;\n"
+"optional_integer\n"
+" integer_ne .or .true .emit 0x00;\n"
+"optional_exponent\n"
+" exponent .or .true .emit 0x00;\n"
+"exponent\n"
+" exponent_1 .and optional_sign_ne .and integer_ne .error EXPONENT_VALUE_EXPECTED;\n"
+"exponent_1\n"
+" 'e' .or 'E';\n"
+"optional_sign_ne\n"
+" minus_ne .or plus_ne .or .true;\n"
+"plus_ne\n"
+" optional_space .and '+' .and optional_space;\n"
+"minus_ne\n"
+" optional_space .and '-' .emit '-' .and optional_space;\n"
+"identifier_ne\n"
+" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit 0x00 .emit $;\n"
+"follow_idchar\n"
+" first_idchar .or digit10;\n"
+"first_idchar\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
+"digit10\n"
+" '0'-'9';\n"
+".string __string_filter;\n"
+"__string_filter\n"
+" .loop __identifier_char;\n"
+"__identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '$' .or '0'-'9';\n"
+"e_signature\n"
+" e_signature_char .and .loop e_signature_char;\n"
+"e_signature_char\n"
+" '!' .or '.' .or 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
+"e_statement\n"
+" .loop e_statement_not_term;\n"
+"e_statement_not_term\n"
+" '\\x3C'-'\\xFF' .or '\\x0E'-'\\x3A' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"e_identifier\n"
+" e_identifier_first .and .loop e_identifier_next;\n"
+"e_identifier_first\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '$';\n"
+"e_identifier_next\n"
+" e_identifier_first .or '0'-'9';\n"
+"e_token\n"
+" e_identifier .or e_token_number .or '[' .or ']' .or '.' .or '{' .or '}' .or '=' .or '+' .or\n"
+" '-' .or ',' .or ';';\n"
+"e_token_number\n"
+" e_token_digit .and .loop e_token_digit;\n"
+"e_token_digit\n"
+" '0'-'9';\n"
+"e_charordigit\n"
+" 'A'-'Z' .or 'a'-'z' .or '0'-'9';\n"
+""
diff --git a/src/mesa/shader/grammar.c b/src/mesa/shader/grammar.c
index 9644978..0ed347b 100644
--- a/src/mesa/shader/grammar.c
+++ b/src/mesa/shader/grammar.c
@@ -1,2760 +1,2799 @@
-#ifndef GRAMMAR_PORT_BUILD

-#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file

-#endif

-

-/*

-    Last Modified: 2004-II-8

-*/

-

-/*

-    INTRODUCTION

-    ------------

-

-    The task is to check the syntax of an input string. Input string is a stream of ASCII

-    characters terminated with a null-character ('\0'). Checking it using C language is

-    difficult and hard to implement without bugs. It is hard to maintain and make changes when

-    the syntax changes.

-

-    This is because of a high redundancy of the C code. Large blocks of code are duplicated with

-    only small changes. Even use of macros does not solve the problem because macros cannot

-    erase the complexity of the problem.

-

-    The resolution is to create a new language that will be highly oriented to our task. Once

-    we describe a particular syntax, we are done. We can then focus on the code that implements

-    the language. The size and complexity of it is relatively small than the code that directly

-    checks the syntax.

-

-    First, we must implement our new language. Here, the language is implemented in C, but it

-    could also be implemented in any other language. The code is listed below. We must take

-    a good care that it is bug free. This is simple because the code is simple and clean.

-

-    Next, we must describe the syntax of our new language in itself. Once created and checked

-    manually that it is correct, we can use it to check another scripts.

-

-    Note that our new language loading code does not have to check the syntax. It is because we

-    assume that the script describing itself is correct, and other scripts can be syntactically

-    checked by the former script. The loading code must only do semantic checking which leads us to

-    simple resolving references.

-

-    THE LANGUAGE

-    ------------

-

-    Here I will describe the syntax of the new language (further called "Synek"). It is mainly a

-    sequence of declarations terminated by a semicolon. The declaration consists of a symbol,

-    which is an identifier, and its definition. A definition is in turn a sequence of specifiers

-    connected with ".and" or ".or" operator. These operators cannot be mixed together in a one

-    definition. Specifier can be a symbol, string, character, character range or a special

-    keyword ".true" or ".false".

-

-    On the very beginning of the script there is a declaration of a root symbol and is in the form:

-        .syntax <root_symbol>;

-    The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if

-    the root symbol evaluates to true. A symbol evaluates to true if the definition associated with

-    the symbol evaluates to true. Definition evaluation depends on the operator used to connect

-    specifiers in the definition. If ".and" operator is used, definition evaluates to true if and

-    only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to

-    true if any of the specifiers evaluates to true. If definition contains only one specifier,

-    it is evaluated as if it was connected with ".true" keyword by ".and" operator.

-

-    If specifier is a ".true" keyword, it always evaluates to true.

-

-    If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false

-    when it does not evaluate to true.

-

-    Character range specifier is in the form:

-        '<first_character>' - '<second_character>'

-    If specifier is a character range, it evaluates to true if character in the stream is greater

-    or equal to <first_character> and less or equal to <second_character>. In that situation 

-    the stream pointer is advanced to point to next character in the stream. All C-style escape

-    sequences are supported although trigraph sequences are not. The comparisions are performed

-    on 8-bit unsigned integers.

-

-    Character specifier is in the form:

-        '<single_character>'

-    It evaluates to true if the following character range specifier evaluates to true:

-        '<single_character>' - '<single_character>'

-

-    String specifier is in the form:

-        "<string>"

-    Let N be the number of characters in <string>. Let <string>[i] designate i-th character in

-    <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)

-    the following character specifier evaluates to true:

-        '<string>[i]'

-    If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.

-

-    Symbol specifier can be optionally preceded by a ".loop" keyword in the form:

-        .loop <symbol>                  (1)

-    where <symbol> is defined as follows:

-        <symbol> <definition>;          (2)

-    Construction (1) is replaced by the following code:

-        <symbol$1>

-    and declaration (2) is replaced by the following:

-        <symbol$1> <symbol$2> .or .true;

-        <symbol$2> <symbol> .and <symbol$1>;

-        <symbol> <definition>;

-

-    ESCAPE SEQUENCES

-    ----------------

-

-    Synek supports all escape sequences in character specifiers. The mapping table is listed below.

-    All occurences of the characters in the first column are replaced with the corresponding

-    character in the second column.

-

-        Escape sequence         Represents

-    ------------------------------------------------------------------------------------------------

-        \a                      Bell (alert)

-        \b                      Backspace

-        \f                      Formfeed

-        \n                      New line

-        \r                      Carriage return

-        \t                      Horizontal tab

-        \v                      Vertical tab

-        \'                      Single quotation mark

-        \"                      Double quotation mark

-        \\                      Backslash

-        \?                      Literal question mark

-        \ooo                    ASCII character in octal notation

-        \xhhh                   ASCII character in hexadecimal notation

-    ------------------------------------------------------------------------------------------------

-

-    RAISING ERRORS

-    --------------

-

-    Any specifier can be followed by a special construction that is executed when the specifier

-    evaluates to false. The construction is in the form:

-        .error <ERROR_TEXT>

-    <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is

-    in the form:

-        .errtext <ERROR_TEXT> "<error_desc>"

-    When specifier evaluates to false and this construction is present, parsing is stopped

-    immediately and <error_desc> is returned as a result of parsing. The error position is also

-    returned and it is meant as an offset from the beggining of the stream to the character that

-    was valid so far. Example:

-

-        (**** syntax script ****)

-

-        .syntax program;

-        .errtext MISSING_SEMICOLON      "missing ';'"

-        program         declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and

-                        .loop space .and '\0';

-        declaration     "declare" .and .loop space .and identifier;

-        space           ' ';

-

-        (**** sample code ****)

-

-        declare foo ,

-

-    In the example above checking the sample code will result in error message "missing ';'" and

-    error position 12. The sample code is not correct. Note the presence of '\0' specifier to

-    assure that there is no code after semicolon - only spaces.

-    <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,

-    the identifier and dollar signs are replaced by a string retrieved by invoking symbol with

-    the identifier name. The starting position is the error position. The lenght of the resulting

-    string is the position after invoking the symbol.

-

-    PRODUCTION

-    ----------

-

-    Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers

-    that evaluate to true. That is, every specifier and optional error construction can be followed

-    by a number of emit constructions that are in the form:

-        .emit <parameter>

-    <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by

-    0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration

-    in the form:

-        .emtcode <identifier> <hex_number>

-

-    When given specifier evaluates to true, all emits associated with the specifier are output

-    in order they were declared. A star means that last-read character should be output instead

-    of constant value. Example:

-

-        (**** syntax script ****)

-

-        .syntax foobar;

-        .emtcode WORD_FOO       0x01

-        .emtcode WORD_BAR       0x02

-        foobar      FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;

-        FOO         "foo" .and SPACE;

-        BAR         "bar" .and SPACE;

-        SPACE       ' ' .or '\0';

-

-        (**** sample text 1 ****)

-

-        foo

-

-        (**** sample text 2 ****)

-

-        foobar

-

-    For both samples the result will be one-element array. For first sample text it will be

-    value 1, for second - 0. Note that every text will be accepted because of presence of

-    .true as an alternative.

-

-    Another example:

-

-        (**** syntax script ****)

-

-        .syntax declaration;

-        .emtcode VARIABLE       0x01

-        declaration     "declare" .and .loop space .and

-                        identifier .emit VARIABLE .and          (1)

-                        .true .emit 0x00 .and                   (2)

-                        .loop space .and ';';

-        space           ' ' .or '\t';

-        identifier      .loop id_char .emit *;                  (3)

-        id_char         'a'-'z' .or 'A'-'Z' .or '_';

-

-        (**** sample code ****)

-

-        declare    fubar;

-

-    In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to

-    true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used

-    to terminate the string with null to signal when the string ends. Specifier (3) outputs

-    all characters that make declared identifier. The result of sample code will be the

-    following array:

-        { 1, 'f', 'u', 'b', 'a', 'r', 0 }

-

-    If .emit is followed by dollar $, it means that current position should be output. Current

-    position is a 32-bit unsigned integer distance from the very beginning of the parsed string to

-    first character consumed by the specifier associated with the .emit instruction. Current

-    position is stored in the output buffer in Little-Endian convention (the lowest byte comes

-    first).

-*/

-

-static void mem_free (void **);

-

-/*

-    internal error messages

-*/

-static const byte *OUT_OF_MEMORY =          (byte *) "internal error 1001: out of physical memory";

-static const byte *UNRESOLVED_REFERENCE =   (byte *) "internal error 1002: unresolved reference '$'";

-static const byte *INVALID_GRAMMAR_ID =     (byte *) "internal error 1003: invalid grammar object";

-static const byte *INVALID_REGISTER_NAME =  (byte *) "internal error 1004: invalid register name: '$'";

-

-static const byte *error_message = NULL;

-static byte *error_param = NULL;        /* this is inserted into error_message in place of $ */

-static int error_position = -1;

-

-static byte *unknown = (byte *) "???";

-

-static void clear_last_error ()

-{

-    /* reset error message */

-    error_message = NULL;

-

-    /* free error parameter - if error_param is a "???" don't free it - it's static */

-    if (error_param != unknown)

-        mem_free ((void **) &error_param);

-    else

-        error_param = NULL;

-

-    /* reset error position */

-    error_position = -1;

-}

-

-static void set_last_error (const byte *msg, byte *param, int pos)

-{

-    /* error message can only be set only once */

-    if (error_message != NULL)

-    {

-        mem_free (&param);

-        return;

-    }

-

-    error_message = msg;

-

-    if (param != NULL)

-        error_param = param;

-    else

-        error_param = unknown;

-

-    error_position = pos;

-}

-

-/*

-    memory management routines

-*/

-static void *mem_alloc (size_t size)

-{

-    void *ptr = grammar_alloc_malloc (size);

-    if (ptr == NULL)

-        set_last_error (OUT_OF_MEMORY, NULL, -1);

-    return ptr;

-}

-

-static void *mem_copy (void *dst, const void *src, size_t size)

-{

-    return grammar_memory_copy (dst, src, size);

-}

-

-static void mem_free (void **ptr)

-{

-    grammar_alloc_free (*ptr);

-    *ptr = NULL;

-}

-

-static void *mem_realloc (void *ptr, size_t old_size, size_t new_size)

-{

-    void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size);

-    if (ptr2 == NULL)

-        set_last_error (OUT_OF_MEMORY, NULL, -1);

-    return ptr2;

-}

-

-static byte *str_copy_n (byte *dst, const byte *src, size_t max_len)

-{

-    return grammar_string_copy_n (dst, src, max_len);

-}

-

-static byte *str_duplicate (const byte *str)

-{

-    byte *new_str = grammar_string_duplicate (str);

-    if (new_str == NULL)

-        set_last_error (OUT_OF_MEMORY, NULL, -1);

-    return new_str;

-}

-

-static int str_equal (const byte *str1, const byte *str2)

-{

-    return grammar_string_compare (str1, str2) == 0;

-}

-

-static int str_equal_n (const byte *str1, const byte *str2, unsigned int n)

-{

-    return grammar_string_compare_n (str1, str2, n) == 0;

-}

-

-static unsigned int str_length (const byte *str)

-{

-    return grammar_string_length (str);

-}

-

-/*

-    string to byte map typedef

-*/

-typedef struct map_byte_

-{

-    byte *key;

-    byte data;

-    struct map_byte_ *next;

-} map_byte;

-

-static void map_byte_create (map_byte **ma)

-{

-    *ma = mem_alloc (sizeof (map_byte));

-    if (*ma)

-    {

-        (**ma).key = NULL;

-        (**ma).data = '\0';

-        (**ma).next = NULL;

-    }

-}

-

-/* XXX unfold the recursion */

-static void map_byte_destroy (map_byte **ma)

-{

-    if (*ma)

-    {

-        map_byte_destroy (&(**ma).next);

-        mem_free ((void **) &(**ma).key);

-        mem_free ((void **) ma);

-    }

-}

-

-static void map_byte_append (map_byte **ma, map_byte **nm)

-{

-    while (*ma)

-        ma = &(**ma).next;

-    *ma = *nm;

-}

-

-/*

-    searches the map for the specified key,

-    returns pointer to the element with the specified key if it exists

-    returns NULL otherwise

-*/

-map_byte *map_byte_locate (map_byte **ma, const byte *key)

-{

-    while (*ma)

-    {

-        if (str_equal ((**ma).key, key))

-            return *ma;

-

-        ma = &(**ma).next;

-    }

-

-    set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);

-    return NULL;

-}

-

-/*

-    searches the map for specified key,

-    if the key is matched, *data is filled with data associated with the key,

-    returns 0 if the key is matched,

-    returns 1 otherwise

-*/

-static int map_byte_find (map_byte **ma, const byte *key, byte *data)

-{

-    map_byte *found = map_byte_locate (ma, key);

-    if (found != NULL)

-    {

-        *data = found->data;

-

-        return 0;

-    }

-

-    return 1;

-}

-

-/*

-    regbyte context typedef

-

-    Each regbyte consists of its name and a default value. These are static and created at

-    grammar script compile-time, for example the following line:

-        .regbyte vertex_blend      0x00

-    adds a new regbyte named "vertex_blend" to the static list and initializes it to 0.

-    When the script is executed, this regbyte can be accessed by name for read and write. When a

-    particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx

-    stack. The new entry contains information abot which regbyte it references and its new value.

-    When a given regbyte is accessed for read, the stack is searched top-down to find an

-    entry that references the regbyte. The first matching entry is used to return the current

-    value it holds. If no entry is found, the default value is returned.

-*/

-typedef struct regbyte_ctx_

-{

-    map_byte *m_regbyte;

-    byte m_current_value;

-    struct regbyte_ctx_ *m_prev;

-} regbyte_ctx;

-

-static void regbyte_ctx_create (regbyte_ctx **re)

-{

-    *re = mem_alloc (sizeof (regbyte_ctx));

-    if (*re)

-    {

-        (**re).m_regbyte = NULL;

-        (**re).m_prev = NULL;

-    }

-}

-

-static void regbyte_ctx_destroy (regbyte_ctx **re)

-{

-    if (*re)

-    {

-        mem_free ((void **) re);

-    }

-}

-

-static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg)

-{

-    /* first lookup in the register stack */

-    while (*re != NULL)

-    {

-        if ((**re).m_regbyte == reg)

-            return (**re).m_current_value;

-

-        re = &(**re).m_prev;

-    }

-

-    /* if not found - return the default value */

-    return reg->data;

-}

-

-/*

-    emit type typedef

-*/

-typedef enum emit_type_

-{

-    et_byte,            /* explicit number */

-    et_stream,          /* eaten character */

-    et_position         /* current position */

-} emit_type;

-

-/*

-    emit destination typedef

-*/

-typedef enum emit_dest_

-{

-    ed_output,          /* write to the output buffer */

-    ed_regbyte          /* write a particular regbyte */

-} emit_dest;

-

-/*

-    emit typedef

-*/

-typedef struct emit_

-{

-    emit_dest m_emit_dest;

-    emit_type m_emit_type;      /* ed_output */

-    byte m_byte;                /* et_byte */

-    map_byte *m_regbyte;        /* ed_regbyte */

-    byte *m_regname;            /* ed_regbyte - temporary */

-    struct emit_ *m_next;

-} emit;

-

-static void emit_create (emit **em)

-{

-    *em = mem_alloc (sizeof (emit));

-    if (*em)

-    {

-        (**em).m_emit_dest = ed_output;

-        (**em).m_emit_type = et_byte;

-        (**em).m_byte = '\0';

-        (**em).m_regbyte = NULL;

-        (**em).m_regname = NULL;

-        (**em).m_next = NULL;

-    }

-}

-

-static void emit_destroy (emit **em)

-{

-    if (*em)

-    {

-        emit_destroy (&(**em).m_next);

-        mem_free ((void **) &(**em).m_regname);

-        mem_free ((void **) em);

-    }

-}

-

-/*

-    error typedef

-*/

-typedef struct error_

-{

-    byte *m_text;

-    byte *m_token_name;

-    struct rule_ *m_token;

-} error;

-

-static void error_create (error **er)

-{

-    *er = mem_alloc (sizeof (error));

-    if (*er)

-    {

-        (**er).m_text = NULL;

-        (**er).m_token_name = NULL;

-        (**er).m_token = NULL;

-    }

-}

-

-static void error_destroy (error **er)

-{

-    if (*er)

-    {

-        mem_free ((void **) &(**er).m_text);

-        mem_free ((void **) &(**er).m_token_name);

-        mem_free ((void **) er);

-    }

-}

-

-struct dict_;

-static byte *error_get_token (error *, struct dict_ *, const byte *, unsigned int);

-

-/*

-    condition operand type typedef

-*/

-typedef enum cond_oper_type_

-{

-    cot_byte,               /* constant 8-bit unsigned integer */

-    cot_regbyte             /* pointer to byte register containing the current value */

-} cond_oper_type;

-

-/*

-    condition operand typedef

-*/

-typedef struct cond_oper_

-{

-    cond_oper_type m_type;

-    byte m_byte;            /* cot_byte */

-    map_byte *m_regbyte;    /* cot_regbyte */

-    byte *m_regname;        /* cot_regbyte - temporary */

-} cond_oper;

-

-/*

-    condition type typedef

-*/

-typedef enum cond_type_

-{

-    ct_equal,

-    ct_not_equal

-} cond_type;

-

-/*

-    condition typedef

-*/

-typedef struct cond_

-{

-    cond_type m_type;

-    cond_oper m_operands[2];

-} cond;

-

-static void cond_create (cond **co)

-{

-    *co = mem_alloc (sizeof (cond));

-    if (*co)

-    {

-        (**co).m_operands[0].m_regname = NULL;

-        (**co).m_operands[1].m_regname = NULL;

-    }

-}

-

-static void cond_destroy (cond **co)

-{

-    if (*co)

-    {

-        mem_free ((void **) &(**co).m_operands[0].m_regname);

-        mem_free ((void **) &(**co).m_operands[1].m_regname);

-        mem_free ((void **) co);

-    }

-}

-

-/*

-    specifier type typedef

-*/

-typedef enum spec_type_

-{

-    st_false,

-    st_true,

-    st_byte,

-    st_byte_range,

-    st_string,

-    st_identifier,

-    st_identifier_loop,

-    st_debug

-} spec_type;

-

-/*

-    specifier typedef

-*/

-typedef struct spec_

-{

-    spec_type m_spec_type;

-    byte m_byte[2];                 /* st_byte, st_byte_range */

-    byte *m_string;                 /* st_string */

-    struct rule_ *m_rule;           /* st_identifier, st_identifier_loop */

-    emit *m_emits;

-    error *m_errtext;

-    cond *m_cond;

-    struct spec_ *m_next;

-} spec;

-

-static void spec_create (spec **sp)

-{

-    *sp = mem_alloc (sizeof (spec));

-    if (*sp)

-    {

-        (**sp).m_spec_type = st_false;

-        (**sp).m_byte[0] = '\0';

-        (**sp).m_byte[1] = '\0';

-        (**sp).m_string = NULL;

-        (**sp).m_rule = NULL;

-        (**sp).m_emits = NULL;

-        (**sp).m_errtext = NULL;

-        (**sp).m_cond = NULL;

-        (**sp).m_next = NULL;

-    }

-}

-

-static void spec_destroy (spec **sp)

-{

-    if (*sp)

-    {

-        spec_destroy (&(**sp).m_next);

-        emit_destroy (&(**sp).m_emits);

-        error_destroy (&(**sp).m_errtext);

-        mem_free ((void **) &(**sp).m_string);

-        cond_destroy (&(**sp).m_cond);

-        mem_free ((void **) sp);

-    }

-}

-

-static void spec_append (spec **sp, spec **ns)

-{

-    while (*sp)

-        sp = &(**sp).m_next;

-    *sp = *ns;

-}

-

-/*

-    operator typedef

-*/

-typedef enum oper_

-{

-    op_none,

-    op_and,

-    op_or

-} oper;

-

-/*

-    rule typedef

-*/

-typedef struct rule_

-{

-    oper m_oper;

-    spec *m_specs;

-    struct rule_ *m_next;

-/*  int m_referenced; */            /* for debugging purposes */

-} rule;

-

-static void rule_create (rule **ru)

-{

-    *ru = mem_alloc (sizeof (rule));

-    if (*ru)

-    {

-        (**ru).m_oper = op_none;

-        (**ru).m_specs = NULL;

-        (**ru).m_next = NULL;

-/*      (**ru).m_referenced = 0; */

-    }

-}

-

-static void rule_destroy (rule **ru)

-{

-    if (*ru)

-    {

-        rule_destroy (&(**ru).m_next);

-        spec_destroy (&(**ru).m_specs);

-        mem_free ((void **) ru);

-    }

-}

-

-static void rule_append (rule **ru, rule **nr)

-{

-    while (*ru)

-        ru = &(**ru).m_next;

-    *ru = *nr;

-}

-

-/*

-    returns unique grammar id

-*/

-static grammar next_valid_grammar_id ()

-{

-    static grammar id = 0;

-

-    return ++id;

-}

-

-/*

-    dictionary typedef

-*/

-typedef struct dict_

-{

-    rule *m_rulez;

-    rule *m_syntax;

-    rule *m_string;

-    map_byte *m_regbytes;

-    grammar m_id;

-    struct dict_ *m_next;

-} dict;

-

-static void dict_create (dict **di)

-{

-    *di = mem_alloc (sizeof (dict));

-    if (*di)

-    {

-        (**di).m_rulez = NULL;

-        (**di).m_syntax = NULL;

-        (**di).m_string = NULL;

-        (**di).m_regbytes = NULL;

-        (**di).m_id = next_valid_grammar_id ();

-        (**di).m_next = NULL;

-    }

-}

-

-static void dict_destroy (dict **di)

-{

-    if (*di)

-    {

-        rule_destroy (&(**di).m_rulez);

-        map_byte_destroy (&(**di).m_regbytes);

-        mem_free ((void **) di);

-    }

-}

-

-static void dict_append (dict **di, dict **nd)

-{

-    while (*di)

-        di = &(**di).m_next;

-    *di = *nd;

-}

-

-static void dict_find (dict **di, grammar key, dict **data)

-{

-    while (*di)

-    {

-        if ((**di).m_id == key)

-        {

-            *data = *di;

-            return;

-        }

-

-        di = &(**di).m_next;

-    }

-

-    *data = NULL;

-}

-

-static dict *g_dicts = NULL;

-

-/*

-    byte array typedef

-

-    XXX this class is going to be replaced by a faster one, soon

-*/

-typedef struct barray_

-{

-    byte *data;

-    unsigned int len;

-} barray;

-

-static void barray_create (barray **ba)

-{

-    *ba = mem_alloc (sizeof (barray));

-    if (*ba)

-    {

-        (**ba).data = NULL;

-        (**ba).len = 0;

-    }

-}

-

-static void barray_destroy (barray **ba)

-{

-    if (*ba)

-    {

-        mem_free ((void **) &(**ba).data);

-        mem_free ((void **) ba);

-    }

-}

-

-/*

-    reallocates byte array to requested size,

-    returns 0 on success,

-    returns 1 otherwise

-*/

-static int barray_resize (barray **ba, unsigned int nlen)

-{

-    byte *new_pointer;

-

-    if (nlen == 0)

-    {

-        mem_free ((void **) &(**ba).data);

-        (**ba).data = NULL;

-        (**ba).len = 0;

-

-        return 0;

-    }

-    else

-    {

-        new_pointer = mem_realloc ((**ba).data, (**ba).len * sizeof (byte), nlen * sizeof (byte));

-        if (new_pointer)

-        {

-            (**ba).data = new_pointer;

-            (**ba).len = nlen;

-

-            return 0;

-        }

-    }

-

-    return 1;

-}

-

-/*

-    adds byte array pointed by *nb to the end of array pointed by *ba,

-    returns 0 on success,

-    returns 1 otherwise

-*/

-static int barray_append (barray **ba, barray **nb)

-{

-    const unsigned int len = (**ba).len;

-

-    if (barray_resize (ba, (**ba).len + (**nb).len))

-        return 1;

-

-    mem_copy ((**ba).data + len, (**nb).data, (**nb).len);

-

-    return 0;

-}

-

-/*

-    adds emit chain pointed by em to the end of array pointed by *ba,

-    returns 0 on success,

-    returns 1 otherwise

-*/

-static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc)

-{

-    emit *temp = em;

-    unsigned int count = 0;

-

-    while (temp)

-    {

-        if (temp->m_emit_dest == ed_output)

-            if (temp->m_emit_type == et_position)

-                count += 4;     /* position is a 32-bit unsigned integer */

-            else

-                count++;

-

-        temp = temp->m_next;

-    }

-

-    if (barray_resize (ba, (**ba).len + count))

-        return 1;

-

-    while (em)

-    {

-        if (em->m_emit_dest == ed_output)

-        {

-            if (em->m_emit_type == et_byte)

-                (**ba).data[(**ba).len - count--] = em->m_byte;

-            else if (em->m_emit_type == et_stream)

-                (**ba).data[(**ba).len - count--] = c;

-            else // em->type == et_position

-                (**ba).data[(**ba).len - count--] = (byte) pos,

-                (**ba).data[(**ba).len - count--] = (byte) (pos >> 8),

-                (**ba).data[(**ba).len - count--] = (byte) (pos >> 16),

-                (**ba).data[(**ba).len - count--] = (byte) (pos >> 24);

-        }

-        else

-        {

-            regbyte_ctx *new_rbc;

-            regbyte_ctx_create (&new_rbc);

-            if (new_rbc == NULL)

-                return 1;

-

-            new_rbc->m_prev = *rbc;

-            new_rbc->m_regbyte = em->m_regbyte;

-            *rbc = new_rbc;

-

-            if (em->m_emit_type == et_byte)

-                new_rbc->m_current_value = em->m_byte;

-            else if (em->m_emit_type == et_stream)

-                new_rbc->m_current_value = c;

-        }

-

-        em = em->m_next;

-    }

-

-    return 0;

-}

-

-/*

-    string to string map typedef

-*/

-typedef struct map_str_

-{

-    byte *key;

-    byte *data;

-    struct map_str_ *next;

-} map_str;

-

-static void map_str_create (map_str **ma)

-{

-    *ma = mem_alloc (sizeof (map_str));

-    if (*ma)

-    {

-        (**ma).key = NULL;

-        (**ma).data = NULL;

-        (**ma).next = NULL;

-    }

-}

-

-static void map_str_destroy (map_str **ma)

-{

-    if (*ma)

-    {

-        map_str_destroy (&(**ma).next);

-        mem_free ((void **) &(**ma).key);

-        mem_free ((void **) &(**ma).data);

-        mem_free ((void **) ma);

-    }

-}

-

-static void map_str_append (map_str **ma, map_str **nm)

-{

-    while (*ma)

-        ma = &(**ma).next;

-    *ma = *nm;

-}

-

-/*

-    searches the map for specified key,

-    if the key is matched, *data is filled with data associated with the key,

-    returns 0 if the key is matched,

-    returns 1 otherwise

-*/

-static int map_str_find (map_str **ma, const byte *key, byte **data)

-{

-    while (*ma)

-    {

-        if (str_equal ((**ma).key, key))

-        {

-            *data = str_duplicate ((**ma).data);

-            if (*data == NULL)

-                return 1;

-

-            return 0;

-        }

-

-        ma = &(**ma).next;

-    }

-

-    set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);

-    return 1;

-}

-

-/*

-    string to rule map typedef

-*/

-typedef struct map_rule_

-{

-    byte *key;

-    rule *data;

-    struct map_rule_ *next;

-} map_rule;

-

-static void map_rule_create (map_rule **ma)

-{

-    *ma = mem_alloc (sizeof (map_rule));

-    if (*ma)

-    {

-        (**ma).key = NULL;

-        (**ma).data = NULL;

-        (**ma).next = NULL;

-    }

-}

-

-static void map_rule_destroy (map_rule **ma)

-{

-    if (*ma)

-    {

-        map_rule_destroy (&(**ma).next);

-        mem_free ((void **) &(**ma).key);

-        mem_free ((void **) ma);

-    }

-}

-

-static void map_rule_append (map_rule **ma, map_rule **nm)

-{

-    while (*ma)

-        ma = &(**ma).next;

-    *ma = *nm;

-}

-

-/*

-    searches the map for specified key,

-    if the key is matched, *data is filled with data associated with the key,

-    returns 0 if the is matched,

-    returns 1 otherwise

-*/

-static int map_rule_find (map_rule **ma, const byte *key, rule **data)

-{

-    while (*ma)

-    {

-        if (str_equal ((**ma).key, key))

-        {

-            *data = (**ma).data;

-

-            return 0;

-        }

-

-        ma = &(**ma).next;

-    }

-

-    set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);

-    return 1;

-}

-

-/*

-    returns 1 if given character is a white space,

-    returns 0 otherwise

-*/

-static int is_space (byte c)

-{

-    return c == ' ' || c == '\t' || c == '\n' || c == '\r';

-}

-

-/*

-    advances text pointer by 1 if character pointed by *text is a space,

-    returns 1 if a space has been eaten,

-    returns 0 otherwise

-*/

-static int eat_space (const byte **text)

-{

-    if (is_space (**text))

-    {

-        (*text)++;

-

-        return 1;

-    }

-

-    return 0;

-}

-

-/*

-    returns 1 if text points to C-style comment start string "/*",

-    returns 0 otherwise

-*/

-static int is_comment_start (const byte *text)

-{

-    return text[0] == '/' && text[1] == '*';

-}

-

-/*

-    advances text pointer to first character after C-style comment block - if any,

-    returns 1 if C-style comment block has been encountered and eaten,

-    returns 0 otherwise

-*/

-static int eat_comment (const byte **text)

-{

-    if (is_comment_start (*text))

-    {

-        /* *text points to comment block - skip two characters to enter comment body */

-        *text += 2;

-        /* skip any character except consecutive '*' and '/' */

-        while (!((*text)[0] == '*' && (*text)[1] == '/'))

-            (*text)++;

-        /* skip those two terminating characters */

-        *text += 2;

-

-        return 1;

-    }

-

-    return 0;

-}

-

-/*

-    advances text pointer to first character that is neither space nor C-style comment block

-*/

-static void eat_spaces (const byte **text)

-{

-    while (eat_space (text) || eat_comment (text))

-        ;

-}

-

-/*

-    resizes string pointed by *ptr to successfully add character c to the end of the string,

-    returns 0 on success,

-    returns 1 otherwise

-*/

-static int string_grow (byte **ptr, unsigned int *len, byte c)

-{

-    /* reallocate the string in 16-byte increments */

-    if ((*len & 0x0F) == 0x0F || *ptr == NULL)

-    {

-        byte *tmp = mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),

-            ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));

-        if (tmp == NULL)

-            return 1;

-

-        *ptr = tmp;

-    }

-

-    if (c)

-    {

-        /* append given character */

-        (*ptr)[*len] = c;

-        (*len)++;

-    }

-    (*ptr)[*len] = '\0';

-

-    return 0;

-}

-

-/*

-    returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _

-    returns 0 otherwise

-*/

-static int is_identifier (byte c)

-{

-    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';

-}

-

-/*

-    copies characters from *text to *id until non-identifier character is encountered,

-    assumes that *id points to NULL object - caller is responsible for later freeing the string,

-    text pointer is advanced to point past the copied identifier,

-    returns 0 if identifier was successfully copied,

-    returns 1 otherwise

-*/

-static int get_identifier (const byte **text, byte **id)

-{

-    const byte *t = *text;

-    byte *p = NULL;

-    unsigned int len = 0;

-

-    if (string_grow (&p, &len, '\0'))

-        return 1;

-

-    /* loop while next character in buffer is valid for identifiers */

-    while (is_identifier (*t))

-    {

-        if (string_grow (&p, &len, *t++))

-        {

-            mem_free ((void **) &p);

-            return 1;

-        }

-    }

-

-    *text = t;

-    *id = p;

-

-    return 0;

-}

-

-/*

-    returns 1 if given character is HEX digit 0-9, A-F or a-f,

-    returns 0 otherwise

-*/

-static int is_hex (byte c)

-{

-    return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');

-}

-

-/*

-    returns value of passed character as if it was HEX digit

-*/

-static unsigned int hex2dec (byte c)

-{

-    if (c >= '0' && c <= '9')

-        return c - '0';

-    if (c >= 'A' && c <= 'F')

-        return c - 'A' + 10;

-    return c - 'a' + 10;

-}

-

-/*

-    converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,

-    advances text pointer past the converted sequence,

-    returns the converted value

-*/

-static unsigned int hex_convert (const byte **text)

-{

-    unsigned int value = 0;

-

-    while (is_hex (**text))

-    {

-        value = value * 0x10 + hex2dec (**text);

-        (*text)++;

-    }

-

-    return value;

-}

-

-/*

-    returns 1 if given character is OCT digit 0-7,

-    returns 0 otherwise

-*/

-static int is_oct (byte c)

-{

-    return c >= '0' && c <= '7';

-}

-

-/*

-    returns value of passed character as if it was OCT digit

-*/

-static int oct2dec (byte c)

-{

-    return c - '0';

-}

-

-static byte get_escape_sequence (const byte **text)

-{

-    int value = 0;

-

-    /* skip '\' character */

-    (*text)++;

-

-    switch (*(*text)++)

-    {

-    case '\'':

-        return '\'';

-    case '"':

-        return '\"';

-    case '?':

-        return '\?';

-    case '\\':

-        return '\\';

-    case 'a':

-        return '\a';

-    case 'b':

-        return '\b';

-    case 'f':

-        return '\f';

-    case 'n':

-        return '\n';

-    case 'r':

-        return '\r';

-    case 't':

-        return '\t';

-    case 'v':

-        return '\v';

-    case 'x':

-        return (byte) hex_convert (text);

-    }

-

-    (*text)--;

-    if (is_oct (**text))

-    {

-        value = oct2dec (*(*text)++);

-        if (is_oct (**text))

-        {

-            value = value * 010 + oct2dec (*(*text)++);

-            if (is_oct (**text))

-                value = value * 010 + oct2dec (*(*text)++);

-        }

-    }

-

-    return (byte) value;

-}

-

-/*

-    copies characters from *text to *str until " or ' character is encountered,

-    assumes that *str points to NULL object - caller is responsible for later freeing the string,

-    assumes that *text points to " or ' character that starts the string,

-    text pointer is advanced to point past the " or ' character,

-    returns 0 if string was successfully copied,

-    returns 1 otherwise

-*/

-static int get_string (const byte **text, byte **str)

-{

-    const byte *t = *text;

-    byte *p = NULL;

-    unsigned int len = 0;

-    byte term_char;

-

-    if (string_grow (&p, &len, '\0'))

-        return 1;

-

-    /* read " or ' character that starts the string */

-    term_char = *t++;

-    /* while next character is not the terminating character */

-    while (*t && *t != term_char)

-    {

-        byte c;

-

-        if (*t == '\\')

-            c = get_escape_sequence (&t);

-        else

-            c = *t++;

-

-        if (string_grow (&p, &len, c))

-        {

-            mem_free ((void **) &p);

-            return 1;

-        }

-    }

-    /* skip " or ' character that ends the string */

-    t++;

-

-    *text = t;

-    *str = p;

-    return 0;

-}

-

-/*

-    gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>

-    assumes that *text already points to <symbol>,

-    returns 0 if emit code is successfully read,

-    returns 1 otherwise

-*/

-static int get_emtcode (const byte **text, map_byte **ma)

-{

-    const byte *t = *text;

-    map_byte *m = NULL;

-

-    map_byte_create (&m);

-    if (m == NULL)

-        return 1;

-

-    if (get_identifier (&t, &m->key))

-    {

-        map_byte_destroy (&m);

-        return 1;

-    }

-    eat_spaces (&t);

-

-    if (*t == '\'')

-    {

-        byte *c;

-

-        if (get_string (&t, &c))

-        {

-            map_byte_destroy (&m);

-            return 1;

-        }

-

-        m->data = (byte) c[0];

-        mem_free ((void **) &c);

-    }

-    else

-    {

-        /* skip HEX "0x" or "0X" prefix */

-        t += 2;

-        m->data = (byte) hex_convert (&t);

-    }

-

-    eat_spaces (&t);

-

-    *text = t;

-    *ma = m;

-    return 0;

-}

-

-/*

-    gets regbyte declaration, the syntax is: ".regbyte" " " <symbol> " " ("0x" | "0X") <hex_value>

-    assumes that *text already points to <symbol>,

-    returns 0 if regbyte is successfully read,

-    returns 1 otherwise

-*/

-static int get_regbyte (const byte **text, map_byte **ma)

-{

-    return get_emtcode (text, ma);

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise

-*/

-static int get_errtext (const byte **text, map_str **ma)

-{

-    const byte *t = *text;

-    map_str *m = NULL;

-

-    map_str_create (&m);

-    if (m == NULL)

-        return 1;

-

-    if (get_identifier (&t, &m->key))

-    {

-        map_str_destroy (&m);

-        return 1;

-    }

-    eat_spaces (&t);

-

-    if (get_string (&t, &m->data))

-    {

-        map_str_destroy (&m);

-        return 1;

-    }

-    eat_spaces (&t);

-

-    *text = t;

-    *ma = m;

-    return 0;

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise,

-*/

-static int get_error (const byte **text, error **er, map_str *maps)

-{

-    const byte *t = *text;

-    byte *temp = NULL;

-

-    if (*t != '.')

-        return 0;

-

-    t++;

-    if (get_identifier (&t, &temp))

-        return 1;

-    eat_spaces (&t);

-

-    if (!str_equal ((byte *) "error", temp))

-    {

-        mem_free ((void **) &temp);

-        return 0;

-    }

-

-    mem_free ((void **) &temp);

-

-    error_create (er);

-    if (*er == NULL)

-        return 1;

-

-    if (*t == '\"')

-    {

-        if (get_string (&t, &(**er).m_text))

-        {

-            error_destroy (er);

-            return 1;

-        }

-        eat_spaces (&t);

-    }

-    else

-    {

-        if (get_identifier (&t, &temp))

-        {

-            error_destroy (er);

-            return 1;

-        }

-        eat_spaces (&t);

-

-        if (map_str_find (&maps, temp, &(**er).m_text))

-        {

-            mem_free ((void **) &temp);

-            error_destroy (er);

-            return 1;

-        }

-

-        mem_free ((void **) &temp);

-    }

-

-    /* try to extract "token" from "...$token$..." */

-    {

-        byte *processed = NULL;

-        unsigned int len = 0, i = 0;

-

-        if (string_grow (&processed, &len, '\0'))

-        {

-            error_destroy (er);

-            return 1;

-        }

-

-        while (i < str_length ((**er).m_text))

-        {

-            /* check if the dollar sign is repeated - if so skip it */

-            if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$')

-            {

-                if (string_grow (&processed, &len, '$'))

-                {

-                    mem_free ((void **) &processed);

-                    error_destroy (er);

-                    return 1;

-                }

-

-                i += 2;

-            }

-            else if ((**er).m_text[i] != '$')

-            {

-                if (string_grow (&processed, &len, (**er).m_text[i]))

-                {

-                    mem_free ((void **) &processed);

-                    error_destroy (er);

-                    return 1;

-                }

-

-                i++;

-            }

-            else

-            {

-                if (string_grow (&processed, &len, '$'))

-                {

-                    mem_free ((void **) &processed);

-                    error_destroy (er);

-                    return 1;

-                }

-

-                {

-                    /* length of token being extracted */

-                    unsigned int tlen = 0;

-

-                    if (string_grow (&(**er).m_token_name, &tlen, '\0'))

-                    {

-                        mem_free ((void **) &processed);

-                        error_destroy (er);

-                        return 1;

-                    }

-

-                    /* skip the dollar sign */

-                    i++;

-

-                    while ((**er).m_text[i] != '$')

-                    {

-                        if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i]))

-                        {

-                            mem_free ((void **) &processed);

-                            error_destroy (er);

-                            return 1;

-                        }

-

-                        i++;

-                    }

-

-                    /* skip the dollar sign */

-                    i++;

-                }

-            }

-        }

-

-        mem_free ((void **) &(**er).m_text);

-        (**er).m_text = processed;

-    }

-

-    *text = t;

-    return 0;

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise,

-*/

-static int get_emits (const byte **text, emit **em, map_byte *mapb)

-{

-    const byte *t = *text;

-    byte *temp = NULL;

-    emit *e = NULL;

-    emit_dest dest;

-

-    if (*t != '.')

-        return 0;

-

-    t++;

-    if (get_identifier (&t, &temp))

-        return 1;

-    eat_spaces (&t);

-

-    /* .emit */

-    if (str_equal ((byte *) "emit", temp))

-        dest = ed_output;

-    /* .load */

-    else if (str_equal ((byte *) "load", temp))

-        dest = ed_regbyte;

-    else

-    {

-        mem_free ((void **) &temp);

-        return 0;

-    }

-

-    mem_free ((void **) &temp);

-

-    emit_create (&e);

-    if (e == NULL)

-        return 1;

-

-    e->m_emit_dest = dest;

-

-    if (dest == ed_regbyte)

-    {

-        if (get_identifier (&t, &e->m_regname))

-        {

-            emit_destroy (&e);

-            return 1;

-        }

-        eat_spaces (&t);

-    }

-

-    /* 0xNN */

-    if (*t == '0')

-    {

-        t += 2;

-        e->m_byte = (byte) hex_convert (&t);

-

-        e->m_emit_type = et_byte;

-    }

-    /* * */

-    else if (*t == '*')

-    {

-        t++;

-

-        e->m_emit_type = et_stream;

-    }

-    /* $ */

-    else if (*t == '$')

-    {

-        t++;

-

-        e->m_emit_type = et_position;

-    }

-    /* 'c' */

-    else if (*t == '\'')

-    {

-        if (get_string (&t, &temp))

-        {

-            emit_destroy (&e);

-            return 1;

-        }

-        e->m_byte = (byte) temp[0];

-

-        mem_free ((void **) &temp);

-

-        e->m_emit_type = et_byte;

-    }

-    else

-    {

-        if (get_identifier (&t, &temp))

-        {

-            emit_destroy (&e);

-            return 1;

-        }

-

-        if (map_byte_find (&mapb, temp, &e->m_byte))

-        {

-            mem_free ((void **) &temp);

-            emit_destroy (&e);

-            return 1;

-        }

-

-        mem_free ((void **) &temp);

-

-        e->m_emit_type = et_byte;

-    }

-

-    eat_spaces (&t);

-

-    if (get_emits (&t, &e->m_next, mapb))

-    {

-        emit_destroy (&e);

-        return 1;

-    }

-

-    *text = t;

-    *em = e;

-    return 0;

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise,

-*/

-static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb)

-{

-    const byte *t = *text;

-    spec *s = NULL;

-

-    spec_create (&s);

-    if (s == NULL)

-        return 1;

-

-    /* first - read optional .if statement */

-    if (*t == '.')

-    {

-        const byte *u = t;

-        byte *keyword = NULL;

-

-        /* skip the dot */

-        u++;

-

-        if (get_identifier (&u, &keyword))

-        {

-            spec_destroy (&s);

-            return 1;

-        }

-

-        /* .if */

-        if (str_equal ((byte *) "if", keyword))

-        {

-            cond_create (&s->m_cond);

-            if (s->m_cond == NULL)

-            {

-                spec_destroy (&s);

-                return 1;

-            }

-

-            /* skip the left paren */

-            eat_spaces (&u);

-            u++;

-

-            /* get the left operand */

-            eat_spaces (&u);

-            if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname))

-            {

-                spec_destroy (&s);

-                return 1;

-            }

-            s->m_cond->m_operands[0].m_type = cot_regbyte;

-

-            /* get the operator (!= or ==) */

-            eat_spaces (&u);

-            if (*u == '!')

-                s->m_cond->m_type = ct_not_equal;

-            else

-                s->m_cond->m_type = ct_equal;

-            u += 2;

-

-            /* skip the 0x prefix */

-            eat_spaces (&u);

-            u += 2;

-

-            /* get the right operand */

-            s->m_cond->m_operands[1].m_byte = hex_convert (&u);

-            s->m_cond->m_operands[1].m_type = cot_byte;

-

-            /* skip the right paren */

-            eat_spaces (&u);

-            u++;

-

-            eat_spaces (&u);

-

-            t = u;

-        }

-

-        mem_free ((void **) &keyword);

-    }

-

-    if (*t == '\'')

-    {

-        byte *temp = NULL;

-

-        if (get_string (&t, &temp))

-        {

-            spec_destroy (&s);

-            return 1;

-        }

-        eat_spaces (&t);

-

-        if (*t == '-')

-        {

-            byte *temp2 = NULL;

-

-            /* skip the '-' character */

-            t++;

-            eat_spaces (&t);

-

-            if (get_string (&t, &temp2))

-            {

-                mem_free ((void **) &temp);

-                spec_destroy (&s);

-                return 1;

-            }

-            eat_spaces (&t);

-

-            s->m_spec_type = st_byte_range;

-            s->m_byte[0] = *temp;

-            s->m_byte[1] = *temp2;

-

-            mem_free ((void **) &temp2);

-        }

-        else

-        {

-            s->m_spec_type = st_byte;

-            *s->m_byte = *temp;

-        }

-

-        mem_free ((void **) &temp);

-    }

-    else if (*t == '"')

-    {

-        if (get_string (&t, &s->m_string))

-        {

-            spec_destroy (&s);

-            return 1;

-        }

-        eat_spaces (&t);

-

-        s->m_spec_type = st_string;

-    }

-    else if (*t == '.')

-    {

-        byte *keyword = NULL;

-

-        /* skip the dot */

-        t++;

-

-        if (get_identifier (&t, &keyword))

-        {

-            spec_destroy (&s);

-            return 1;

-        }

-        eat_spaces (&t);

-

-        /* .true */

-        if (str_equal ((byte *) "true", keyword))

-        {

-            s->m_spec_type = st_true;

-        }

-        /* .false */

-        else if (str_equal ((byte *) "false", keyword))

-        {

-            s->m_spec_type = st_false;

-        }

-        /* .debug */

-        else if (str_equal ((byte *) "debug", keyword))

-        {

-            s->m_spec_type = st_debug;

-        }

-        /* .loop */

-        else if (str_equal ((byte *) "loop", keyword))

-        {

-            if (get_identifier (&t, &s->m_string))

-            {

-                mem_free ((void **) &keyword);

-                spec_destroy (&s);

-                return 1;

-            }

-            eat_spaces (&t);

-

-            s->m_spec_type = st_identifier_loop;

-        }

-

-        mem_free ((void **) &keyword);

-    }

-    else

-    {

-        if (get_identifier (&t, &s->m_string))

-        {

-            spec_destroy (&s);

-            return 1;

-        }

-        eat_spaces (&t);

-

-        s->m_spec_type = st_identifier;

-    }

-

-    if (get_error (&t, &s->m_errtext, maps))

-    {

-        spec_destroy (&s);

-        return 1;

-    }

-

-    if (get_emits (&t, &s->m_emits, mapb))

-    {

-        spec_destroy (&s);

-        return 1;

-    }

-

-    *text = t;

-    *sp = s;

-    return 0;

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise,

-*/

-static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)

-{

-    const byte *t = *text;

-    rule *r = NULL;

-

-    rule_create (&r);

-    if (r == NULL)

-        return 1;

-

-    if (get_spec (&t, &r->m_specs, maps, mapb))

-    {

-        rule_destroy (&r);

-        return 1;

-    }

-

-    while (*t != ';')

-    {

-        byte *op = NULL;

-        spec *sp = NULL;

-

-        /* skip the dot that precedes "and" or "or" */

-        t++;

-

-        /* read "and" or "or" keyword */

-        if (get_identifier (&t, &op))

-        {

-            rule_destroy (&r);

-            return 1;

-        }

-        eat_spaces (&t);

-

-        if (r->m_oper == op_none)

-        {

-            /* .and */

-            if (str_equal ((byte *) "and", op))

-                r->m_oper = op_and;

-            /* .or */

-            else

-                r->m_oper = op_or;

-        }

-

-        mem_free ((void **) &op);

-

-        if (get_spec (&t, &sp, maps, mapb))

-        {

-            rule_destroy (&r);

-            return 1;

-        }

-

-        spec_append (&r->m_specs, &sp);

-    }

-

-    /* skip the semicolon */

-    t++;

-    eat_spaces (&t);

-

-    *text = t;

-    *ru = r;

-    return 0;

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise,

-*/

-static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)

-{

-    if (map_rule_find (&mapr, symbol, ru))

-        return 1;

-

-/*  (**ru).m_referenced = 1; */

-

-    return 0;

-}

-

-/*

-    returns 0 on success,

-    returns 1 otherwise,

-*/

-static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,

-    byte **string_symbol, map_byte *regbytes)

-{

-    rule *rulez = di->m_rulez;

-

-    /* update dependecies for the root and lexer symbols */

-    if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||

-        (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))

-        return 1;

-

-    mem_free ((void **) syntax_symbol);

-    mem_free ((void **) string_symbol);

-

-    /* update dependecies for the rest of the rules */

-    while (rulez)

-    {

-        spec *sp = rulez->m_specs;

-

-        /* iterate through all the specifiers */

-        while (sp)

-        {

-            /* update dependency for identifier */

-            if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)

-            {

-                if (update_dependency (mapr, sp->m_string, &sp->m_rule))

-                    return 1;

-

-                mem_free ((void **) &sp->m_string);

-            }

-

-            /* some errtexts reference to a rule */

-            if (sp->m_errtext && sp->m_errtext->m_token_name)

-            {

-                if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))

-                    return 1;

-

-                mem_free ((void **) &sp->m_errtext->m_token_name);

-            }

-

-            /* update dependency for condition */

-            if (sp->m_cond)

-            {

-                int i;

-                for (i = 0; i < 2; i++)

-                    if (sp->m_cond->m_operands[i].m_type == cot_regbyte)

-                    {

-                        sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (&regbytes,

-                            sp->m_cond->m_operands[i].m_regname);

-

-                        if (sp->m_cond->m_operands[i].m_regbyte == NULL)

-                            return 1;

-

-                        mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);

-                    }

-            }

-

-            /* update dependency for all .load instructions */

-            if (sp->m_emits)

-            {

-                emit *em = sp->m_emits;

-                while (em != NULL)

-                {

-                    if (em->m_emit_dest == ed_regbyte)

-                    {

-                        em->m_regbyte = map_byte_locate (&regbytes, em->m_regname);

-

-                        if (em->m_regbyte == NULL)

-                            return 1;

-

-                        mem_free ((void **) &em->m_regname);

-                    }

-

-                    em = em->m_next;

-                }

-            }

-

-            sp = sp->m_next;

-        }

-

-        rulez = rulez->m_next;

-    }

-

-/* check for unreferenced symbols */

-/*  de = di->m_defntns;

-    while (de)

-    {

-        if (!de->m_referenced)

-        {

-            map_def *ma = mapd;

-            while (ma)

-            {

-                if (ma->data == de)

-                {

-                    assert (0);

-                    break;

-                }

-                ma = ma->next;

-            }

-        }

-        de = de->m_next;

-    }

-*/

-    return 0;

-}

-

-static int satisfies_condition (cond *co, regbyte_ctx *ctx)

-{

-    byte values[2];

-    int i;

-

-    if (co == NULL)

-        return 1;

-

-    for (i = 0; i < 2; i++)

-        switch (co->m_operands[i].m_type)

-        {

-        case cot_byte:

-            values[i] = co->m_operands[i].m_byte;

-            break;

-        case cot_regbyte:

-            values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);

-            break;

-        }

-

-    switch (co->m_type)

-    {

-    case ct_equal:

-        return values[0] == values[1];

-    case ct_not_equal:

-        return values[0] != values[1];

-    }

-

-    return 0;

-}

-

-static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)

-{

-    while (top != limit)

-    {

-        regbyte_ctx *rbc = top->m_prev;

-        regbyte_ctx_destroy (&top);

-        top = rbc;

-    }

-}

-

-typedef enum match_result_

-{

-    mr_not_matched,     /* the examined string does not match */

-    mr_matched,         /* the examined string matches */

-    mr_error_raised,    /* mr_not_matched + error has been raised */

-    mr_dont_emit,       /* used by identifier loops only */

-    mr_internal_error   /* an internal error has occured such as out of memory */

-} match_result;

-

-/*

-    This function does the main job. It parses the text and generates output data.

-

-    XXX optimize it - the barray seems to be the bottleneck

-*/

-static match_result match (dict *di, const byte *text, unsigned int *index, rule *ru, barray **ba,

-    int filtering_string, regbyte_ctx **rbc)

-{

-    unsigned int ind = *index;

-    match_result status = mr_not_matched;

-    spec *sp = ru->m_specs;

-    regbyte_ctx *ctx = *rbc;

-

-    /* for every specifier in the rule */

-    while (sp)

-    {

-        unsigned int i, len, save_ind = ind;

-        barray *array = NULL;

-

-        if (satisfies_condition (sp->m_cond, ctx))

-        {

-            switch (sp->m_spec_type)

-            {

-            case st_identifier:

-                barray_create (&array);

-                if (array == NULL)

-                {

-                    free_regbyte_ctx_stack (ctx, *rbc);

-                    return mr_internal_error;

-                }

-

-                status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);

-                if (status == mr_internal_error)

-                {

-                    free_regbyte_ctx_stack (ctx, *rbc);

-                    barray_destroy (&array);

-                    return mr_internal_error;

-                }

-                break;

-            case st_string:

-                len = str_length (sp->m_string);

-

-                /* prefilter the stream */

-                if (!filtering_string && di->m_string)

-                {

-                    barray *ba;

-                    unsigned int filter_index = 0;

-                    match_result result;

-                    regbyte_ctx *null_ctx = NULL;

-

-                    barray_create (&ba);

-                    if (ba == NULL)

-                    {

-                        free_regbyte_ctx_stack (ctx, *rbc);

-                        return mr_internal_error;

-                    }

-

-                    result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);

-

-                    if (result == mr_internal_error)

-                    {

-                        free_regbyte_ctx_stack (ctx, *rbc);

-                        barray_destroy (&ba);

-                        return mr_internal_error;

-                    }

-

-                    if (result != mr_matched)

-                    {

-                        barray_destroy (&ba);

-                        status = mr_not_matched;

-                        break;

-                    }

-

-                    barray_destroy (&ba);

-

-                    if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))

-                    {

-                        status = mr_not_matched;

-                        break;

-                    }

-

-                    status = mr_matched;

-                    ind += len;

-                }

-                else

-                {

-                    status = mr_matched;

-                    for (i = 0; status == mr_matched && i < len; i++)

-                        if (text[ind + i] != sp->m_string[i])

-                            status = mr_not_matched;

-                    if (status == mr_matched)

-                        ind += len;

-                }

-                break;

-            case st_byte:

-                status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;

-                if (status == mr_matched)

-                    ind++;

-                break;

-            case st_byte_range:

-                status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?

-                    mr_matched : mr_not_matched;

-                if (status == mr_matched)

-                    ind++;

-                break;

-            case st_true:

-                status = mr_matched;

-                break;

-            case st_false:

-                status = mr_not_matched;

-                break;

-            case st_debug:

-                status = ru->m_oper == op_and ? mr_matched : mr_not_matched;

-                break;

-            case st_identifier_loop:

-                barray_create (&array);

-                if (array == NULL)

-                {

-                    free_regbyte_ctx_stack (ctx, *rbc);

-                    return mr_internal_error;

-                }

-

-                status = mr_dont_emit;

-                for (;;)

-                {

-                    match_result result;

-

-                    save_ind = ind;

-                    result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);

-

-                    if (result == mr_error_raised)

-                    {

-                        status = result;

-                        break;

-                    }

-                    else if (result == mr_matched)

-                    {

-                        if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||

-                            barray_append (ba, &array))

-                        {

-                            free_regbyte_ctx_stack (ctx, *rbc);

-                            barray_destroy (&array);

-                            return mr_internal_error;

-                        }

-                        barray_destroy (&array);

-                        barray_create (&array);

-                        if (array == NULL)

-                        {

-                            free_regbyte_ctx_stack (ctx, *rbc);

-                            return mr_internal_error;

-                        }

-                    }

-                    else if (result == mr_internal_error)

-                    {

-                        free_regbyte_ctx_stack (ctx, *rbc);

-                        barray_destroy (&array);

-                        return mr_internal_error;

-                    }

-                    else

-                        break;

-                }

-                break;

-            }

-        }

-        else

-        {

-            status = mr_not_matched;

-        }

-

-        if (status == mr_error_raised)

-        {

-            free_regbyte_ctx_stack (ctx, *rbc);

-            barray_destroy (&array);

-

-            return mr_error_raised;

-        }

-

-        if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)

-        {

-            free_regbyte_ctx_stack (ctx, *rbc);

-            barray_destroy (&array);

-

-            if (sp->m_errtext)

-            {

-                set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,

-                    ind), ind);

-

-                return mr_error_raised;

-            }

-

-            return mr_not_matched;

-        }

-

-        if (status == mr_matched)

-        {

-            if (sp->m_emits)

-                if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx))

-                {

-                    free_regbyte_ctx_stack (ctx, *rbc);

-                    barray_destroy (&array);

-                    return mr_internal_error;

-                }

-

-            if (array)

-                if (barray_append (ba, &array))

-                {

-                    free_regbyte_ctx_stack (ctx, *rbc);

-                    barray_destroy (&array);

-                    return mr_internal_error;

-                }

-        }

-

-        barray_destroy (&array);

-

-        /* if the rule operator is a logical or, we pick up the first matching specifier */

-        if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))

-        {

-            *index = ind;

-            *rbc = ctx;

-            return mr_matched;

-        }

-

-        sp = sp->m_next;

-    }

-

-    /* everything went fine - all specifiers match up */

-    if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))

-    {

-        *index = ind;

-        *rbc = ctx;

-        return mr_matched;

-    }

-

-    free_regbyte_ctx_stack (ctx, *rbc);

-    return mr_not_matched;

-}

-

-static byte *error_get_token (error *er, dict *di, const byte *text, unsigned int ind)

-{

-    byte *str = NULL;

-

-    if (er->m_token)

-    {

-        barray *ba;

-        unsigned int filter_index = 0;

-        regbyte_ctx *ctx = NULL;

-

-        barray_create (&ba);

-        if (ba != NULL)

-        {

-            if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched &&

-                filter_index)

-            {

-                str = mem_alloc (filter_index + 1);

-                if (str != NULL)

-                {

-                    str_copy_n (str, text + ind, filter_index);

-                    str[filter_index] = '\0';

-                }

-            }

-            barray_destroy (&ba);

-        }

-    }

-

-    return str;

-}

-

-typedef struct grammar_load_state_

-{

-    dict *di;

-    byte *syntax_symbol;

-    byte *string_symbol;

-    map_str *maps;

-    map_byte *mapb;

-    map_rule *mapr;

-} grammar_load_state;

-

-static void grammar_load_state_create (grammar_load_state **gr)

-{

-    *gr = mem_alloc (sizeof (grammar_load_state));

-    if (*gr)

-    {

-        (**gr).di = NULL;

-        (**gr).syntax_symbol = NULL;

-        (**gr).string_symbol = NULL;

-        (**gr).maps = NULL;

-        (**gr).mapb = NULL;

-        (**gr).mapr = NULL;

-    }

-}

-

-static void grammar_load_state_destroy (grammar_load_state **gr)

-{

-    if (*gr)

-    {

-        dict_destroy (&(**gr).di);

-        mem_free ((void **) &(**gr).syntax_symbol);

-        mem_free ((void **) &(**gr).string_symbol);

-        map_str_destroy (&(**gr).maps);

-        map_byte_destroy (&(**gr).mapb);

-        map_rule_destroy (&(**gr).mapr);

-        mem_free ((void **) gr);

-    }

-}

-

-/*

-    the API

-*/

-

-grammar grammar_load_from_text (const byte *text)

-{

-    grammar_load_state *g = NULL;

-    grammar id = 0;

-

-    clear_last_error ();

-

-    grammar_load_state_create (&g);

-    if (g == NULL)

-        return 0;

-

-    dict_create (&g->di);

-    if (g->di == NULL)

-    {

-        grammar_load_state_destroy (&g);

-        return 0;

-    }

-

-    eat_spaces (&text);

-

-    /* skip ".syntax" keyword */

-    text += 7;

-    eat_spaces (&text);

-

-    /* retrieve root symbol */

-    if (get_identifier (&text, &g->syntax_symbol))

-    {

-        grammar_load_state_destroy (&g);

-        return 0;

-    }

-    eat_spaces (&text);

-

-    /* skip semicolon */

-    text++;

-    eat_spaces (&text);

-

-    while (*text)

-    {

-        byte *symbol = NULL;

-        int is_dot = *text == '.';

-

-        if (is_dot)

-            text++;

-

-        if (get_identifier (&text, &symbol))

-        {

-            grammar_load_state_destroy (&g);

-            return 0;

-        }

-        eat_spaces (&text);

-

-        /* .emtcode */

-        if (is_dot && str_equal (symbol, (byte *) "emtcode"))

-        {

-            map_byte *ma = NULL;

-

-            mem_free ((void **) &symbol);

-

-            if (get_emtcode (&text, &ma))

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            map_byte_append (&g->mapb, &ma);

-        }

-        /* .regbyte */

-        else if (is_dot && str_equal (symbol, (byte *) "regbyte"))

-        {

-            map_byte *ma = NULL;

-

-            mem_free ((void **) &symbol);

-

-            if (get_regbyte (&text, &ma))

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            map_byte_append (&g->di->m_regbytes, &ma);

-        }

-        /* .errtext */

-        else if (is_dot && str_equal (symbol, (byte *) "errtext"))

-        {

-            map_str *ma = NULL;

-

-            mem_free ((void **) &symbol);

-

-            if (get_errtext (&text, &ma))

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            map_str_append (&g->maps, &ma);

-        }

-        /* .string */

-        else if (is_dot && str_equal (symbol, (byte *) "string"))

-        {

-            mem_free ((void **) &symbol);

-

-            if (g->di->m_string != NULL)

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            if (get_identifier (&text, &g->string_symbol))

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            /* skip semicolon */

-            eat_spaces (&text);

-            text++;

-            eat_spaces (&text);

-        }

-        else

-        {

-            rule *ru = NULL;

-            map_rule *ma = NULL;

-

-            if (get_rule (&text, &ru, g->maps, g->mapb))

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            rule_append (&g->di->m_rulez, &ru);

-

-            /* if a rule consist of only one specifier, give it an ".and" operator */

-            if (ru->m_oper == op_none)

-                ru->m_oper = op_and;

-

-            map_rule_create (&ma);

-            if (ma == NULL)

-            {

-                grammar_load_state_destroy (&g);

-                return 0;

-            }

-

-            ma->key = symbol;

-            ma->data = ru;

-            map_rule_append (&g->mapr, &ma);

-        }

-    }

-

-    if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol,

-        g->di->m_regbytes))

-    {

-        grammar_load_state_destroy (&g);

-        return 0;

-    }

-

-    dict_append (&g_dicts, &g->di);

-    id = g->di->m_id;

-    g->di = NULL;

-

-    grammar_load_state_destroy (&g);

-

-    return id;

-}

-

-int grammar_set_reg8 (grammar id, const byte *name, byte value)

-{

-    dict *di = NULL;

-    map_byte *reg = NULL;

-

-    clear_last_error ();

-

-    dict_find (&g_dicts, id, &di);

-    if (di == NULL)

-    {

-        set_last_error (INVALID_GRAMMAR_ID, NULL, -1);

-        return 0;

-    }

-

-    reg = map_byte_locate (&di->m_regbytes, name);

-    if (reg == NULL)

-    {

-        set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1);

-        return 0;

-    }

-

-    reg->data = value;

-    return 1;

-}

-

-int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size)

-{

-    dict *di = NULL;

-    barray *ba = NULL;

-    unsigned int index = 0;

-    regbyte_ctx *rbc = NULL;

-

-    clear_last_error ();

-

-    dict_find (&g_dicts, id, &di);

-    if (di == NULL)

-    {

-        set_last_error (INVALID_GRAMMAR_ID, NULL, -1);

-        return 0;

-    }

-

-    barray_create (&ba);

-    if (ba == NULL)

-        return 0;

-

-    *prod = NULL;

-    *size = 0;

-

-    if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched)

-    {

-        barray_destroy (&ba);

-        free_regbyte_ctx_stack (rbc, NULL);

-        return 0;

-    }

-

-    free_regbyte_ctx_stack (rbc, NULL);

-

-    *prod = mem_alloc (ba->len * sizeof (byte));

-    if (*prod == NULL)

-    {

-        barray_destroy (&ba);

-        return 0;

-    }

-

-    mem_copy (*prod, ba->data, ba->len * sizeof (byte));

-    *size = ba->len;

-    barray_destroy (&ba);

-

-    return 1;

-}

-

-int grammar_destroy (grammar id)

-{

-    dict **di = &g_dicts;

-

-    clear_last_error ();

-

-    while (*di != NULL)

-    {

-        if ((**di).m_id == id)

-        {

-            dict *tmp = *di;

-            *di = (**di).m_next;

-            dict_destroy (&tmp);

-            return 1;

-        }

-

-        di = &(**di).m_next;

-    }

-

-    set_last_error (INVALID_GRAMMAR_ID, NULL, -1);

-    return 0;

-}

-

-void grammar_get_last_error (byte *text, unsigned int size, int *pos)

-{

-    unsigned int len = 0, dots_made = 0;

-    const byte *p = error_message;

-

-    *text = '\0';

-

-#define APPEND_CHARACTER(x) if (dots_made == 0) {\

-                                if (len < size - 1) {\

-                                    text[len++] = (x); text[len] = '\0';\

-                                } else {\

-                                    int i;\

-                                    for (i = 0; i < 3; i++)\

-                                        if (--len >= 0)\

-                                            text[len] = '.';\

-                                    dots_made = 1;\

-                                }\

-                            }

-

-    if (p)

-        while (*p)

-            if (*p == '$')

-            {

-                const byte *r = error_param;

-

-                while (*r)

-                {

-                    APPEND_CHARACTER(*r)

-                    r++;

-                }

-

-                p++;

-            }

-            else

-            {

-                APPEND_CHARACTER(*p)

-                p++;

-            }

-

-    *pos = error_position;

-

-#undef APPEND_CHARACTER

-

-}

-

+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file grammar.c
+ * syntax parsing engine
+ * \author Michal Krol
+ */
+
+#ifndef GRAMMAR_PORT_BUILD
+#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file
+#endif
+
+/*
+    Last Modified: 2004-II-8
+*/
+
+/*
+    INTRODUCTION
+    ------------
+
+    The task is to check the syntax of an input string. Input string is a stream of ASCII
+    characters terminated with a null-character ('\0'). Checking it using C language is
+    difficult and hard to implement without bugs. It is hard to maintain and make changes when
+    the syntax changes.
+
+    This is because of a high redundancy of the C code. Large blocks of code are duplicated with
+    only small changes. Even use of macros does not solve the problem because macros cannot
+    erase the complexity of the problem.
+
+    The resolution is to create a new language that will be highly oriented to our task. Once
+    we describe a particular syntax, we are done. We can then focus on the code that implements
+    the language. The size and complexity of it is relatively small than the code that directly
+    checks the syntax.
+
+    First, we must implement our new language. Here, the language is implemented in C, but it
+    could also be implemented in any other language. The code is listed below. We must take
+    a good care that it is bug free. This is simple because the code is simple and clean.
+
+    Next, we must describe the syntax of our new language in itself. Once created and checked
+    manually that it is correct, we can use it to check another scripts.
+
+    Note that our new language loading code does not have to check the syntax. It is because we
+    assume that the script describing itself is correct, and other scripts can be syntactically
+    checked by the former script. The loading code must only do semantic checking which leads us to
+    simple resolving references.
+
+    THE LANGUAGE
+    ------------
+
+    Here I will describe the syntax of the new language (further called "Synek"). It is mainly a
+    sequence of declarations terminated by a semicolon. The declaration consists of a symbol,
+    which is an identifier, and its definition. A definition is in turn a sequence of specifiers
+    connected with ".and" or ".or" operator. These operators cannot be mixed together in a one
+    definition. Specifier can be a symbol, string, character, character range or a special
+    keyword ".true" or ".false".
+
+    On the very beginning of the script there is a declaration of a root symbol and is in the form:
+        .syntax <root_symbol>;
+    The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if
+    the root symbol evaluates to true. A symbol evaluates to true if the definition associated with
+    the symbol evaluates to true. Definition evaluation depends on the operator used to connect
+    specifiers in the definition. If ".and" operator is used, definition evaluates to true if and
+    only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to
+    true if any of the specifiers evaluates to true. If definition contains only one specifier,
+    it is evaluated as if it was connected with ".true" keyword by ".and" operator.
+
+    If specifier is a ".true" keyword, it always evaluates to true.
+
+    If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false
+    when it does not evaluate to true.
+
+    Character range specifier is in the form:
+        '<first_character>' - '<second_character>'
+    If specifier is a character range, it evaluates to true if character in the stream is greater
+    or equal to <first_character> and less or equal to <second_character>. In that situation 
+    the stream pointer is advanced to point to next character in the stream. All C-style escape
+    sequences are supported although trigraph sequences are not. The comparisions are performed
+    on 8-bit unsigned integers.
+
+    Character specifier is in the form:
+        '<single_character>'
+    It evaluates to true if the following character range specifier evaluates to true:
+        '<single_character>' - '<single_character>'
+
+    String specifier is in the form:
+        "<string>"
+    Let N be the number of characters in <string>. Let <string>[i] designate i-th character in
+    <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)
+    the following character specifier evaluates to true:
+        '<string>[i]'
+    If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.
+
+    Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
+        .loop <symbol>                  (1)
+    where <symbol> is defined as follows:
+        <symbol> <definition>;          (2)
+    Construction (1) is replaced by the following code:
+        <symbol$1>
+    and declaration (2) is replaced by the following:
+        <symbol$1> <symbol$2> .or .true;
+        <symbol$2> <symbol> .and <symbol$1>;
+        <symbol> <definition>;
+
+    Synek supports also a register mechanizm. User can, in its SYN file, declare a number of
+    registers that can be accessed in the syn body. Each reg has its name and a default value.
+    The register is one byte wide. The C code can change the default value by calling
+    grammar_set_reg8() with grammar id, register name and a new value. As we know, each rule is
+    a sequence of specifiers joined with .and or .or operator. And now each specifier can be
+    prefixed with a condition expression in a form ".if (<reg_name> <operator> <hex_literal>)"
+    where <operator> can be == or !=. If the condition evaluates to false, the specifier
+    evaluates to .false. Otherwise it evalutes to the specifier.
+
+    ESCAPE SEQUENCES
+    ----------------
+
+    Synek supports all escape sequences in character specifiers. The mapping table is listed below.
+    All occurences of the characters in the first column are replaced with the corresponding
+    character in the second column.
+
+        Escape sequence         Represents
+    ------------------------------------------------------------------------------------------------
+        \a                      Bell (alert)
+        \b                      Backspace
+        \f                      Formfeed
+        \n                      New line
+        \r                      Carriage return
+        \t                      Horizontal tab
+        \v                      Vertical tab
+        \'                      Single quotation mark
+        \"                      Double quotation mark
+        \\                      Backslash
+        \?                      Literal question mark
+        \ooo                    ASCII character in octal notation
+        \xhhh                   ASCII character in hexadecimal notation
+    ------------------------------------------------------------------------------------------------
+
+    RAISING ERRORS
+    --------------
+
+    Any specifier can be followed by a special construction that is executed when the specifier
+    evaluates to false. The construction is in the form:
+        .error <ERROR_TEXT>
+    <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is
+    in the form:
+        .errtext <ERROR_TEXT> "<error_desc>"
+    When specifier evaluates to false and this construction is present, parsing is stopped
+    immediately and <error_desc> is returned as a result of parsing. The error position is also
+    returned and it is meant as an offset from the beggining of the stream to the character that
+    was valid so far. Example:
+
+        (**** syntax script ****)
+
+        .syntax program;
+        .errtext MISSING_SEMICOLON      "missing ';'"
+        program         declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and
+                        .loop space .and '\0';
+        declaration     "declare" .and .loop space .and identifier;
+        space           ' ';
+
+        (**** sample code ****)
+
+        declare foo ,
+
+    In the example above checking the sample code will result in error message "missing ';'" and
+    error position 12. The sample code is not correct. Note the presence of '\0' specifier to
+    assure that there is no code after semicolon - only spaces.
+    <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,
+    the identifier and dollar signs are replaced by a string retrieved by invoking symbol with
+    the identifier name. The starting position is the error position. The lenght of the resulting
+    string is the position after invoking the symbol.
+
+    PRODUCTION
+    ----------
+
+    Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers
+    that evaluate to true. That is, every specifier and optional error construction can be followed
+    by a number of emit constructions that are in the form:
+        .emit <parameter>
+    <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by
+    0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration
+    in the form:
+        .emtcode <identifier> <hex_number>
+
+    When given specifier evaluates to true, all emits associated with the specifier are output
+    in order they were declared. A star means that last-read character should be output instead
+    of constant value. Example:
+
+        (**** syntax script ****)
+
+        .syntax foobar;
+        .emtcode WORD_FOO       0x01
+        .emtcode WORD_BAR       0x02
+        foobar      FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
+        FOO         "foo" .and SPACE;
+        BAR         "bar" .and SPACE;
+        SPACE       ' ' .or '\0';
+
+        (**** sample text 1 ****)
+
+        foo
+
+        (**** sample text 2 ****)
+
+        foobar
+
+    For both samples the result will be one-element array. For first sample text it will be
+    value 1, for second - 0. Note that every text will be accepted because of presence of
+    .true as an alternative.
+
+    Another example:
+
+        (**** syntax script ****)
+
+        .syntax declaration;
+        .emtcode VARIABLE       0x01
+        declaration     "declare" .and .loop space .and
+                        identifier .emit VARIABLE .and          (1)
+                        .true .emit 0x00 .and                   (2)
+                        .loop space .and ';';
+        space           ' ' .or '\t';
+        identifier      .loop id_char .emit *;                  (3)
+        id_char         'a'-'z' .or 'A'-'Z' .or '_';
+
+        (**** sample code ****)
+
+        declare    fubar;
+
+    In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to
+    true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used
+    to terminate the string with null to signal when the string ends. Specifier (3) outputs
+    all characters that make declared identifier. The result of sample code will be the
+    following array:
+        { 1, 'f', 'u', 'b', 'a', 'r', 0 }
+
+    If .emit is followed by dollar $, it means that current position should be output. Current
+    position is a 32-bit unsigned integer distance from the very beginning of the parsed string to
+    first character consumed by the specifier associated with the .emit instruction. Current
+    position is stored in the output buffer in Little-Endian convention (the lowest byte comes
+    first).
+*/
+
+static void mem_free (void **);
+
+/*
+    internal error messages
+*/
+static const byte *OUT_OF_MEMORY =          (byte *) "internal error 1001: out of physical memory";
+static const byte *UNRESOLVED_REFERENCE =   (byte *) "internal error 1002: unresolved reference '$'";
+static const byte *INVALID_GRAMMAR_ID =     (byte *) "internal error 1003: invalid grammar object";
+static const byte *INVALID_REGISTER_NAME =  (byte *) "internal error 1004: invalid register name: '$'";
+
+static const byte *error_message = NULL;
+static byte *error_param = NULL;        /* this is inserted into error_message in place of $ */
+static int error_position = -1;
+
+static byte *unknown = (byte *) "???";
+
+static void clear_last_error ()
+{
+    /* reset error message */
+    error_message = NULL;
+
+    /* free error parameter - if error_param is a "???" don't free it - it's static */
+    if (error_param != unknown)
+        mem_free ((void **) &error_param);
+    else
+        error_param = NULL;
+
+    /* reset error position */
+    error_position = -1;
+}
+
+static void set_last_error (const byte *msg, byte *param, int pos)
+{
+    /* error message can only be set only once */
+    if (error_message != NULL)
+    {
+        mem_free (&param);
+        return;
+    }
+
+    error_message = msg;
+
+    if (param != NULL)
+        error_param = param;
+    else
+        error_param = unknown;
+
+    error_position = pos;
+}
+
+/*
+    memory management routines
+*/
+static void *mem_alloc (size_t size)
+{
+    void *ptr = grammar_alloc_malloc (size);
+    if (ptr == NULL)
+        set_last_error (OUT_OF_MEMORY, NULL, -1);
+    return ptr;
+}
+
+static void *mem_copy (void *dst, const void *src, size_t size)
+{
+    return grammar_memory_copy (dst, src, size);
+}
+
+static void mem_free (void **ptr)
+{
+    grammar_alloc_free (*ptr);
+    *ptr = NULL;
+}
+
+static void *mem_realloc (void *ptr, size_t old_size, size_t new_size)
+{
+    void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size);
+    if (ptr2 == NULL)
+        set_last_error (OUT_OF_MEMORY, NULL, -1);
+    return ptr2;
+}
+
+static byte *str_copy_n (byte *dst, const byte *src, size_t max_len)
+{
+    return grammar_string_copy_n (dst, src, max_len);
+}
+
+static byte *str_duplicate (const byte *str)
+{
+    byte *new_str = grammar_string_duplicate (str);
+    if (new_str == NULL)
+        set_last_error (OUT_OF_MEMORY, NULL, -1);
+    return new_str;
+}
+
+static int str_equal (const byte *str1, const byte *str2)
+{
+    return grammar_string_compare (str1, str2) == 0;
+}
+
+static int str_equal_n (const byte *str1, const byte *str2, unsigned int n)
+{
+    return grammar_string_compare_n (str1, str2, n) == 0;
+}
+
+static unsigned int str_length (const byte *str)
+{
+    return grammar_string_length (str);
+}
+
+/*
+    string to byte map typedef
+*/
+typedef struct map_byte_
+{
+    byte *key;
+    byte data;
+    struct map_byte_ *next;
+} map_byte;
+
+static void map_byte_create (map_byte **ma)
+{
+    *ma = mem_alloc (sizeof (map_byte));
+    if (*ma)
+    {
+        (**ma).key = NULL;
+        (**ma).data = '\0';
+        (**ma).next = NULL;
+    }
+}
+
+/* XXX unfold the recursion */
+static void map_byte_destroy (map_byte **ma)
+{
+    if (*ma)
+    {
+        map_byte_destroy (&(**ma).next);
+        mem_free ((void **) &(**ma).key);
+        mem_free ((void **) ma);
+    }
+}
+
+static void map_byte_append (map_byte **ma, map_byte **nm)
+{
+    while (*ma)
+        ma = &(**ma).next;
+    *ma = *nm;
+}
+
+/*
+    searches the map for the specified key,
+    returns pointer to the element with the specified key if it exists
+    returns NULL otherwise
+*/
+map_byte *map_byte_locate (map_byte **ma, const byte *key)
+{
+    while (*ma)
+    {
+        if (str_equal ((**ma).key, key))
+            return *ma;
+
+        ma = &(**ma).next;
+    }
+
+    set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+    return NULL;
+}
+
+/*
+    searches the map for specified key,
+    if the key is matched, *data is filled with data associated with the key,
+    returns 0 if the key is matched,
+    returns 1 otherwise
+*/
+static int map_byte_find (map_byte **ma, const byte *key, byte *data)
+{
+    map_byte *found = map_byte_locate (ma, key);
+    if (found != NULL)
+    {
+        *data = found->data;
+
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+    regbyte context typedef
+
+    Each regbyte consists of its name and a default value. These are static and created at
+    grammar script compile-time, for example the following line:
+        .regbyte vertex_blend      0x00
+    adds a new regbyte named "vertex_blend" to the static list and initializes it to 0.
+    When the script is executed, this regbyte can be accessed by name for read and write. When a
+    particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx
+    stack. The new entry contains information abot which regbyte it references and its new value.
+    When a given regbyte is accessed for read, the stack is searched top-down to find an
+    entry that references the regbyte. The first matching entry is used to return the current
+    value it holds. If no entry is found, the default value is returned.
+*/
+typedef struct regbyte_ctx_
+{
+    map_byte *m_regbyte;
+    byte m_current_value;
+    struct regbyte_ctx_ *m_prev;
+} regbyte_ctx;
+
+static void regbyte_ctx_create (regbyte_ctx **re)
+{
+    *re = mem_alloc (sizeof (regbyte_ctx));
+    if (*re)
+    {
+        (**re).m_regbyte = NULL;
+        (**re).m_prev = NULL;
+    }
+}
+
+static void regbyte_ctx_destroy (regbyte_ctx **re)
+{
+    if (*re)
+    {
+        mem_free ((void **) re);
+    }
+}
+
+static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg)
+{
+    /* first lookup in the register stack */
+    while (*re != NULL)
+    {
+        if ((**re).m_regbyte == reg)
+            return (**re).m_current_value;
+
+        re = &(**re).m_prev;
+    }
+
+    /* if not found - return the default value */
+    return reg->data;
+}
+
+/*
+    emit type typedef
+*/
+typedef enum emit_type_
+{
+    et_byte,            /* explicit number */
+    et_stream,          /* eaten character */
+    et_position         /* current position */
+} emit_type;
+
+/*
+    emit destination typedef
+*/
+typedef enum emit_dest_
+{
+    ed_output,          /* write to the output buffer */
+    ed_regbyte          /* write a particular regbyte */
+} emit_dest;
+
+/*
+    emit typedef
+*/
+typedef struct emit_
+{
+    emit_dest m_emit_dest;
+    emit_type m_emit_type;      /* ed_output */
+    byte m_byte;                /* et_byte */
+    map_byte *m_regbyte;        /* ed_regbyte */
+    byte *m_regname;            /* ed_regbyte - temporary */
+    struct emit_ *m_next;
+} emit;
+
+static void emit_create (emit **em)
+{
+    *em = mem_alloc (sizeof (emit));
+    if (*em)
+    {
+        (**em).m_emit_dest = ed_output;
+        (**em).m_emit_type = et_byte;
+        (**em).m_byte = '\0';
+        (**em).m_regbyte = NULL;
+        (**em).m_regname = NULL;
+        (**em).m_next = NULL;
+    }
+}
+
+static void emit_destroy (emit **em)
+{
+    if (*em)
+    {
+        emit_destroy (&(**em).m_next);
+        mem_free ((void **) &(**em).m_regname);
+        mem_free ((void **) em);
+    }
+}
+
+/*
+    error typedef
+*/
+typedef struct error_
+{
+    byte *m_text;
+    byte *m_token_name;
+    struct rule_ *m_token;
+} error;
+
+static void error_create (error **er)
+{
+    *er = mem_alloc (sizeof (error));
+    if (*er)
+    {
+        (**er).m_text = NULL;
+        (**er).m_token_name = NULL;
+        (**er).m_token = NULL;
+    }
+}
+
+static void error_destroy (error **er)
+{
+    if (*er)
+    {
+        mem_free ((void **) &(**er).m_text);
+        mem_free ((void **) &(**er).m_token_name);
+        mem_free ((void **) er);
+    }
+}
+
+struct dict_;
+static byte *error_get_token (error *, struct dict_ *, const byte *, unsigned int);
+
+/*
+    condition operand type typedef
+*/
+typedef enum cond_oper_type_
+{
+    cot_byte,               /* constant 8-bit unsigned integer */
+    cot_regbyte             /* pointer to byte register containing the current value */
+} cond_oper_type;
+
+/*
+    condition operand typedef
+*/
+typedef struct cond_oper_
+{
+    cond_oper_type m_type;
+    byte m_byte;            /* cot_byte */
+    map_byte *m_regbyte;    /* cot_regbyte */
+    byte *m_regname;        /* cot_regbyte - temporary */
+} cond_oper;
+
+/*
+    condition type typedef
+*/
+typedef enum cond_type_
+{
+    ct_equal,
+    ct_not_equal
+} cond_type;
+
+/*
+    condition typedef
+*/
+typedef struct cond_
+{
+    cond_type m_type;
+    cond_oper m_operands[2];
+} cond;
+
+static void cond_create (cond **co)
+{
+    *co = mem_alloc (sizeof (cond));
+    if (*co)
+    {
+        (**co).m_operands[0].m_regname = NULL;
+        (**co).m_operands[1].m_regname = NULL;
+    }
+}
+
+static void cond_destroy (cond **co)
+{
+    if (*co)
+    {
+        mem_free ((void **) &(**co).m_operands[0].m_regname);
+        mem_free ((void **) &(**co).m_operands[1].m_regname);
+        mem_free ((void **) co);
+    }
+}
+
+/*
+    specifier type typedef
+*/
+typedef enum spec_type_
+{
+    st_false,
+    st_true,
+    st_byte,
+    st_byte_range,
+    st_string,
+    st_identifier,
+    st_identifier_loop,
+    st_debug
+} spec_type;
+
+/*
+    specifier typedef
+*/
+typedef struct spec_
+{
+    spec_type m_spec_type;
+    byte m_byte[2];                 /* st_byte, st_byte_range */
+    byte *m_string;                 /* st_string */
+    struct rule_ *m_rule;           /* st_identifier, st_identifier_loop */
+    emit *m_emits;
+    error *m_errtext;
+    cond *m_cond;
+    struct spec_ *m_next;
+} spec;
+
+static void spec_create (spec **sp)
+{
+    *sp = mem_alloc (sizeof (spec));
+    if (*sp)
+    {
+        (**sp).m_spec_type = st_false;
+        (**sp).m_byte[0] = '\0';
+        (**sp).m_byte[1] = '\0';
+        (**sp).m_string = NULL;
+        (**sp).m_rule = NULL;
+        (**sp).m_emits = NULL;
+        (**sp).m_errtext = NULL;
+        (**sp).m_cond = NULL;
+        (**sp).m_next = NULL;
+    }
+}
+
+static void spec_destroy (spec **sp)
+{
+    if (*sp)
+    {
+        spec_destroy (&(**sp).m_next);
+        emit_destroy (&(**sp).m_emits);
+        error_destroy (&(**sp).m_errtext);
+        mem_free ((void **) &(**sp).m_string);
+        cond_destroy (&(**sp).m_cond);
+        mem_free ((void **) sp);
+    }
+}
+
+static void spec_append (spec **sp, spec **ns)
+{
+    while (*sp)
+        sp = &(**sp).m_next;
+    *sp = *ns;
+}
+
+/*
+    operator typedef
+*/
+typedef enum oper_
+{
+    op_none,
+    op_and,
+    op_or
+} oper;
+
+/*
+    rule typedef
+*/
+typedef struct rule_
+{
+    oper m_oper;
+    spec *m_specs;
+    struct rule_ *m_next;
+/*  int m_referenced; */            /* for debugging purposes */
+} rule;
+
+static void rule_create (rule **ru)
+{
+    *ru = mem_alloc (sizeof (rule));
+    if (*ru)
+    {
+        (**ru).m_oper = op_none;
+        (**ru).m_specs = NULL;
+        (**ru).m_next = NULL;
+/*      (**ru).m_referenced = 0; */
+    }
+}
+
+static void rule_destroy (rule **ru)
+{
+    if (*ru)
+    {
+        rule_destroy (&(**ru).m_next);
+        spec_destroy (&(**ru).m_specs);
+        mem_free ((void **) ru);
+    }
+}
+
+static void rule_append (rule **ru, rule **nr)
+{
+    while (*ru)
+        ru = &(**ru).m_next;
+    *ru = *nr;
+}
+
+/*
+    returns unique grammar id
+*/
+static grammar next_valid_grammar_id ()
+{
+    static grammar id = 0;
+
+    return ++id;
+}
+
+/*
+    dictionary typedef
+*/
+typedef struct dict_
+{
+    rule *m_rulez;
+    rule *m_syntax;
+    rule *m_string;
+    map_byte *m_regbytes;
+    grammar m_id;
+    struct dict_ *m_next;
+} dict;
+
+static void dict_create (dict **di)
+{
+    *di = mem_alloc (sizeof (dict));
+    if (*di)
+    {
+        (**di).m_rulez = NULL;
+        (**di).m_syntax = NULL;
+        (**di).m_string = NULL;
+        (**di).m_regbytes = NULL;
+        (**di).m_id = next_valid_grammar_id ();
+        (**di).m_next = NULL;
+    }
+}
+
+static void dict_destroy (dict **di)
+{
+    if (*di)
+    {
+        rule_destroy (&(**di).m_rulez);
+        map_byte_destroy (&(**di).m_regbytes);
+        mem_free ((void **) di);
+    }
+}
+
+static void dict_append (dict **di, dict **nd)
+{
+    while (*di)
+        di = &(**di).m_next;
+    *di = *nd;
+}
+
+static void dict_find (dict **di, grammar key, dict **data)
+{
+    while (*di)
+    {
+        if ((**di).m_id == key)
+        {
+            *data = *di;
+            return;
+        }
+
+        di = &(**di).m_next;
+    }
+
+    *data = NULL;
+}
+
+static dict *g_dicts = NULL;
+
+/*
+    byte array typedef
+
+    XXX this class is going to be replaced by a faster one, soon
+*/
+typedef struct barray_
+{
+    byte *data;
+    unsigned int len;
+} barray;
+
+static void barray_create (barray **ba)
+{
+    *ba = mem_alloc (sizeof (barray));
+    if (*ba)
+    {
+        (**ba).data = NULL;
+        (**ba).len = 0;
+    }
+}
+
+static void barray_destroy (barray **ba)
+{
+    if (*ba)
+    {
+        mem_free ((void **) &(**ba).data);
+        mem_free ((void **) ba);
+    }
+}
+
+/*
+    reallocates byte array to requested size,
+    returns 0 on success,
+    returns 1 otherwise
+*/
+static int barray_resize (barray **ba, unsigned int nlen)
+{
+    byte *new_pointer;
+
+    if (nlen == 0)
+    {
+        mem_free ((void **) &(**ba).data);
+        (**ba).data = NULL;
+        (**ba).len = 0;
+
+        return 0;
+    }
+    else
+    {
+        new_pointer = mem_realloc ((**ba).data, (**ba).len * sizeof (byte), nlen * sizeof (byte));
+        if (new_pointer)
+        {
+            (**ba).data = new_pointer;
+            (**ba).len = nlen;
+
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+/*
+    adds byte array pointed by *nb to the end of array pointed by *ba,
+    returns 0 on success,
+    returns 1 otherwise
+*/
+static int barray_append (barray **ba, barray **nb)
+{
+    const unsigned int len = (**ba).len;
+
+    if (barray_resize (ba, (**ba).len + (**nb).len))
+        return 1;
+
+    mem_copy ((**ba).data + len, (**nb).data, (**nb).len);
+
+    return 0;
+}
+
+/*
+    adds emit chain pointed by em to the end of array pointed by *ba,
+    returns 0 on success,
+    returns 1 otherwise
+*/
+static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc)
+{
+    emit *temp = em;
+    unsigned int count = 0;
+
+    while (temp)
+    {
+        if (temp->m_emit_dest == ed_output)
+            if (temp->m_emit_type == et_position)
+                count += 4;     /* position is a 32-bit unsigned integer */
+            else
+                count++;
+
+        temp = temp->m_next;
+    }
+
+    if (barray_resize (ba, (**ba).len + count))
+        return 1;
+
+    while (em)
+    {
+        if (em->m_emit_dest == ed_output)
+        {
+            if (em->m_emit_type == et_byte)
+                (**ba).data[(**ba).len - count--] = em->m_byte;
+            else if (em->m_emit_type == et_stream)
+                (**ba).data[(**ba).len - count--] = c;
+            else // em->type == et_position
+                (**ba).data[(**ba).len - count--] = (byte) pos,
+                (**ba).data[(**ba).len - count--] = (byte) (pos >> 8),
+                (**ba).data[(**ba).len - count--] = (byte) (pos >> 16),
+                (**ba).data[(**ba).len - count--] = (byte) (pos >> 24);
+        }
+        else
+        {
+            regbyte_ctx *new_rbc;
+            regbyte_ctx_create (&new_rbc);
+            if (new_rbc == NULL)
+                return 1;
+
+            new_rbc->m_prev = *rbc;
+            new_rbc->m_regbyte = em->m_regbyte;
+            *rbc = new_rbc;
+
+            if (em->m_emit_type == et_byte)
+                new_rbc->m_current_value = em->m_byte;
+            else if (em->m_emit_type == et_stream)
+                new_rbc->m_current_value = c;
+        }
+
+        em = em->m_next;
+    }
+
+    return 0;
+}
+
+/*
+    string to string map typedef
+*/
+typedef struct map_str_
+{
+    byte *key;
+    byte *data;
+    struct map_str_ *next;
+} map_str;
+
+static void map_str_create (map_str **ma)
+{
+    *ma = mem_alloc (sizeof (map_str));
+    if (*ma)
+    {
+        (**ma).key = NULL;
+        (**ma).data = NULL;
+        (**ma).next = NULL;
+    }
+}
+
+static void map_str_destroy (map_str **ma)
+{
+    if (*ma)
+    {
+        map_str_destroy (&(**ma).next);
+        mem_free ((void **) &(**ma).key);
+        mem_free ((void **) &(**ma).data);
+        mem_free ((void **) ma);
+    }
+}
+
+static void map_str_append (map_str **ma, map_str **nm)
+{
+    while (*ma)
+        ma = &(**ma).next;
+    *ma = *nm;
+}
+
+/*
+    searches the map for specified key,
+    if the key is matched, *data is filled with data associated with the key,
+    returns 0 if the key is matched,
+    returns 1 otherwise
+*/
+static int map_str_find (map_str **ma, const byte *key, byte **data)
+{
+    while (*ma)
+    {
+        if (str_equal ((**ma).key, key))
+        {
+            *data = str_duplicate ((**ma).data);
+            if (*data == NULL)
+                return 1;
+
+            return 0;
+        }
+
+        ma = &(**ma).next;
+    }
+
+    set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+    return 1;
+}
+
+/*
+    string to rule map typedef
+*/
+typedef struct map_rule_
+{
+    byte *key;
+    rule *data;
+    struct map_rule_ *next;
+} map_rule;
+
+static void map_rule_create (map_rule **ma)
+{
+    *ma = mem_alloc (sizeof (map_rule));
+    if (*ma)
+    {
+        (**ma).key = NULL;
+        (**ma).data = NULL;
+        (**ma).next = NULL;
+    }
+}
+
+static void map_rule_destroy (map_rule **ma)
+{
+    if (*ma)
+    {
+        map_rule_destroy (&(**ma).next);
+        mem_free ((void **) &(**ma).key);
+        mem_free ((void **) ma);
+    }
+}
+
+static void map_rule_append (map_rule **ma, map_rule **nm)
+{
+    while (*ma)
+        ma = &(**ma).next;
+    *ma = *nm;
+}
+
+/*
+    searches the map for specified key,
+    if the key is matched, *data is filled with data associated with the key,
+    returns 0 if the is matched,
+    returns 1 otherwise
+*/
+static int map_rule_find (map_rule **ma, const byte *key, rule **data)
+{
+    while (*ma)
+    {
+        if (str_equal ((**ma).key, key))
+        {
+            *data = (**ma).data;
+
+            return 0;
+        }
+
+        ma = &(**ma).next;
+    }
+
+    set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+    return 1;
+}
+
+/*
+    returns 1 if given character is a white space,
+    returns 0 otherwise
+*/
+static int is_space (byte c)
+{
+    return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+}
+
+/*
+    advances text pointer by 1 if character pointed by *text is a space,
+    returns 1 if a space has been eaten,
+    returns 0 otherwise
+*/
+static int eat_space (const byte **text)
+{
+    if (is_space (**text))
+    {
+        (*text)++;
+
+        return 1;
+    }
+
+    return 0;
+}
+
+/*
+    returns 1 if text points to C-style comment start string "/*",
+    returns 0 otherwise
+*/
+static int is_comment_start (const byte *text)
+{
+    return text[0] == '/' && text[1] == '*';
+}
+
+/*
+    advances text pointer to first character after C-style comment block - if any,
+    returns 1 if C-style comment block has been encountered and eaten,
+    returns 0 otherwise
+*/
+static int eat_comment (const byte **text)
+{
+    if (is_comment_start (*text))
+    {
+        /* *text points to comment block - skip two characters to enter comment body */
+        *text += 2;
+        /* skip any character except consecutive '*' and '/' */
+        while (!((*text)[0] == '*' && (*text)[1] == '/'))
+            (*text)++;
+        /* skip those two terminating characters */
+        *text += 2;
+
+        return 1;
+    }
+
+    return 0;
+}
+
+/*
+    advances text pointer to first character that is neither space nor C-style comment block
+*/
+static void eat_spaces (const byte **text)
+{
+    while (eat_space (text) || eat_comment (text))
+        ;
+}
+
+/*
+    resizes string pointed by *ptr to successfully add character c to the end of the string,
+    returns 0 on success,
+    returns 1 otherwise
+*/
+static int string_grow (byte **ptr, unsigned int *len, byte c)
+{
+    /* reallocate the string in 16-byte increments */
+    if ((*len & 0x0F) == 0x0F || *ptr == NULL)
+    {
+        byte *tmp = mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),
+            ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));
+        if (tmp == NULL)
+            return 1;
+
+        *ptr = tmp;
+    }
+
+    if (c)
+    {
+        /* append given character */
+        (*ptr)[*len] = c;
+        (*len)++;
+    }
+    (*ptr)[*len] = '\0';
+
+    return 0;
+}
+
+/*
+    returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _
+    returns 0 otherwise
+*/
+static int is_identifier (byte c)
+{
+    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+}
+
+/*
+    copies characters from *text to *id until non-identifier character is encountered,
+    assumes that *id points to NULL object - caller is responsible for later freeing the string,
+    text pointer is advanced to point past the copied identifier,
+    returns 0 if identifier was successfully copied,
+    returns 1 otherwise
+*/
+static int get_identifier (const byte **text, byte **id)
+{
+    const byte *t = *text;
+    byte *p = NULL;
+    unsigned int len = 0;
+
+    if (string_grow (&p, &len, '\0'))
+        return 1;
+
+    /* loop while next character in buffer is valid for identifiers */
+    while (is_identifier (*t))
+    {
+        if (string_grow (&p, &len, *t++))
+        {
+            mem_free ((void **) &p);
+            return 1;
+        }
+    }
+
+    *text = t;
+    *id = p;
+
+    return 0;
+}
+
+/*
+    returns 1 if given character is HEX digit 0-9, A-F or a-f,
+    returns 0 otherwise
+*/
+static int is_hex (byte c)
+{
+    return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
+}
+
+/*
+    returns value of passed character as if it was HEX digit
+*/
+static unsigned int hex2dec (byte c)
+{
+    if (c >= '0' && c <= '9')
+        return c - '0';
+    if (c >= 'A' && c <= 'F')
+        return c - 'A' + 10;
+    return c - 'a' + 10;
+}
+
+/*
+    converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
+    advances text pointer past the converted sequence,
+    returns the converted value
+*/
+static unsigned int hex_convert (const byte **text)
+{
+    unsigned int value = 0;
+
+    while (is_hex (**text))
+    {
+        value = value * 0x10 + hex2dec (**text);
+        (*text)++;
+    }
+
+    return value;
+}
+
+/*
+    returns 1 if given character is OCT digit 0-7,
+    returns 0 otherwise
+*/
+static int is_oct (byte c)
+{
+    return c >= '0' && c <= '7';
+}
+
+/*
+    returns value of passed character as if it was OCT digit
+*/
+static int oct2dec (byte c)
+{
+    return c - '0';
+}
+
+static byte get_escape_sequence (const byte **text)
+{
+    int value = 0;
+
+    /* skip '\' character */
+    (*text)++;
+
+    switch (*(*text)++)
+    {
+    case '\'':
+        return '\'';
+    case '"':
+        return '\"';
+    case '?':
+        return '\?';
+    case '\\':
+        return '\\';
+    case 'a':
+        return '\a';
+    case 'b':
+        return '\b';
+    case 'f':
+        return '\f';
+    case 'n':
+        return '\n';
+    case 'r':
+        return '\r';
+    case 't':
+        return '\t';
+    case 'v':
+        return '\v';
+    case 'x':
+        return (byte) hex_convert (text);
+    }
+
+    (*text)--;
+    if (is_oct (**text))
+    {
+        value = oct2dec (*(*text)++);
+        if (is_oct (**text))
+        {
+            value = value * 010 + oct2dec (*(*text)++);
+            if (is_oct (**text))
+                value = value * 010 + oct2dec (*(*text)++);
+        }
+    }
+
+    return (byte) value;
+}
+
+/*
+    copies characters from *text to *str until " or ' character is encountered,
+    assumes that *str points to NULL object - caller is responsible for later freeing the string,
+    assumes that *text points to " or ' character that starts the string,
+    text pointer is advanced to point past the " or ' character,
+    returns 0 if string was successfully copied,
+    returns 1 otherwise
+*/
+static int get_string (const byte **text, byte **str)
+{
+    const byte *t = *text;
+    byte *p = NULL;
+    unsigned int len = 0;
+    byte term_char;
+
+    if (string_grow (&p, &len, '\0'))
+        return 1;
+
+    /* read " or ' character that starts the string */
+    term_char = *t++;
+    /* while next character is not the terminating character */
+    while (*t && *t != term_char)
+    {
+        byte c;
+
+        if (*t == '\\')
+            c = get_escape_sequence (&t);
+        else
+            c = *t++;
+
+        if (string_grow (&p, &len, c))
+        {
+            mem_free ((void **) &p);
+            return 1;
+        }
+    }
+    /* skip " or ' character that ends the string */
+    t++;
+
+    *text = t;
+    *str = p;
+    return 0;
+}
+
+/*
+    gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
+    assumes that *text already points to <symbol>,
+    returns 0 if emit code is successfully read,
+    returns 1 otherwise
+*/
+static int get_emtcode (const byte **text, map_byte **ma)
+{
+    const byte *t = *text;
+    map_byte *m = NULL;
+
+    map_byte_create (&m);
+    if (m == NULL)
+        return 1;
+
+    if (get_identifier (&t, &m->key))
+    {
+        map_byte_destroy (&m);
+        return 1;
+    }
+    eat_spaces (&t);
+
+    if (*t == '\'')
+    {
+        byte *c;
+
+        if (get_string (&t, &c))
+        {
+            map_byte_destroy (&m);
+            return 1;
+        }
+
+        m->data = (byte) c[0];
+        mem_free ((void **) &c);
+    }
+    else
+    {
+        /* skip HEX "0x" or "0X" prefix */
+        t += 2;
+        m->data = (byte) hex_convert (&t);
+    }
+
+    eat_spaces (&t);
+
+    *text = t;
+    *ma = m;
+    return 0;
+}
+
+/*
+    gets regbyte declaration, the syntax is: ".regbyte" " " <symbol> " " ("0x" | "0X") <hex_value>
+    assumes that *text already points to <symbol>,
+    returns 0 if regbyte is successfully read,
+    returns 1 otherwise
+*/
+static int get_regbyte (const byte **text, map_byte **ma)
+{
+    return get_emtcode (text, ma);
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise
+*/
+static int get_errtext (const byte **text, map_str **ma)
+{
+    const byte *t = *text;
+    map_str *m = NULL;
+
+    map_str_create (&m);
+    if (m == NULL)
+        return 1;
+
+    if (get_identifier (&t, &m->key))
+    {
+        map_str_destroy (&m);
+        return 1;
+    }
+    eat_spaces (&t);
+
+    if (get_string (&t, &m->data))
+    {
+        map_str_destroy (&m);
+        return 1;
+    }
+    eat_spaces (&t);
+
+    *text = t;
+    *ma = m;
+    return 0;
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise,
+*/
+static int get_error (const byte **text, error **er, map_str *maps)
+{
+    const byte *t = *text;
+    byte *temp = NULL;
+
+    if (*t != '.')
+        return 0;
+
+    t++;
+    if (get_identifier (&t, &temp))
+        return 1;
+    eat_spaces (&t);
+
+    if (!str_equal ((byte *) "error", temp))
+    {
+        mem_free ((void **) &temp);
+        return 0;
+    }
+
+    mem_free ((void **) &temp);
+
+    error_create (er);
+    if (*er == NULL)
+        return 1;
+
+    if (*t == '\"')
+    {
+        if (get_string (&t, &(**er).m_text))
+        {
+            error_destroy (er);
+            return 1;
+        }
+        eat_spaces (&t);
+    }
+    else
+    {
+        if (get_identifier (&t, &temp))
+        {
+            error_destroy (er);
+            return 1;
+        }
+        eat_spaces (&t);
+
+        if (map_str_find (&maps, temp, &(**er).m_text))
+        {
+            mem_free ((void **) &temp);
+            error_destroy (er);
+            return 1;
+        }
+
+        mem_free ((void **) &temp);
+    }
+
+    /* try to extract "token" from "...$token$..." */
+    {
+        byte *processed = NULL;
+        unsigned int len = 0, i = 0;
+
+        if (string_grow (&processed, &len, '\0'))
+        {
+            error_destroy (er);
+            return 1;
+        }
+
+        while (i < str_length ((**er).m_text))
+        {
+            /* check if the dollar sign is repeated - if so skip it */
+            if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$')
+            {
+                if (string_grow (&processed, &len, '$'))
+                {
+                    mem_free ((void **) &processed);
+                    error_destroy (er);
+                    return 1;
+                }
+
+                i += 2;
+            }
+            else if ((**er).m_text[i] != '$')
+            {
+                if (string_grow (&processed, &len, (**er).m_text[i]))
+                {
+                    mem_free ((void **) &processed);
+                    error_destroy (er);
+                    return 1;
+                }
+
+                i++;
+            }
+            else
+            {
+                if (string_grow (&processed, &len, '$'))
+                {
+                    mem_free ((void **) &processed);
+                    error_destroy (er);
+                    return 1;
+                }
+
+                {
+                    /* length of token being extracted */
+                    unsigned int tlen = 0;
+
+                    if (string_grow (&(**er).m_token_name, &tlen, '\0'))
+                    {
+                        mem_free ((void **) &processed);
+                        error_destroy (er);
+                        return 1;
+                    }
+
+                    /* skip the dollar sign */
+                    i++;
+
+                    while ((**er).m_text[i] != '$')
+                    {
+                        if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i]))
+                        {
+                            mem_free ((void **) &processed);
+                            error_destroy (er);
+                            return 1;
+                        }
+
+                        i++;
+                    }
+
+                    /* skip the dollar sign */
+                    i++;
+                }
+            }
+        }
+
+        mem_free ((void **) &(**er).m_text);
+        (**er).m_text = processed;
+    }
+
+    *text = t;
+    return 0;
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise,
+*/
+static int get_emits (const byte **text, emit **em, map_byte *mapb)
+{
+    const byte *t = *text;
+    byte *temp = NULL;
+    emit *e = NULL;
+    emit_dest dest;
+
+    if (*t != '.')
+        return 0;
+
+    t++;
+    if (get_identifier (&t, &temp))
+        return 1;
+    eat_spaces (&t);
+
+    /* .emit */
+    if (str_equal ((byte *) "emit", temp))
+        dest = ed_output;
+    /* .load */
+    else if (str_equal ((byte *) "load", temp))
+        dest = ed_regbyte;
+    else
+    {
+        mem_free ((void **) &temp);
+        return 0;
+    }
+
+    mem_free ((void **) &temp);
+
+    emit_create (&e);
+    if (e == NULL)
+        return 1;
+
+    e->m_emit_dest = dest;
+
+    if (dest == ed_regbyte)
+    {
+        if (get_identifier (&t, &e->m_regname))
+        {
+            emit_destroy (&e);
+            return 1;
+        }
+        eat_spaces (&t);
+    }
+
+    /* 0xNN */
+    if (*t == '0')
+    {
+        t += 2;
+        e->m_byte = (byte) hex_convert (&t);
+
+        e->m_emit_type = et_byte;
+    }
+    /* * */
+    else if (*t == '*')
+    {
+        t++;
+
+        e->m_emit_type = et_stream;
+    }
+    /* $ */
+    else if (*t == '$')
+    {
+        t++;
+
+        e->m_emit_type = et_position;
+    }
+    /* 'c' */
+    else if (*t == '\'')
+    {
+        if (get_string (&t, &temp))
+        {
+            emit_destroy (&e);
+            return 1;
+        }
+        e->m_byte = (byte) temp[0];
+
+        mem_free ((void **) &temp);
+
+        e->m_emit_type = et_byte;
+    }
+    else
+    {
+        if (get_identifier (&t, &temp))
+        {
+            emit_destroy (&e);
+            return 1;
+        }
+
+        if (map_byte_find (&mapb, temp, &e->m_byte))
+        {
+            mem_free ((void **) &temp);
+            emit_destroy (&e);
+            return 1;
+        }
+
+        mem_free ((void **) &temp);
+
+        e->m_emit_type = et_byte;
+    }
+
+    eat_spaces (&t);
+
+    if (get_emits (&t, &e->m_next, mapb))
+    {
+        emit_destroy (&e);
+        return 1;
+    }
+
+    *text = t;
+    *em = e;
+    return 0;
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise,
+*/
+static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb)
+{
+    const byte *t = *text;
+    spec *s = NULL;
+
+    spec_create (&s);
+    if (s == NULL)
+        return 1;
+
+    /* first - read optional .if statement */
+    if (*t == '.')
+    {
+        const byte *u = t;
+        byte *keyword = NULL;
+
+        /* skip the dot */
+        u++;
+
+        if (get_identifier (&u, &keyword))
+        {
+            spec_destroy (&s);
+            return 1;
+        }
+
+        /* .if */
+        if (str_equal ((byte *) "if", keyword))
+        {
+            cond_create (&s->m_cond);
+            if (s->m_cond == NULL)
+            {
+                spec_destroy (&s);
+                return 1;
+            }
+
+            /* skip the left paren */
+            eat_spaces (&u);
+            u++;
+
+            /* get the left operand */
+            eat_spaces (&u);
+            if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname))
+            {
+                spec_destroy (&s);
+                return 1;
+            }
+            s->m_cond->m_operands[0].m_type = cot_regbyte;
+
+            /* get the operator (!= or ==) */
+            eat_spaces (&u);
+            if (*u == '!')
+                s->m_cond->m_type = ct_not_equal;
+            else
+                s->m_cond->m_type = ct_equal;
+            u += 2;
+
+            /* skip the 0x prefix */
+            eat_spaces (&u);
+            u += 2;
+
+            /* get the right operand */
+            s->m_cond->m_operands[1].m_byte = hex_convert (&u);
+            s->m_cond->m_operands[1].m_type = cot_byte;
+
+            /* skip the right paren */
+            eat_spaces (&u);
+            u++;
+
+            eat_spaces (&u);
+
+            t = u;
+        }
+
+        mem_free ((void **) &keyword);
+    }
+
+    if (*t == '\'')
+    {
+        byte *temp = NULL;
+
+        if (get_string (&t, &temp))
+        {
+            spec_destroy (&s);
+            return 1;
+        }
+        eat_spaces (&t);
+
+        if (*t == '-')
+        {
+            byte *temp2 = NULL;
+
+            /* skip the '-' character */
+            t++;
+            eat_spaces (&t);
+
+            if (get_string (&t, &temp2))
+            {
+                mem_free ((void **) &temp);
+                spec_destroy (&s);
+                return 1;
+            }
+            eat_spaces (&t);
+
+            s->m_spec_type = st_byte_range;
+            s->m_byte[0] = *temp;
+            s->m_byte[1] = *temp2;
+
+            mem_free ((void **) &temp2);
+        }
+        else
+        {
+            s->m_spec_type = st_byte;
+            *s->m_byte = *temp;
+        }
+
+        mem_free ((void **) &temp);
+    }
+    else if (*t == '"')
+    {
+        if (get_string (&t, &s->m_string))
+        {
+            spec_destroy (&s);
+            return 1;
+        }
+        eat_spaces (&t);
+
+        s->m_spec_type = st_string;
+    }
+    else if (*t == '.')
+    {
+        byte *keyword = NULL;
+
+        /* skip the dot */
+        t++;
+
+        if (get_identifier (&t, &keyword))
+        {
+            spec_destroy (&s);
+            return 1;
+        }
+        eat_spaces (&t);
+
+        /* .true */
+        if (str_equal ((byte *) "true", keyword))
+        {
+            s->m_spec_type = st_true;
+        }
+        /* .false */
+        else if (str_equal ((byte *) "false", keyword))
+        {
+            s->m_spec_type = st_false;
+        }
+        /* .debug */
+        else if (str_equal ((byte *) "debug", keyword))
+        {
+            s->m_spec_type = st_debug;
+        }
+        /* .loop */
+        else if (str_equal ((byte *) "loop", keyword))
+        {
+            if (get_identifier (&t, &s->m_string))
+            {
+                mem_free ((void **) &keyword);
+                spec_destroy (&s);
+                return 1;
+            }
+            eat_spaces (&t);
+
+            s->m_spec_type = st_identifier_loop;
+        }
+
+        mem_free ((void **) &keyword);
+    }
+    else
+    {
+        if (get_identifier (&t, &s->m_string))
+        {
+            spec_destroy (&s);
+            return 1;
+        }
+        eat_spaces (&t);
+
+        s->m_spec_type = st_identifier;
+    }
+
+    if (get_error (&t, &s->m_errtext, maps))
+    {
+        spec_destroy (&s);
+        return 1;
+    }
+
+    if (get_emits (&t, &s->m_emits, mapb))
+    {
+        spec_destroy (&s);
+        return 1;
+    }
+
+    *text = t;
+    *sp = s;
+    return 0;
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise,
+*/
+static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)
+{
+    const byte *t = *text;
+    rule *r = NULL;
+
+    rule_create (&r);
+    if (r == NULL)
+        return 1;
+
+    if (get_spec (&t, &r->m_specs, maps, mapb))
+    {
+        rule_destroy (&r);
+        return 1;
+    }
+
+    while (*t != ';')
+    {
+        byte *op = NULL;
+        spec *sp = NULL;
+
+        /* skip the dot that precedes "and" or "or" */
+        t++;
+
+        /* read "and" or "or" keyword */
+        if (get_identifier (&t, &op))
+        {
+            rule_destroy (&r);
+            return 1;
+        }
+        eat_spaces (&t);
+
+        if (r->m_oper == op_none)
+        {
+            /* .and */
+            if (str_equal ((byte *) "and", op))
+                r->m_oper = op_and;
+            /* .or */
+            else
+                r->m_oper = op_or;
+        }
+
+        mem_free ((void **) &op);
+
+        if (get_spec (&t, &sp, maps, mapb))
+        {
+            rule_destroy (&r);
+            return 1;
+        }
+
+        spec_append (&r->m_specs, &sp);
+    }
+
+    /* skip the semicolon */
+    t++;
+    eat_spaces (&t);
+
+    *text = t;
+    *ru = r;
+    return 0;
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise,
+*/
+static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)
+{
+    if (map_rule_find (&mapr, symbol, ru))
+        return 1;
+
+/*  (**ru).m_referenced = 1; */
+
+    return 0;
+}
+
+/*
+    returns 0 on success,
+    returns 1 otherwise,
+*/
+static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,
+    byte **string_symbol, map_byte *regbytes)
+{
+    rule *rulez = di->m_rulez;
+
+    /* update dependecies for the root and lexer symbols */
+    if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||
+        (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))
+        return 1;
+
+    mem_free ((void **) syntax_symbol);
+    mem_free ((void **) string_symbol);
+
+    /* update dependecies for the rest of the rules */
+    while (rulez)
+    {
+        spec *sp = rulez->m_specs;
+
+        /* iterate through all the specifiers */
+        while (sp)
+        {
+            /* update dependency for identifier */
+            if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)
+            {
+                if (update_dependency (mapr, sp->m_string, &sp->m_rule))
+                    return 1;
+
+                mem_free ((void **) &sp->m_string);
+            }
+
+            /* some errtexts reference to a rule */
+            if (sp->m_errtext && sp->m_errtext->m_token_name)
+            {
+                if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))
+                    return 1;
+
+                mem_free ((void **) &sp->m_errtext->m_token_name);
+            }
+
+            /* update dependency for condition */
+            if (sp->m_cond)
+            {
+                int i;
+                for (i = 0; i < 2; i++)
+                    if (sp->m_cond->m_operands[i].m_type == cot_regbyte)
+                    {
+                        sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (&regbytes,
+                            sp->m_cond->m_operands[i].m_regname);
+
+                        if (sp->m_cond->m_operands[i].m_regbyte == NULL)
+                            return 1;
+
+                        mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);
+                    }
+            }
+
+            /* update dependency for all .load instructions */
+            if (sp->m_emits)
+            {
+                emit *em = sp->m_emits;
+                while (em != NULL)
+                {
+                    if (em->m_emit_dest == ed_regbyte)
+                    {
+                        em->m_regbyte = map_byte_locate (&regbytes, em->m_regname);
+
+                        if (em->m_regbyte == NULL)
+                            return 1;
+
+                        mem_free ((void **) &em->m_regname);
+                    }
+
+                    em = em->m_next;
+                }
+            }
+
+            sp = sp->m_next;
+        }
+
+        rulez = rulez->m_next;
+    }
+
+/* check for unreferenced symbols */
+/*  de = di->m_defntns;
+    while (de)
+    {
+        if (!de->m_referenced)
+        {
+            map_def *ma = mapd;
+            while (ma)
+            {
+                if (ma->data == de)
+                {
+                    assert (0);
+                    break;
+                }
+                ma = ma->next;
+            }
+        }
+        de = de->m_next;
+    }
+*/
+    return 0;
+}
+
+static int satisfies_condition (cond *co, regbyte_ctx *ctx)
+{
+    byte values[2];
+    int i;
+
+    if (co == NULL)
+        return 1;
+
+    for (i = 0; i < 2; i++)
+        switch (co->m_operands[i].m_type)
+        {
+        case cot_byte:
+            values[i] = co->m_operands[i].m_byte;
+            break;
+        case cot_regbyte:
+            values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);
+            break;
+        }
+
+    switch (co->m_type)
+    {
+    case ct_equal:
+        return values[0] == values[1];
+    case ct_not_equal:
+        return values[0] != values[1];
+    }
+
+    return 0;
+}
+
+static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)
+{
+    while (top != limit)
+    {
+        regbyte_ctx *rbc = top->m_prev;
+        regbyte_ctx_destroy (&top);
+        top = rbc;
+    }
+}
+
+typedef enum match_result_
+{
+    mr_not_matched,     /* the examined string does not match */
+    mr_matched,         /* the examined string matches */
+    mr_error_raised,    /* mr_not_matched + error has been raised */
+    mr_dont_emit,       /* used by identifier loops only */
+    mr_internal_error   /* an internal error has occured such as out of memory */
+} match_result;
+
+/*
+    This function does the main job. It parses the text and generates output data.
+
+    XXX optimize it - the barray seems to be the bottleneck
+*/
+static match_result match (dict *di, const byte *text, unsigned int *index, rule *ru, barray **ba,
+    int filtering_string, regbyte_ctx **rbc)
+{
+    unsigned int ind = *index;
+    match_result status = mr_not_matched;
+    spec *sp = ru->m_specs;
+    regbyte_ctx *ctx = *rbc;
+
+    /* for every specifier in the rule */
+    while (sp)
+    {
+        unsigned int i, len, save_ind = ind;
+        barray *array = NULL;
+
+        if (satisfies_condition (sp->m_cond, ctx))
+        {
+            switch (sp->m_spec_type)
+            {
+            case st_identifier:
+                barray_create (&array);
+                if (array == NULL)
+                {
+                    free_regbyte_ctx_stack (ctx, *rbc);
+                    return mr_internal_error;
+                }
+
+                status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
+                if (status == mr_internal_error)
+                {
+                    free_regbyte_ctx_stack (ctx, *rbc);
+                    barray_destroy (&array);
+                    return mr_internal_error;
+                }
+                break;
+            case st_string:
+                len = str_length (sp->m_string);
+
+                /* prefilter the stream */
+                if (!filtering_string && di->m_string)
+                {
+                    barray *ba;
+                    unsigned int filter_index = 0;
+                    match_result result;
+                    regbyte_ctx *null_ctx = NULL;
+
+                    barray_create (&ba);
+                    if (ba == NULL)
+                    {
+                        free_regbyte_ctx_stack (ctx, *rbc);
+                        return mr_internal_error;
+                    }
+
+                    result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);
+
+                    if (result == mr_internal_error)
+                    {
+                        free_regbyte_ctx_stack (ctx, *rbc);
+                        barray_destroy (&ba);
+                        return mr_internal_error;
+                    }
+
+                    if (result != mr_matched)
+                    {
+                        barray_destroy (&ba);
+                        status = mr_not_matched;
+                        break;
+                    }
+
+                    barray_destroy (&ba);
+
+                    if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))
+                    {
+                        status = mr_not_matched;
+                        break;
+                    }
+
+                    status = mr_matched;
+                    ind += len;
+                }
+                else
+                {
+                    status = mr_matched;
+                    for (i = 0; status == mr_matched && i < len; i++)
+                        if (text[ind + i] != sp->m_string[i])
+                            status = mr_not_matched;
+                    if (status == mr_matched)
+                        ind += len;
+                }
+                break;
+            case st_byte:
+                status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
+                if (status == mr_matched)
+                    ind++;
+                break;
+            case st_byte_range:
+                status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?
+                    mr_matched : mr_not_matched;
+                if (status == mr_matched)
+                    ind++;
+                break;
+            case st_true:
+                status = mr_matched;
+                break;
+            case st_false:
+                status = mr_not_matched;
+                break;
+            case st_debug:
+                status = ru->m_oper == op_and ? mr_matched : mr_not_matched;
+                break;
+            case st_identifier_loop:
+                barray_create (&array);
+                if (array == NULL)
+                {
+                    free_regbyte_ctx_stack (ctx, *rbc);
+                    return mr_internal_error;
+                }
+
+                status = mr_dont_emit;
+                for (;;)
+                {
+                    match_result result;
+
+                    save_ind = ind;
+                    result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
+
+                    if (result == mr_error_raised)
+                    {
+                        status = result;
+                        break;
+                    }
+                    else if (result == mr_matched)
+                    {
+                        if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||
+                            barray_append (ba, &array))
+                        {
+                            free_regbyte_ctx_stack (ctx, *rbc);
+                            barray_destroy (&array);
+                            return mr_internal_error;
+                        }
+                        barray_destroy (&array);
+                        barray_create (&array);
+                        if (array == NULL)
+                        {
+                            free_regbyte_ctx_stack (ctx, *rbc);
+                            return mr_internal_error;
+                        }
+                    }
+                    else if (result == mr_internal_error)
+                    {
+                        free_regbyte_ctx_stack (ctx, *rbc);
+                        barray_destroy (&array);
+                        return mr_internal_error;
+                    }
+                    else
+                        break;
+                }
+                break;
+            }
+        }
+        else
+        {
+            status = mr_not_matched;
+        }
+
+        if (status == mr_error_raised)
+        {
+            free_regbyte_ctx_stack (ctx, *rbc);
+            barray_destroy (&array);
+
+            return mr_error_raised;
+        }
+
+        if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)
+        {
+            free_regbyte_ctx_stack (ctx, *rbc);
+            barray_destroy (&array);
+
+            if (sp->m_errtext)
+            {
+                set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,
+                    ind), ind);
+
+                return mr_error_raised;
+            }
+
+            return mr_not_matched;
+        }
+
+        if (status == mr_matched)
+        {
+            if (sp->m_emits)
+                if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx))
+                {
+                    free_regbyte_ctx_stack (ctx, *rbc);
+                    barray_destroy (&array);
+                    return mr_internal_error;
+                }
+
+            if (array)
+                if (barray_append (ba, &array))
+                {
+                    free_regbyte_ctx_stack (ctx, *rbc);
+                    barray_destroy (&array);
+                    return mr_internal_error;
+                }
+        }
+
+        barray_destroy (&array);
+
+        /* if the rule operator is a logical or, we pick up the first matching specifier */
+        if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))
+        {
+            *index = ind;
+            *rbc = ctx;
+            return mr_matched;
+        }
+
+        sp = sp->m_next;
+    }
+
+    /* everything went fine - all specifiers match up */
+    if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))
+    {
+        *index = ind;
+        *rbc = ctx;
+        return mr_matched;
+    }
+
+    free_regbyte_ctx_stack (ctx, *rbc);
+    return mr_not_matched;
+}
+
+static byte *error_get_token (error *er, dict *di, const byte *text, unsigned int ind)
+{
+    byte *str = NULL;
+
+    if (er->m_token)
+    {
+        barray *ba;
+        unsigned int filter_index = 0;
+        regbyte_ctx *ctx = NULL;
+
+        barray_create (&ba);
+        if (ba != NULL)
+        {
+            if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched &&
+                filter_index)
+            {
+                str = mem_alloc (filter_index + 1);
+                if (str != NULL)
+                {
+                    str_copy_n (str, text + ind, filter_index);
+                    str[filter_index] = '\0';
+                }
+            }
+            barray_destroy (&ba);
+        }
+    }
+
+    return str;
+}
+
+typedef struct grammar_load_state_
+{
+    dict *di;
+    byte *syntax_symbol;
+    byte *string_symbol;
+    map_str *maps;
+    map_byte *mapb;
+    map_rule *mapr;
+} grammar_load_state;
+
+static void grammar_load_state_create (grammar_load_state **gr)
+{
+    *gr = mem_alloc (sizeof (grammar_load_state));
+    if (*gr)
+    {
+        (**gr).di = NULL;
+        (**gr).syntax_symbol = NULL;
+        (**gr).string_symbol = NULL;
+        (**gr).maps = NULL;
+        (**gr).mapb = NULL;
+        (**gr).mapr = NULL;
+    }
+}
+
+static void grammar_load_state_destroy (grammar_load_state **gr)
+{
+    if (*gr)
+    {
+        dict_destroy (&(**gr).di);
+        mem_free ((void **) &(**gr).syntax_symbol);
+        mem_free ((void **) &(**gr).string_symbol);
+        map_str_destroy (&(**gr).maps);
+        map_byte_destroy (&(**gr).mapb);
+        map_rule_destroy (&(**gr).mapr);
+        mem_free ((void **) gr);
+    }
+}
+
+/*
+    the API
+*/
+
+grammar grammar_load_from_text (const byte *text)
+{
+    grammar_load_state *g = NULL;
+    grammar id = 0;
+
+    clear_last_error ();
+
+    grammar_load_state_create (&g);
+    if (g == NULL)
+        return 0;
+
+    dict_create (&g->di);
+    if (g->di == NULL)
+    {
+        grammar_load_state_destroy (&g);
+        return 0;
+    }
+
+    eat_spaces (&text);
+
+    /* skip ".syntax" keyword */
+    text += 7;
+    eat_spaces (&text);
+
+    /* retrieve root symbol */
+    if (get_identifier (&text, &g->syntax_symbol))
+    {
+        grammar_load_state_destroy (&g);
+        return 0;
+    }
+    eat_spaces (&text);
+
+    /* skip semicolon */
+    text++;
+    eat_spaces (&text);
+
+    while (*text)
+    {
+        byte *symbol = NULL;
+        int is_dot = *text == '.';
+
+        if (is_dot)
+            text++;
+
+        if (get_identifier (&text, &symbol))
+        {
+            grammar_load_state_destroy (&g);
+            return 0;
+        }
+        eat_spaces (&text);
+
+        /* .emtcode */
+        if (is_dot && str_equal (symbol, (byte *) "emtcode"))
+        {
+            map_byte *ma = NULL;
+
+            mem_free ((void **) &symbol);
+
+            if (get_emtcode (&text, &ma))
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            map_byte_append (&g->mapb, &ma);
+        }
+        /* .regbyte */
+        else if (is_dot && str_equal (symbol, (byte *) "regbyte"))
+        {
+            map_byte *ma = NULL;
+
+            mem_free ((void **) &symbol);
+
+            if (get_regbyte (&text, &ma))
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            map_byte_append (&g->di->m_regbytes, &ma);
+        }
+        /* .errtext */
+        else if (is_dot && str_equal (symbol, (byte *) "errtext"))
+        {
+            map_str *ma = NULL;
+
+            mem_free ((void **) &symbol);
+
+            if (get_errtext (&text, &ma))
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            map_str_append (&g->maps, &ma);
+        }
+        /* .string */
+        else if (is_dot && str_equal (symbol, (byte *) "string"))
+        {
+            mem_free ((void **) &symbol);
+
+            if (g->di->m_string != NULL)
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            if (get_identifier (&text, &g->string_symbol))
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            /* skip semicolon */
+            eat_spaces (&text);
+            text++;
+            eat_spaces (&text);
+        }
+        else
+        {
+            rule *ru = NULL;
+            map_rule *ma = NULL;
+
+            if (get_rule (&text, &ru, g->maps, g->mapb))
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            rule_append (&g->di->m_rulez, &ru);
+
+            /* if a rule consist of only one specifier, give it an ".and" operator */
+            if (ru->m_oper == op_none)
+                ru->m_oper = op_and;
+
+            map_rule_create (&ma);
+            if (ma == NULL)
+            {
+                grammar_load_state_destroy (&g);
+                return 0;
+            }
+
+            ma->key = symbol;
+            ma->data = ru;
+            map_rule_append (&g->mapr, &ma);
+        }
+    }
+
+    if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol,
+        g->di->m_regbytes))
+    {
+        grammar_load_state_destroy (&g);
+        return 0;
+    }
+
+    dict_append (&g_dicts, &g->di);
+    id = g->di->m_id;
+    g->di = NULL;
+
+    grammar_load_state_destroy (&g);
+
+    return id;
+}
+
+int grammar_set_reg8 (grammar id, const byte *name, byte value)
+{
+    dict *di = NULL;
+    map_byte *reg = NULL;
+
+    clear_last_error ();
+
+    dict_find (&g_dicts, id, &di);
+    if (di == NULL)
+    {
+        set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+        return 0;
+    }
+
+    reg = map_byte_locate (&di->m_regbytes, name);
+    if (reg == NULL)
+    {
+        set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1);
+        return 0;
+    }
+
+    reg->data = value;
+    return 1;
+}
+
+int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size)
+{
+    dict *di = NULL;
+    barray *ba = NULL;
+    unsigned int index = 0;
+    regbyte_ctx *rbc = NULL;
+
+    clear_last_error ();
+
+    dict_find (&g_dicts, id, &di);
+    if (di == NULL)
+    {
+        set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+        return 0;
+    }
+
+    barray_create (&ba);
+    if (ba == NULL)
+        return 0;
+
+    *prod = NULL;
+    *size = 0;
+
+    if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched)
+    {
+        barray_destroy (&ba);
+        free_regbyte_ctx_stack (rbc, NULL);
+        return 0;
+    }
+
+    free_regbyte_ctx_stack (rbc, NULL);
+
+    *prod = mem_alloc (ba->len * sizeof (byte));
+    if (*prod == NULL)
+    {
+        barray_destroy (&ba);
+        return 0;
+    }
+
+    mem_copy (*prod, ba->data, ba->len * sizeof (byte));
+    *size = ba->len;
+    barray_destroy (&ba);
+
+    return 1;
+}
+
+int grammar_destroy (grammar id)
+{
+    dict **di = &g_dicts;
+
+    clear_last_error ();
+
+    while (*di != NULL)
+    {
+        if ((**di).m_id == id)
+        {
+            dict *tmp = *di;
+            *di = (**di).m_next;
+            dict_destroy (&tmp);
+            return 1;
+        }
+
+        di = &(**di).m_next;
+    }
+
+    set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+    return 0;
+}
+
+void grammar_get_last_error (byte *text, unsigned int size, int *pos)
+{
+    unsigned int len = 0, dots_made = 0;
+    const byte *p = error_message;
+
+    *text = '\0';
+
+#define APPEND_CHARACTER(x) if (dots_made == 0) {\
+                                if (len < size - 1) {\
+                                    text[len++] = (x); text[len] = '\0';\
+                                } else {\
+                                    int i;\
+                                    for (i = 0; i < 3; i++)\
+                                        if (--len >= 0)\
+                                            text[len] = '.';\
+                                    dots_made = 1;\
+                                }\
+                            }
+
+    if (p)
+        while (*p)
+            if (*p == '$')
+            {
+                const byte *r = error_param;
+
+                while (*r)
+                {
+                    APPEND_CHARACTER(*r)
+                    r++;
+                }
+
+                p++;
+            }
+            else
+            {
+                APPEND_CHARACTER(*p)
+                p++;
+            }
+
+    *pos = error_position;
+
+#undef APPEND_CHARACTER
+
+}
+
diff --git a/src/mesa/shader/grammar.h b/src/mesa/shader/grammar.h
index 152ebc1..41a484e 100644
--- a/src/mesa/shader/grammar.h
+++ b/src/mesa/shader/grammar.h
@@ -1,68 +1,92 @@
-#ifndef GRAMMAR_H

-#define GRAMMAR_H

-

-

-#ifndef GRAMMAR_PORT_INCLUDE

-#error Do not include this file directly, include your grammar_XXX.h instead

-#endif

-

-

-#ifdef __cplusplus

-extern "C" {

-#endif

-

-void grammar_alloc_free (void *);

-void *grammar_alloc_malloc (unsigned int);

-void *grammar_alloc_realloc (void *, unsigned int, unsigned int);

-void *grammar_memory_copy (void *, const void *, unsigned int);

-int grammar_string_compare (const byte *, const byte *);

-int grammar_string_compare_n (const byte *, const byte *, unsigned int);

-byte *grammar_string_copy (byte *, const byte *);

-byte *grammar_string_copy_n (byte *, const byte *, unsigned int);

-byte *grammar_string_duplicate (const byte *);

-unsigned int grammar_string_length (const byte *);

-

-/*

-    loads grammar script from null-terminated ASCII <text>

-    returns unique grammar id to grammar object

-    returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text)

-*/

-grammar grammar_load_from_text (const byte *text);

-

-/*

-    sets a new <value> to a register <name> for grammar <id>

-    returns 0 on error (call grammar_get_last_error to retrieve the error text)

-    returns 1 on success

-*/

-int grammar_set_reg8 (grammar id, const byte *name, byte value);

-

-/*

-    checks if a null-terminated <text> matches given grammar <id>

-    returns 0 on error (call grammar_get_last_error to retrieve the error text)

-    returns 1 on success, the <prod> points to newly allocated buffer with production and <size>

-    is filled with the production size

-    call grammar_alloc_free to free the memory block pointed by <prod>

-*/

-int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size);

-

-/*

-    destroys grammar object identified by <id>

-    returns 0 on error (call grammar_get_last_error to retrieve the error text)

-    returns 1 on success

-*/

-int grammar_destroy (grammar id);

-

-/*

-    retrieves last grammar error reported either by grammar_load_from_text, grammar_check

-    or grammar_destroy

-    the user allocated <text> buffer receives error description, <pos> points to error position,

-    <size> is the size of the text buffer to fill in - it must be at least 4 bytes long,

-*/

-void grammar_get_last_error (byte *text, unsigned int size, int *pos);

-

-#ifdef __cplusplus

-}

-#endif

-

-#endif

-

+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef GRAMMAR_H
+#define GRAMMAR_H
+
+
+#ifndef GRAMMAR_PORT_INCLUDE
+#error Do not include this file directly, include your grammar_XXX.h instead
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grammar_alloc_free (void *);
+void *grammar_alloc_malloc (unsigned int);
+void *grammar_alloc_realloc (void *, unsigned int, unsigned int);
+void *grammar_memory_copy (void *, const void *, unsigned int);
+int grammar_string_compare (const byte *, const byte *);
+int grammar_string_compare_n (const byte *, const byte *, unsigned int);
+byte *grammar_string_copy (byte *, const byte *);
+byte *grammar_string_copy_n (byte *, const byte *, unsigned int);
+byte *grammar_string_duplicate (const byte *);
+unsigned int grammar_string_length (const byte *);
+
+/*
+    loads grammar script from null-terminated ASCII <text>
+    returns unique grammar id to grammar object
+    returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text)
+*/
+grammar grammar_load_from_text (const byte *text);
+
+/*
+    sets a new <value> to a register <name> for grammar <id>
+    returns 0 on error (call grammar_get_last_error to retrieve the error text)
+    returns 1 on success
+*/
+int grammar_set_reg8 (grammar id, const byte *name, byte value);
+
+/*
+    checks if a null-terminated <text> matches given grammar <id>
+    returns 0 on error (call grammar_get_last_error to retrieve the error text)
+    returns 1 on success, the <prod> points to newly allocated buffer with production and <size>
+    is filled with the production size
+    call grammar_alloc_free to free the memory block pointed by <prod>
+*/
+int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size);
+
+/*
+    destroys grammar object identified by <id>
+    returns 0 on error (call grammar_get_last_error to retrieve the error text)
+    returns 1 on success
+*/
+int grammar_destroy (grammar id);
+
+/*
+    retrieves last grammar error reported either by grammar_load_from_text, grammar_check
+    or grammar_destroy
+    the user allocated <text> buffer receives error description, <pos> points to error position,
+    <size> is the size of the text buffer to fill in - it must be at least 4 bytes long,
+*/
+void grammar_get_last_error (byte *text, unsigned int size, int *pos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/mesa/shader/grammar_mesa.c b/src/mesa/shader/grammar_mesa.c
index b9cb17f..0aadac5 100644
--- a/src/mesa/shader/grammar_mesa.c
+++ b/src/mesa/shader/grammar_mesa.c
@@ -1,57 +1,87 @@
-#include "grammar_mesa.h"

-

-#define GRAMMAR_PORT_BUILD 1

-#include "grammar.c"

-#undef GRAMMAR_PORT_BUILD

-

-

-void grammar_alloc_free (void *ptr)

-{

-    _mesa_free (ptr);

-}

-

-void *grammar_alloc_malloc (unsigned int size)

-{

-    return _mesa_malloc (size);

-}

-

-void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size)

-{

-    return _mesa_realloc (ptr, old_size, size);

-}

-

-void *grammar_memory_copy (void *dst, const void * src, unsigned int size)

-{

-    return _mesa_memcpy (dst, src, size);

-}

-

-int grammar_string_compare (const byte *str1, const byte *str2)

-{

-    return _mesa_strcmp ((const char *) str1, (const char *) str2);

-}

-

-int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n)

-{

-    return _mesa_strncmp ((const char *) str1, (const char *) str2, n);

-}

-

-byte *grammar_string_copy (byte *dst, const byte *src)

-{

-    return (byte *) _mesa_strcpy ((char *) dst, (const char *) src);

-}

-

-byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n)

-{

-    return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n);

-}

-

-byte *grammar_string_duplicate (const byte *src)

-{

-    return (byte *) _mesa_strdup ((const char *) src);

-}

-

-unsigned int grammar_string_length (const byte *str)

-{

-    return _mesa_strlen ((const char *) str);

-}

-

+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file grammar_mesa.c
+ * mesa3d port to syntax parsing engine
+ * \author Michal Krol
+ */
+
+#include "grammar_mesa.h"
+
+#define GRAMMAR_PORT_BUILD 1
+#include "grammar.c"
+#undef GRAMMAR_PORT_BUILD
+
+
+void grammar_alloc_free (void *ptr)
+{
+    _mesa_free (ptr);
+}
+
+void *grammar_alloc_malloc (unsigned int size)
+{
+    return _mesa_malloc (size);
+}
+
+void *grammar_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size)
+{
+    return _mesa_realloc (ptr, old_size, size);
+}
+
+void *grammar_memory_copy (void *dst, const void * src, unsigned int size)
+{
+    return _mesa_memcpy (dst, src, size);
+}
+
+int grammar_string_compare (const byte *str1, const byte *str2)
+{
+    return _mesa_strcmp ((const char *) str1, (const char *) str2);
+}
+
+int grammar_string_compare_n (const byte *str1, const byte *str2, unsigned int n)
+{
+    return _mesa_strncmp ((const char *) str1, (const char *) str2, n);
+}
+
+byte *grammar_string_copy (byte *dst, const byte *src)
+{
+    return (byte *) _mesa_strcpy ((char *) dst, (const char *) src);
+}
+
+byte *grammar_string_copy_n (byte *dst, const byte *src, unsigned int n)
+{
+    return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n);
+}
+
+byte *grammar_string_duplicate (const byte *src)
+{
+    return (byte *) _mesa_strdup ((const char *) src);
+}
+
+unsigned int grammar_string_length (const byte *str)
+{
+    return _mesa_strlen ((const char *) str);
+}
+
diff --git a/src/mesa/shader/grammar_mesa.h b/src/mesa/shader/grammar_mesa.h
index 77a8804..c14033a 100644
--- a/src/mesa/shader/grammar_mesa.h
+++ b/src/mesa/shader/grammar_mesa.h
@@ -1,19 +1,43 @@
-#ifndef GRAMMAR_MESA_H

-#define GRAMMAR_MESA_H

-

-

-#include "imports.h"

-/* NOTE: include Mesa 3-D specific headers here */

-

-

-typedef GLuint grammar;

-typedef GLubyte byte;

-

-

-#define GRAMMAR_PORT_INCLUDE 1

-#include "grammar.h"

-#undef GRAMMAR_PORT_INCLUDE

-

-

-#endif

-

+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef GRAMMAR_MESA_H
+#define GRAMMAR_MESA_H
+
+
+#include "imports.h"
+/* NOTE: include Mesa 3-D specific headers here */
+
+
+typedef GLuint grammar;
+typedef GLubyte byte;
+
+
+#define GRAMMAR_PORT_INCLUDE 1
+#include "grammar.h"
+#undef GRAMMAR_PORT_INCLUDE
+
+
+#endif
+
diff --git a/src/mesa/shader/grammar_syn.h b/src/mesa/shader/grammar_syn.h
index 766196a..9c3419e 100644
--- a/src/mesa/shader/grammar_syn.h
+++ b/src/mesa/shader/grammar_syn.h
@@ -1,196 +1,226 @@
-".syntax grammar;\n"

-".emtcode DECLARATION_END 0x00\n"

-".emtcode DECLARATION_EMITCODE 0x01\n"

-".emtcode DECLARATION_ERRORTEXT 0x02\n"

-".emtcode DECLARATION_REGBYTE 0x03\n"

-".emtcode DECLARATION_LEXER 0x04\n"

-".emtcode DECLARATION_RULE 0x05\n"

-".emtcode SPECIFIER_END 0x00\n"

-".emtcode SPECIFIER_AND_TAG 0x01\n"

-".emtcode SPECIFIER_OR_TAG 0x02\n"

-".emtcode SPECIFIER_CHARACTER_RANGE 0x03\n"

-".emtcode SPECIFIER_CHARACTER 0x04\n"

-".emtcode SPECIFIER_STRING 0x05\n"

-".emtcode SPECIFIER_IDENTIFIER 0x06\n"

-".emtcode SPECIFIER_TRUE 0x07\n"

-".emtcode SPECIFIER_FALSE 0x08\n"

-".emtcode SPECIFIER_DEBUG 0x09\n"

-".emtcode IDENTIFIER_NO_LOOP 0x00\n"

-".emtcode IDENTIFIER_LOOP 0x01\n"

-".emtcode ERROR_NOT_PRESENT 0x00\n"

-".emtcode ERROR_PRESENT 0x01\n"

-".emtcode EMIT_NULL 0x00\n"

-".emtcode EMIT_INTEGER 0x01\n"

-".emtcode EMIT_IDENTIFIER 0x02\n"

-".emtcode EMIT_CHARACTER 0x03\n"

-".emtcode EMIT_LAST_CHARACTER 0x04\n"

-".emtcode EMIT_CURRENT_POSITION 0x05\n"

-".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n"

-".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n"

-".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n"

-".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n"

-".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n"

-".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n"

-"grammar\n"

-" grammar_1 .error INVALID_GRAMMAR;\n"

-"grammar_1\n"

-" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n"

-" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n"

-"optional_space\n"

-" space .or .true;\n"

-"space\n"

-" single_space .and .loop single_space;\n"

-"single_space\n"

-" white_char .or comment_block;\n"

-"white_char\n"

-" ' ' .or '\\t' .or '\\n' .or '\\r';\n"

-"comment_block\n"

-" '/' .and '*' .and .loop comment_char .and '*' .and '/';\n"

-"comment_char\n"

-" comment_char_no_star .or comment_char_1;\n"

-"comment_char_1\n"

-" '*' .and comment_char_no_slash;\n"

-"comment_char_no_star\n"

-" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"

-"comment_char_no_slash\n"

-" '\\x30'-'\\xFF' .or '\\x01'-'\\x2E';\n"

-"identifier\n"

-" identifier_ne .error IDENTIFIER_EXPECTED;\n"

-"identifier_ne\n"

-" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n"

-"first_idchar\n"

-" 'a'-'z' .or 'A'-'Z' .or '_';\n"

-"follow_idchar\n"

-" first_idchar .or digit_dec;\n"

-"digit_dec\n"

-" '0'-'9';\n"

-"semicolon\n"

-" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"

-"declaration_list\n"

-" declaration .and .loop declaration;\n"

-"declaration\n"

-" emitcode_definition .emit DECLARATION_EMITCODE .or\n"

-" errortext_definition .emit DECLARATION_ERRORTEXT .or\n"

-" regbyte_definition .emit DECLARATION_REGBYTE .or\n"

-" lexer_definition .emit DECLARATION_LEXER .or\n"

-" rule_definition .emit DECLARATION_RULE;\n"

-"emitcode_definition\n"

-" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n"

-"integer\n"

-" integer_ne .error INTEGER_EXPECTED;\n"

-"integer_ne\n"

-" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n"

-"hex_prefix\n"

-" '0' .and hex_prefix_1;\n"

-"hex_prefix_1\n"

-" 'x' .or 'X';\n"

-"digit_hex\n"

-" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n"

-"space_or_null\n"

-" space .or '\\0';\n"

-"errortext_definition\n"

-" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n"

-"string\n"

-" string_ne .error STRING_EXPECTED;\n"

-"string_ne\n"

-" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n"

-"string_char_double_quotes\n"

-" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n"

-"string_char\n"

-" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n"

-" '\\x01'-'\\x09';\n"

-"escape_sequence\n"

-" '\\\\' .emit * .and escape_code;\n"

-"escape_code\n"

-" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n"

-"simple_escape_code\n"

-" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n"

-"hex_escape_code\n"

-" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n"

-"oct_escape_code\n"

-" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n"

-"digit_oct\n"

-" '0'-'7';\n"

-"optional_digit_oct\n"

-" digit_oct .emit * .or .true;\n"

-"regbyte_definition\n"

-" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n"

-"lexer_definition\n"

-" \".string\" .and space .and identifier .and semicolon;\n"

-"rule_definition\n"

-" identifier_ne .and space .and definition;\n"

-"definition\n"

-" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n"

-"optional_specifiers_and_or\n"

-" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n"

-"specifier\n"

-" specifier_condition .and optional_space .and specifier_rule;\n"

-"specifier_condition\n"

-" specifier_condition_1 .or .true;\n"

-"specifier_condition_1\n"

-" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n"

-" right_operand .and optional_space .and ')';\n"

-"left_operand\n"

-" identifier;\n"

-"operator\n"

-" operator_1 .or operator_2;\n"

-"operator_1\n"

-" optional_space .and '!' .and '=' .and optional_space;\n"

-"operator_2\n"

-" optional_space .and '=' .and '=' .and optional_space;\n"

-"right_operand\n"

-" integer;\n"

-"specifier_rule\n"

-" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n"

-"specifier_rule_1\n"

-" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n"

-" character .emit SPECIFIER_CHARACTER .or\n"

-" string_ne .emit SPECIFIER_STRING .or\n"

-" \".true\" .emit SPECIFIER_TRUE .or\n"

-" \".false\" .emit SPECIFIER_FALSE .or\n"

-" \".debug\" .emit SPECIFIER_DEBUG .or\n"

-" loop_identifier .emit SPECIFIER_IDENTIFIER;\n"

-"character\n"

-" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n"

-"string_char_single_quotes\n"

-" escape_sequence .or string_char .emit * .or '\"' .emit *;\n"

-"character_range\n"

-" character .and optional_space .and '-' .and optional_space .and character;\n"

-"loop_identifier\n"

-" optional_loop .and identifier;\n"

-"optional_loop\n"

-" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_NO_LOOP;\n"

-"optional_loop_1\n"

-" \".loop\" .and space;\n"

-"optional_error\n"

-" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n"

-"error\n"

-" space .and \".error\" .and space .and identifier;\n"

-"emit\n"

-" emit_output .or emit_regbyte;\n"

-"emit_output\n"

-" space .and \".emit\" .and space .and emit_param;\n"

-"emit_param\n"

-" integer_ne .emit EMIT_INTEGER .or\n"

-" identifier_ne .emit EMIT_IDENTIFIER .or\n"

-" character .emit EMIT_CHARACTER .or\n"

-" '*' .emit EMIT_LAST_CHARACTER .or\n"

-" '$' .emit EMIT_CURRENT_POSITION;\n"

-"emit_regbyte\n"

-" space .and \".load\" .and space .and identifier .and space .and emit_param;\n"

-"and_specifiers\n"

-" and_specifier .and .loop and_specifier;\n"

-"or_specifiers\n"

-" or_specifier .and .loop or_specifier;\n"

-"and_specifier\n"

-" space .and \".and\" .and space .and specifier;\n"

-"or_specifier\n"

-" space .and \".or\" .and space .and specifier;\n"

-".string __string_filter;\n"

-"__string_filter\n"

-" __first_identifier_char .and .loop __next_identifier_char;\n"

-"__first_identifier_char\n"

-" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n"

-"__next_identifier_char\n"

-" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"

-""
\ No newline at end of file
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.1
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file grammar_syn.h
+ * syntax parsing engine language syntax
+ * \author Michal Krol
+ */
+
+".syntax grammar;\n"
+".emtcode DECLARATION_END 0x00\n"
+".emtcode DECLARATION_EMITCODE 0x01\n"
+".emtcode DECLARATION_ERRORTEXT 0x02\n"
+".emtcode DECLARATION_REGBYTE 0x03\n"
+".emtcode DECLARATION_LEXER 0x04\n"
+".emtcode DECLARATION_RULE 0x05\n"
+".emtcode SPECIFIER_END 0x00\n"
+".emtcode SPECIFIER_AND_TAG 0x01\n"
+".emtcode SPECIFIER_OR_TAG 0x02\n"
+".emtcode SPECIFIER_CHARACTER_RANGE 0x03\n"
+".emtcode SPECIFIER_CHARACTER 0x04\n"
+".emtcode SPECIFIER_STRING 0x05\n"
+".emtcode SPECIFIER_IDENTIFIER 0x06\n"
+".emtcode SPECIFIER_TRUE 0x07\n"
+".emtcode SPECIFIER_FALSE 0x08\n"
+".emtcode SPECIFIER_DEBUG 0x09\n"
+".emtcode IDENTIFIER_NO_LOOP 0x00\n"
+".emtcode IDENTIFIER_LOOP 0x01\n"
+".emtcode ERROR_NOT_PRESENT 0x00\n"
+".emtcode ERROR_PRESENT 0x01\n"
+".emtcode EMIT_NULL 0x00\n"
+".emtcode EMIT_INTEGER 0x01\n"
+".emtcode EMIT_IDENTIFIER 0x02\n"
+".emtcode EMIT_CHARACTER 0x03\n"
+".emtcode EMIT_LAST_CHARACTER 0x04\n"
+".emtcode EMIT_CURRENT_POSITION 0x05\n"
+".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n"
+".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n"
+".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n"
+".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n"
+".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n"
+".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n"
+"grammar\n"
+" grammar_1 .error INVALID_GRAMMAR;\n"
+"grammar_1\n"
+" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n"
+" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n"
+"optional_space\n"
+" space .or .true;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" white_char .or comment_block;\n"
+"white_char\n"
+" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
+"comment_block\n"
+" '/' .and '*' .and .loop comment_char .and '*' .and '/';\n"
+"comment_char\n"
+" comment_char_no_star .or comment_char_1;\n"
+"comment_char_1\n"
+" '*' .and comment_char_no_slash;\n"
+"comment_char_no_star\n"
+" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
+"comment_char_no_slash\n"
+" '\\x30'-'\\xFF' .or '\\x01'-'\\x2E';\n"
+"identifier\n"
+" identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"identifier_ne\n"
+" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n"
+"first_idchar\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"follow_idchar\n"
+" first_idchar .or digit_dec;\n"
+"digit_dec\n"
+" '0'-'9';\n"
+"semicolon\n"
+" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
+"declaration_list\n"
+" declaration .and .loop declaration;\n"
+"declaration\n"
+" emitcode_definition .emit DECLARATION_EMITCODE .or\n"
+" errortext_definition .emit DECLARATION_ERRORTEXT .or\n"
+" regbyte_definition .emit DECLARATION_REGBYTE .or\n"
+" lexer_definition .emit DECLARATION_LEXER .or\n"
+" rule_definition .emit DECLARATION_RULE;\n"
+"emitcode_definition\n"
+" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n"
+"integer\n"
+" integer_ne .error INTEGER_EXPECTED;\n"
+"integer_ne\n"
+" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n"
+"hex_prefix\n"
+" '0' .and hex_prefix_1;\n"
+"hex_prefix_1\n"
+" 'x' .or 'X';\n"
+"digit_hex\n"
+" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n"
+"space_or_null\n"
+" space .or '\\0';\n"
+"errortext_definition\n"
+" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n"
+"string\n"
+" string_ne .error STRING_EXPECTED;\n"
+"string_ne\n"
+" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n"
+"string_char_double_quotes\n"
+" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n"
+"string_char\n"
+" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n"
+" '\\x01'-'\\x09';\n"
+"escape_sequence\n"
+" '\\\\' .emit * .and escape_code;\n"
+"escape_code\n"
+" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n"
+"simple_escape_code\n"
+" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n"
+"hex_escape_code\n"
+" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n"
+"oct_escape_code\n"
+" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n"
+"digit_oct\n"
+" '0'-'7';\n"
+"optional_digit_oct\n"
+" digit_oct .emit * .or .true;\n"
+"regbyte_definition\n"
+" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n"
+"lexer_definition\n"
+" \".string\" .and space .and identifier .and semicolon;\n"
+"rule_definition\n"
+" identifier_ne .and space .and definition;\n"
+"definition\n"
+" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n"
+"optional_specifiers_and_or\n"
+" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n"
+"specifier\n"
+" specifier_condition .and optional_space .and specifier_rule;\n"
+"specifier_condition\n"
+" specifier_condition_1 .or .true;\n"
+"specifier_condition_1\n"
+" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n"
+" right_operand .and optional_space .and ')';\n"
+"left_operand\n"
+" identifier;\n"
+"operator\n"
+" operator_1 .or operator_2;\n"
+"operator_1\n"
+" optional_space .and '!' .and '=' .and optional_space;\n"
+"operator_2\n"
+" optional_space .and '=' .and '=' .and optional_space;\n"
+"right_operand\n"
+" integer;\n"
+"specifier_rule\n"
+" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n"
+"specifier_rule_1\n"
+" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n"
+" character .emit SPECIFIER_CHARACTER .or\n"
+" string_ne .emit SPECIFIER_STRING .or\n"
+" \".true\" .emit SPECIFIER_TRUE .or\n"
+" \".false\" .emit SPECIFIER_FALSE .or\n"
+" \".debug\" .emit SPECIFIER_DEBUG .or\n"
+" loop_identifier .emit SPECIFIER_IDENTIFIER;\n"
+"character\n"
+" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n"
+"string_char_single_quotes\n"
+" escape_sequence .or string_char .emit * .or '\"' .emit *;\n"
+"character_range\n"
+" character .and optional_space .and '-' .and optional_space .and character;\n"
+"loop_identifier\n"
+" optional_loop .and identifier;\n"
+"optional_loop\n"
+" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_NO_LOOP;\n"
+"optional_loop_1\n"
+" \".loop\" .and space;\n"
+"optional_error\n"
+" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n"
+"error\n"
+" space .and \".error\" .and space .and identifier;\n"
+"emit\n"
+" emit_output .or emit_regbyte;\n"
+"emit_output\n"
+" space .and \".emit\" .and space .and emit_param;\n"
+"emit_param\n"
+" integer_ne .emit EMIT_INTEGER .or\n"
+" identifier_ne .emit EMIT_IDENTIFIER .or\n"
+" character .emit EMIT_CHARACTER .or\n"
+" '*' .emit EMIT_LAST_CHARACTER .or\n"
+" '$' .emit EMIT_CURRENT_POSITION;\n"
+"emit_regbyte\n"
+" space .and \".load\" .and space .and identifier .and space .and emit_param;\n"
+"and_specifiers\n"
+" and_specifier .and .loop and_specifier;\n"
+"or_specifiers\n"
+" or_specifier .and .loop or_specifier;\n"
+"and_specifier\n"
+" space .and \".and\" .and space .and specifier;\n"
+"or_specifier\n"
+" space .and \".or\" .and space .and specifier;\n"
+".string __string_filter;\n"
+"__string_filter\n"
+" __first_identifier_char .and .loop __next_identifier_char;\n"
+"__first_identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n"
+"__next_identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
+""