aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/shader/slang/library/slang_shader.syn
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/shader/slang/library/slang_shader.syn')
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_shader.syn1716
1 files changed, 1716 insertions, 0 deletions
diff --git a/mesalib/src/mesa/shader/slang/library/slang_shader.syn b/mesalib/src/mesa/shader/slang/library/slang_shader.syn
new file mode 100644
index 000000000..cc5c70a02
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_shader.syn
@@ -0,0 +1,1716 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2004-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. 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 slang_shader.syn
+ * slang vertex/fragment shader syntax
+ * \author Michal Krol
+ */
+
+/*
+ * usage:
+ * syn2c slang_shader.syn > slang_shader_syn.h
+ *
+ * when modifying or extending this file, several things must be taken into
+ * consideration:
+ *
+ * - when adding new operators that were marked as reserved in the
+ * initial specification, one must only uncomment particular lines of
+ * code that refer to operators being added;
+ *
+ * - when adding new shader targets, one must reserve a new value for
+ * shader_type register and use it in .if constructs for symbols that
+ * are exclusive for that shader;
+ *
+ * - some symbols mimic output of other symbols - the best example is
+ * the "for" construct: expression "for (foo(); ; bar())" is seen as
+ * "for (foo(); true; bar())" by the output processor - hence, special
+ * care must be taken when rearranging output of essential symbols;
+ *
+ * - order of single-quoted tokens does matter in alternatives - so do not
+ * parse "<" operator before "<<" and "<<" before "<<=";
+ *
+ * - all double-quoted tokens are internally preprocessed to eliminate
+ * problems with parsing strings that are prefixes of other strings,
+ * like "sampler1D" and "sampler1DShadow";
+ */
+
+.syntax translation_unit;
+
+/* revision number - increment after each change affecting emitted output */
+.emtcode REVISION 5
+
+/* external declaration (or precision or invariant stmt) */
+.emtcode EXTERNAL_NULL 0
+.emtcode EXTERNAL_FUNCTION_DEFINITION 1
+.emtcode EXTERNAL_DECLARATION 2
+.emtcode DEFAULT_PRECISION 3
+.emtcode INVARIANT_STMT 4
+
+/* precision */
+.emtcode PRECISION_DEFAULT 0
+.emtcode PRECISION_LOW 1
+.emtcode PRECISION_MEDIUM 2
+.emtcode PRECISION_HIGH 3
+
+/* declaration */
+.emtcode DECLARATION_FUNCTION_PROTOTYPE 1
+.emtcode DECLARATION_INIT_DECLARATOR_LIST 2
+
+/* function type */
+.emtcode FUNCTION_ORDINARY 0
+.emtcode FUNCTION_CONSTRUCTOR 1
+.emtcode FUNCTION_OPERATOR 2
+
+/* function call type */
+.emtcode FUNCTION_CALL_NONARRAY 0
+.emtcode FUNCTION_CALL_ARRAY 1
+
+/* operator type */
+.emtcode OPERATOR_ADDASSIGN 1
+.emtcode OPERATOR_SUBASSIGN 2
+.emtcode OPERATOR_MULASSIGN 3
+.emtcode OPERATOR_DIVASSIGN 4
+/*.emtcode OPERATOR_MODASSIGN 5*/
+/*.emtcode OPERATOR_LSHASSIGN 6*/
+/*.emtcode OPERATOR_RSHASSIGN 7*/
+/*.emtcode OPERATOR_ORASSIGN 8*/
+/*.emtcode OPERATOR_XORASSIGN 9*/
+/*.emtcode OPERATOR_ANDASSIGN 10*/
+.emtcode OPERATOR_LOGICALXOR 11
+/*.emtcode OPERATOR_BITOR 12*/
+/*.emtcode OPERATOR_BITXOR 13*/
+/*.emtcode OPERATOR_BITAND 14*/
+.emtcode OPERATOR_LESS 15
+.emtcode OPERATOR_GREATER 16
+.emtcode OPERATOR_LESSEQUAL 17
+.emtcode OPERATOR_GREATEREQUAL 18
+/*.emtcode OPERATOR_LSHIFT 19*/
+/*.emtcode OPERATOR_RSHIFT 20*/
+.emtcode OPERATOR_MULTIPLY 21
+.emtcode OPERATOR_DIVIDE 22
+/*.emtcode OPERATOR_MODULUS 23*/
+.emtcode OPERATOR_INCREMENT 24
+.emtcode OPERATOR_DECREMENT 25
+.emtcode OPERATOR_PLUS 26
+.emtcode OPERATOR_MINUS 27
+/*.emtcode OPERATOR_COMPLEMENT 28*/
+.emtcode OPERATOR_NOT 29
+
+/* init declarator list */
+.emtcode DECLARATOR_NONE 0
+.emtcode DECLARATOR_NEXT 1
+
+/* variable declaration */
+.emtcode VARIABLE_NONE 0
+.emtcode VARIABLE_IDENTIFIER 1
+.emtcode VARIABLE_INITIALIZER 2
+.emtcode VARIABLE_ARRAY_EXPLICIT 3
+.emtcode VARIABLE_ARRAY_UNKNOWN 4
+
+/* type qualifier */
+.emtcode TYPE_QUALIFIER_NONE 0
+.emtcode TYPE_QUALIFIER_CONST 1
+.emtcode TYPE_QUALIFIER_ATTRIBUTE 2
+.emtcode TYPE_QUALIFIER_VARYING 3
+.emtcode TYPE_QUALIFIER_UNIFORM 4
+.emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5
+.emtcode TYPE_QUALIFIER_FIXEDINPUT 6
+
+/* invariant qualifier */
+.emtcode TYPE_VARIANT 90
+.emtcode TYPE_INVARIANT 91
+
+/* centroid qualifier */
+.emtcode TYPE_CENTER 95
+.emtcode TYPE_CENTROID 96
+
+/* type specifier */
+.emtcode TYPE_SPECIFIER_VOID 0
+.emtcode TYPE_SPECIFIER_BOOL 1
+.emtcode TYPE_SPECIFIER_BVEC2 2
+.emtcode TYPE_SPECIFIER_BVEC3 3
+.emtcode TYPE_SPECIFIER_BVEC4 4
+.emtcode TYPE_SPECIFIER_INT 5
+.emtcode TYPE_SPECIFIER_IVEC2 6
+.emtcode TYPE_SPECIFIER_IVEC3 7
+.emtcode TYPE_SPECIFIER_IVEC4 8
+.emtcode TYPE_SPECIFIER_FLOAT 9
+.emtcode TYPE_SPECIFIER_VEC2 10
+.emtcode TYPE_SPECIFIER_VEC3 11
+.emtcode TYPE_SPECIFIER_VEC4 12
+.emtcode TYPE_SPECIFIER_MAT2 13
+.emtcode TYPE_SPECIFIER_MAT3 14
+.emtcode TYPE_SPECIFIER_MAT4 15
+.emtcode TYPE_SPECIFIER_SAMPLER1D 16
+.emtcode TYPE_SPECIFIER_SAMPLER2D 17
+.emtcode TYPE_SPECIFIER_SAMPLER3D 18
+.emtcode TYPE_SPECIFIER_SAMPLERCUBE 19
+.emtcode TYPE_SPECIFIER_SAMPLER1DSHADOW 20
+.emtcode TYPE_SPECIFIER_SAMPLER2DSHADOW 21
+.emtcode TYPE_SPECIFIER_SAMPLER2DRECT 22
+.emtcode TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
+.emtcode TYPE_SPECIFIER_STRUCT 24
+.emtcode TYPE_SPECIFIER_TYPENAME 25
+
+/* OpenGL 2.1 */
+.emtcode TYPE_SPECIFIER_MAT23 26
+.emtcode TYPE_SPECIFIER_MAT32 27
+.emtcode TYPE_SPECIFIER_MAT24 28
+.emtcode TYPE_SPECIFIER_MAT42 29
+.emtcode TYPE_SPECIFIER_MAT34 30
+.emtcode TYPE_SPECIFIER_MAT43 31
+
+/* type specifier array */
+.emtcode TYPE_SPECIFIER_NONARRAY 0
+.emtcode TYPE_SPECIFIER_ARRAY 1
+
+/* structure field */
+.emtcode FIELD_NONE 0
+.emtcode FIELD_NEXT 1
+.emtcode FIELD_ARRAY 2
+
+/* operation */
+.emtcode OP_END 0
+.emtcode OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
+.emtcode OP_BLOCK_BEGIN_NEW_SCOPE 2
+.emtcode OP_DECLARE 3
+.emtcode OP_ASM 4
+.emtcode OP_BREAK 5
+.emtcode OP_CONTINUE 6
+.emtcode OP_DISCARD 7
+.emtcode OP_RETURN 8
+.emtcode OP_EXPRESSION 9
+.emtcode OP_IF 10
+.emtcode OP_WHILE 11
+.emtcode OP_DO 12
+.emtcode OP_FOR 13
+.emtcode OP_PUSH_VOID 14
+.emtcode OP_PUSH_BOOL 15
+.emtcode OP_PUSH_INT 16
+.emtcode OP_PUSH_FLOAT 17
+.emtcode OP_PUSH_IDENTIFIER 18
+.emtcode OP_SEQUENCE 19
+.emtcode OP_ASSIGN 20
+.emtcode OP_ADDASSIGN 21
+.emtcode OP_SUBASSIGN 22
+.emtcode OP_MULASSIGN 23
+.emtcode OP_DIVASSIGN 24
+/*.emtcode OP_MODASSIGN 25*/
+/*.emtcode OP_LSHASSIGN 26*/
+/*.emtcode OP_RSHASSIGN 27*/
+/*.emtcode OP_ORASSIGN 28*/
+/*.emtcode OP_XORASSIGN 29*/
+/*.emtcode OP_ANDASSIGN 30*/
+.emtcode OP_SELECT 31
+.emtcode OP_LOGICALOR 32
+.emtcode OP_LOGICALXOR 33
+.emtcode OP_LOGICALAND 34
+/*.emtcode OP_BITOR 35*/
+/*.emtcode OP_BITXOR 36*/
+/*.emtcode OP_BITAND 37*/
+.emtcode OP_EQUAL 38
+.emtcode OP_NOTEQUAL 39
+.emtcode OP_LESS 40
+.emtcode OP_GREATER 41
+.emtcode OP_LESSEQUAL 42
+.emtcode OP_GREATEREQUAL 43
+/*.emtcode OP_LSHIFT 44*/
+/*.emtcode OP_RSHIFT 45*/
+.emtcode OP_ADD 46
+.emtcode OP_SUBTRACT 47
+.emtcode OP_MULTIPLY 48
+.emtcode OP_DIVIDE 49
+/*.emtcode OP_MODULUS 50*/
+.emtcode OP_PREINCREMENT 51
+.emtcode OP_PREDECREMENT 52
+.emtcode OP_PLUS 53
+.emtcode OP_MINUS 54
+/*.emtcode OP_COMPLEMENT 55*/
+.emtcode OP_NOT 56
+.emtcode OP_SUBSCRIPT 57
+.emtcode OP_CALL 58
+.emtcode OP_FIELD 59
+.emtcode OP_POSTINCREMENT 60
+.emtcode OP_POSTDECREMENT 61
+.emtcode OP_PRECISION 62
+.emtcode OP_METHOD 63
+
+/* parameter qualifier */
+.emtcode PARAM_QUALIFIER_IN 0
+.emtcode PARAM_QUALIFIER_OUT 1
+.emtcode PARAM_QUALIFIER_INOUT 2
+
+/* function parameter */
+.emtcode PARAMETER_NONE 0
+.emtcode PARAMETER_NEXT 1
+
+/* function parameter array presence */
+.emtcode PARAMETER_ARRAY_NOT_PRESENT 0
+.emtcode PARAMETER_ARRAY_PRESENT 1
+
+/* INVALID_EXTERNAL_DECLARATION seems to be reported when there's */
+/* any syntax errors... */
+.errtext INVALID_EXTERNAL_DECLARATION "2001: Syntax error."
+.errtext INVALID_OPERATOR_OVERRIDE "2002: Invalid operator override."
+.errtext LBRACE_EXPECTED "2003: '{' expected but '$err_token$' found."
+.errtext LPAREN_EXPECTED "2004: '(' expected but '$err_token$' found."
+.errtext RPAREN_EXPECTED "2005: ')' expected but '$err_token$' found."
+.errtext INVALID_PRECISION "2006: Invalid precision specifier '$err_token$'."
+.errtext INVALID_PRECISION_TYPE "2007: Invalid precision type '$err_token$'."
+
+
+/*
+ * tells whether the shader that is being parsed is a built-in shader or not
+ * 0 - normal behaviour
+ * 1 - accepts constructor and operator definitions and __asm statements
+ * the implementation will set it to 1 when compiling internal built-in shaders
+ */
+.regbyte parsing_builtin 0
+
+/*
+ * holds the type of the shader being parsed; possible values are
+ * listed below.
+ * FRAGMENT_SHADER 1
+ * VERTEX_SHADER 2
+ * shader type is set by the caller before parsing
+ */
+.regbyte shader_type 0
+
+/*
+ * <variable_identifier> ::= <identifier>
+ */
+variable_identifier
+ identifier .emit OP_PUSH_IDENTIFIER;
+
+/*
+ * <primary_expression> ::= <variable_identifier>
+ * | <intconstant>
+ * | <floatconstant>
+ * | <boolconstant>
+ * | "(" <expression> ")"
+ */
+primary_expression
+ floatconstant .or boolconstant .or intconstant .or variable_identifier .or primary_expression_1;
+primary_expression_1
+ lparen .and expression .and rparen;
+
+/*
+ * <postfix_expression> ::= <primary_expression>
+ * | <postfix_expression> "[" <integer_expression> "]"
+ * | <function_call>
+ * | <postfix_expression> "." <field_selection>
+ * | <postfix_expression> "++"
+ * | <postfix_expression> "--"
+ */
+postfix_expression
+ postfix_expression_1 .and .loop postfix_expression_2;
+postfix_expression_1
+ function_call .or primary_expression;
+postfix_expression_2
+ postfix_expression_3 .or postfix_expression_4 .or
+ plusplus .emit OP_POSTINCREMENT .or
+ minusminus .emit OP_POSTDECREMENT;
+postfix_expression_3
+ lbracket .and integer_expression .and rbracket .emit OP_SUBSCRIPT;
+postfix_expression_4
+ dot .and field_selection .emit OP_FIELD;
+
+/*
+ * <integer_expression> ::= <expression>
+ */
+integer_expression
+ expression;
+
+/*
+ * <function_call> ::= <function_call_generic>
+ */
+function_call
+ function_call_or_method;
+
+/*
+ * <function_call_or_method> ::= <regular_function_call>
+ * | <postfix_expression> "." <function_call_generic>
+ */
+function_call_or_method
+ regular_function_call .or method_call;
+
+/*
+ * <method_call> ::= <identifier> "." <function_call_generic>
+ */
+method_call
+ identifier .emit OP_METHOD .and dot .and function_call_generic .and .true .emit OP_END;
+
+/*
+ * <regular_function_call> ::= <function_call_generic>
+ */
+regular_function_call
+ function_call_generic .emit OP_CALL .and .true .emit OP_END;
+
+/*
+ * <function_call_generic> ::= <function_call_header_with_parameters> ")"
+ * | <function_call_header_no_parameters> ")"
+ */
+function_call_generic
+ function_call_generic_1 .or function_call_generic_2;
+function_call_generic_1
+ function_call_header_with_parameters .and rparen .error RPAREN_EXPECTED;
+function_call_generic_2
+ function_call_header_no_parameters .and rparen .error RPAREN_EXPECTED;
+
+/*
+ * <function_call_header_no_parameters>::= <function_call_header> "void"
+ * | <function_call_header>
+ */
+function_call_header_no_parameters
+ function_call_header .and function_call_header_no_parameters_1;
+function_call_header_no_parameters_1
+ "void" .or .true;
+
+/*
+ * <function_call_header_with_parameters> ::= <function_call_header> <assignment_expression>
+ * | <function_call_header_with_parameters> "," <assignment_expression>
+ */
+function_call_header_with_parameters
+ function_call_header .and assignment_expression .and .true .emit OP_END .and
+ .loop function_call_header_with_parameters_1;
+function_call_header_with_parameters_1
+ comma .and assignment_expression .and .true .emit OP_END;
+
+/*
+ * <function_call_header> ::= <function_identifier> "("
+ */
+function_call_header
+ function_identifier .and lparen;
+
+/*
+ * <function_identifier> ::= <constructor_identifier>
+ * | <identifier>
+ * | <type_specifier>
+ *
+ * note: <constructor_identifier> and <type_specifier> have been deleted
+ */
+function_identifier
+ identifier .and function_identifier_opt_array;
+function_identifier_opt_array
+ function_identifier_array .emit FUNCTION_CALL_ARRAY .or
+ .true .emit FUNCTION_CALL_NONARRAY;
+function_identifier_array
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <unary_expression> ::= <postfix_expression>
+ * | "++" <unary_expression>
+ * | "--" <unary_expression>
+ * | <unary_operator> <unary_expression>
+ *
+ * <unary_operator> ::= "+"
+ * | "-"
+ * | "!"
+ * | "~" // reserved
+ */
+unary_expression
+ postfix_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or
+ unary_expression_4 .or unary_expression_5/* .or unary_expression_6*/;
+unary_expression_1
+ plusplus .and unary_expression .and .true .emit OP_PREINCREMENT;
+unary_expression_2
+ minusminus .and unary_expression .and .true .emit OP_PREDECREMENT;
+unary_expression_3
+ plus .and unary_expression .and .true .emit OP_PLUS;
+unary_expression_4
+ minus .and unary_expression .and .true .emit OP_MINUS;
+unary_expression_5
+ bang .and unary_expression .and .true .emit OP_NOT;
+/*unary_expression_6
+ tilde .and unary_expression .and .true .emit OP_COMPLEMENT;*/
+
+/*
+ * <multiplicative_expression> ::= <unary_expression>
+ * | <multiplicative_expression> "*" <unary_expression>
+ * | <multiplicative_expression> "/" <unary_expression>
+ * | <multiplicative_expression> "%" <unary_expression> // reserved
+ */
+multiplicative_expression
+ unary_expression .and .loop multiplicative_expression_1;
+multiplicative_expression_1
+ multiplicative_expression_2 .or multiplicative_expression_3/* .or multiplicative_expression_4*/;
+multiplicative_expression_2
+ star .and unary_expression .and .true .emit OP_MULTIPLY;
+multiplicative_expression_3
+ slash .and unary_expression .and .true .emit OP_DIVIDE;
+/*multiplicative_expression_4
+ percent .and unary_expression .and .true .emit OP_MODULUS;*/
+
+/*
+ * <additive_expression> ::= <multiplicative_expression>
+ * | <additive_expression> "+" <multiplicative_expression>
+ * | <additive_expression> "-" <multiplicative_expression>
+ */
+additive_expression
+ multiplicative_expression .and .loop additive_expression_1;
+additive_expression_1
+ additive_expression_2 .or additive_expression_3;
+additive_expression_2
+ plus .and multiplicative_expression .and .true .emit OP_ADD;
+additive_expression_3
+ minus .and multiplicative_expression .and .true .emit OP_SUBTRACT;
+
+/*
+ * <shift_expression> ::= <additive_expression>
+ * | <shift_expression> "<<" <additive_expression> // reserved
+ * | <shift_expression> ">>" <additive_expression> // reserved
+ */
+shift_expression
+ additive_expression/* .and .loop shift_expression_1*/;
+/*shift_expression_1
+ shift_expression_2 .or shift_expression_3;*/
+/*shift_expression_2
+ lessless .and additive_expression .and .true .emit OP_LSHIFT;*/
+/*shift_expression_3
+ greatergreater .and additive_expression .and .true .emit OP_RSHIFT;*/
+
+/*
+ * <relational_expression> ::= <shift_expression>
+ * | <relational_expression> "<" <shift_expression>
+ * | <relational_expression> ">" <shift_expression>
+ * | <relational_expression> "<=" <shift_expression>
+ * | <relational_expression> ">=" <shift_expression>
+ */
+relational_expression
+ shift_expression .and .loop relational_expression_1;
+relational_expression_1
+ relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or
+ relational_expression_5;
+relational_expression_2
+ lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;
+relational_expression_3
+ greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;
+relational_expression_4
+ less .and shift_expression .and .true .emit OP_LESS;
+relational_expression_5
+ greater .and shift_expression .and .true .emit OP_GREATER;
+
+/*
+ * <equality_expression> ::= <relational_expression>
+ * | <equality_expression> "==" <relational_expression>
+ * | <equality_expression> "!=" <relational_expression>
+ */
+equality_expression
+ relational_expression .and .loop equality_expression_1;
+equality_expression_1
+ equality_expression_2 .or equality_expression_3;
+equality_expression_2
+ equalsequals .and relational_expression .and .true .emit OP_EQUAL;
+equality_expression_3
+ bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;
+
+/*
+ * <and_expression> ::= <equality_expression>
+ * | <and_expression> "&" <equality_expression> // reserved
+ */
+and_expression
+ equality_expression/* .and .loop and_expression_1*/;
+/*and_expression_1
+ ampersand .and equality_expression .and .true .emit OP_BITAND;*/
+
+/*
+ * <exclusive_or_expression> ::= <and_expression>
+ * | <exclusive_or_expression> "^" <and_expression> // reserved
+ */
+exclusive_or_expression
+ and_expression/* .and .loop exclusive_or_expression_1*/;
+/*exclusive_or_expression_1
+ caret .and and_expression .and .true .emit OP_BITXOR;*/
+
+/*
+ * <inclusive_or_expression> ::= <exclusive_or_expression>
+ * | <inclusive_or_expression> "|" <exclusive_or_expression> // reserved
+ */
+inclusive_or_expression
+ exclusive_or_expression/* .and .loop inclusive_or_expression_1*/;
+/*inclusive_or_expression_1
+ bar .and exclusive_or_expression .and .true .emit OP_BITOR;*/
+
+/*
+ * <logical_and_expression> ::= <inclusive_or_expression>
+ * | <logical_and_expression> "&&" <inclusive_or_expression>
+ */
+logical_and_expression
+ inclusive_or_expression .and .loop logical_and_expression_1;
+logical_and_expression_1
+ ampersandampersand .and inclusive_or_expression .and .true .emit OP_LOGICALAND;
+
+/*
+ * <logical_xor_expression> ::= <logical_and_expression>
+ * | <logical_xor_expression> "^^" <logical_and_expression>
+ */
+logical_xor_expression
+ logical_and_expression .and .loop logical_xor_expression_1;
+logical_xor_expression_1
+ caretcaret .and logical_and_expression .and .true .emit OP_LOGICALXOR;
+
+/*
+ * <logical_or_expression> ::= <logical_xor_expression>
+ * | <logical_or_expression> "||" <logical_xor_expression>
+ */
+logical_or_expression
+ logical_xor_expression .and .loop logical_or_expression_1;
+logical_or_expression_1
+ barbar .and logical_xor_expression .and .true .emit OP_LOGICALOR;
+
+/*
+ * <conditional_expression> ::= <logical_or_expression>
+ * | <logical_or_expression> "?" <expression> ":" <conditional_expression>
+ */
+conditional_expression
+ logical_or_expression .and .loop conditional_expression_1;
+conditional_expression_1
+ question .and expression .and colon .and conditional_expression .and .true .emit OP_SELECT;
+
+/*
+ * <assignment_expression> ::= <conditional_expression>
+ * | <unary_expression> <assignment_operator> <assignment_expression>
+ *
+ * <assignment_operator> ::= "="
+ * | "*="
+ * | "/="
+ * | "+="
+ * | "-="
+ * | "%=" // reserved
+ * | "<<=" // reserved
+ * | ">>=" // reserved
+ * | "&=" // reserved
+ * | "^=" // reserved
+ * | "|=" // reserved
+ */
+assignment_expression
+ assignment_expression_1 .or assignment_expression_2 .or assignment_expression_3 .or
+ assignment_expression_4 .or assignment_expression_5/* .or assignment_expression_6 .or
+ assignment_expression_7 .or assignment_expression_8 .or assignment_expression_9 .or
+ assignment_expression_10 .or assignment_expression_11*/ .or conditional_expression;
+assignment_expression_1
+ unary_expression .and equals .and assignment_expression .and .true .emit OP_ASSIGN;
+assignment_expression_2
+ unary_expression .and starequals .and assignment_expression .and .true .emit OP_MULASSIGN;
+assignment_expression_3
+ unary_expression .and slashequals .and assignment_expression .and .true .emit OP_DIVASSIGN;
+assignment_expression_4
+ unary_expression .and plusequals .and assignment_expression .and .true .emit OP_ADDASSIGN;
+assignment_expression_5
+ unary_expression .and minusequals .and assignment_expression .and .true .emit OP_SUBASSIGN;
+/*assignment_expression_6
+ unary_expression .and percentequals .and assignment_expression .and .true .emit OP_MODASSIGN;*/
+/*assignment_expression_7
+ unary_expression .and lesslessequals .and assignment_expression .and .true .emit OP_LSHASSIGN;*/
+/*assignment_expression_8
+ unary_expression .and greatergreaterequals .and assignment_expression .and
+ .true .emit OP_RSHASSIGN;*/
+/*assignment_expression_9
+ unary_expression .and ampersandequals .and assignment_expression .and .true .emit OP_ANDASSIGN;*/
+/*assignment_expression_10
+ unary_expression .and caretequals .and assignment_expression .and .true .emit OP_XORASSIGN;*/
+/*assignment_expression_11
+ unary_expression .and barequals .and assignment_expression .and .true .emit OP_ORASSIGN;*/
+
+/*
+ * <expression> ::= <assignment_expression>
+ * | <expression> "," <assignment_expression>
+ */
+expression
+ assignment_expression .and .loop expression_1;
+expression_1
+ comma .and assignment_expression .and .true .emit OP_SEQUENCE;
+
+/*
+ * <constant_expression> ::= <conditional_expression>
+ */
+constant_expression
+ conditional_expression .and .true .emit OP_END;
+
+/*
+ * <declaration> ::= <function_prototype> ";"
+ * | <init_declarator_list> ";"
+ */
+declaration
+ declaration_1 .or declaration_2;
+declaration_1
+ function_prototype .emit DECLARATION_FUNCTION_PROTOTYPE .and semicolon;
+declaration_2
+ init_declarator_list .emit DECLARATION_INIT_DECLARATOR_LIST .and semicolon;
+
+/*
+ * <function_prototype> ::= <function_header> "void" ")"
+ * | <function_declarator> ")"
+ */
+function_prototype
+ function_prototype_1 .or function_prototype_2;
+function_prototype_1
+ function_header .and "void" .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;
+function_prototype_2
+ function_declarator .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;
+
+/*
+ * <function_declarator> ::= <function_header>
+ * | <function_header_with_parameters>
+ */
+function_declarator
+ function_header_with_parameters .or function_header;
+
+/*
+ * <function_header_with_parameters> ::= <function_header> <parameter_declaration>
+ * | <function_header_with_parameters> ","
+ * <parameter_declaration>
+ */
+function_header_with_parameters
+ function_header .and parameter_declaration .and .loop function_header_with_parameters_1;
+function_header_with_parameters_1
+ comma .and parameter_declaration;
+
+/*
+ * <function_header> ::= <fully_specified_type> <identifier> "("
+ */
+function_header
+ function_header_nospace .or function_header_space;
+function_header_space
+ fully_specified_type_space .and space .and function_decl_identifier .and lparen;
+function_header_nospace
+ fully_specified_type_nospace .and function_decl_identifier .and lparen;
+
+/*
+ * <function_decl_identifier> ::= "__constructor"
+ * | <__operator>
+ * | <identifier>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows operator and constructor prototypes and definitions
+ */
+function_decl_identifier
+ .if (parsing_builtin != 0) __operator .emit FUNCTION_OPERATOR .or
+ .if (parsing_builtin != 0) "__constructor" .emit FUNCTION_CONSTRUCTOR .or
+ identifier .emit FUNCTION_ORDINARY;
+
+/*
+ * <__operator> ::= "__operator" <overriden_op>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows operator prototypes and definitions
+ */
+__operator
+ "__operator" .and overriden_operator .error INVALID_OPERATOR_OVERRIDE;
+
+/*
+ * <overriden_op> ::= "="
+ * | "+="
+ * | "-="
+ * | "*="
+ * | "/="
+ * | "%=" // reserved
+ * | "<<=" // reserved
+ * | ">>=" // reserved
+ * | "&=" // reserved
+ * | "^=" // reserved
+ * | "|=" // reserved
+ * | "^^"
+ * | "|" // reserved
+ * | "^" // reserved
+ * | "&" // reserved
+ * | "=="
+ * | "!="
+ * | "<"
+ * | ">"
+ * | "<="
+ * | ">="
+ * | "<<" // reserved
+ * | ">>" // reserved
+ * | "*"
+ * | "/"
+ * | "%" // reserved
+ * | "++"
+ * | "--"
+ * | "+"
+ * | "-"
+ * | "~" // reserved
+ * | "!"
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows operator prototypes and definitions
+ */
+overriden_operator
+ plusplus .emit OPERATOR_INCREMENT .or
+ plusequals .emit OPERATOR_ADDASSIGN .or
+ plus .emit OPERATOR_PLUS .or
+ minusminus .emit OPERATOR_DECREMENT .or
+ minusequals .emit OPERATOR_SUBASSIGN .or
+ minus .emit OPERATOR_MINUS .or
+ bang .emit OPERATOR_NOT .or
+ starequals .emit OPERATOR_MULASSIGN .or
+ star .emit OPERATOR_MULTIPLY .or
+ slashequals .emit OPERATOR_DIVASSIGN .or
+ slash .emit OPERATOR_DIVIDE .or
+ lessequals .emit OPERATOR_LESSEQUAL .or
+ /*lesslessequals .emit OPERATOR_LSHASSIGN .or*/
+ /*lessless .emit OPERATOR_LSHIFT .or*/
+ less .emit OPERATOR_LESS .or
+ greaterequals .emit OPERATOR_GREATEREQUAL .or
+ /*greatergreaterequals .emit OPERATOR_RSHASSIGN .or*/
+ /*greatergreater .emit OPERATOR_RSHIFT .or*/
+ greater .emit OPERATOR_GREATER .or
+ /*percentequals .emit OPERATOR_MODASSIGN .or*/
+ /*percent .emit OPERATOR_MODULUS .or*/
+ /*ampersandequals .emit OPERATOR_ANDASSIGN */
+ /*ampersand .emit OPERATOR_BITAND .or*/
+ /*barequals .emit OPERATOR_ORASSIGN .or*/
+ /*bar .emit OPERATOR_BITOR .or*/
+ /*tilde .emit OPERATOR_COMPLEMENT .or*/
+ /*caretequals .emit OPERATOR_XORASSIGN .or*/
+ caretcaret .emit OPERATOR_LOGICALXOR /*.or
+ caret .emit OPERATOR_BITXOR*/;
+
+/*
+ * <parameter_declarator> ::= <type_specifier> <identifier>
+ * | <type_specifier> <identifier> "[" <constant_expression> "]"
+ */
+parameter_declarator
+ parameter_declarator_nospace .or parameter_declarator_space;
+parameter_declarator_nospace
+ type_specifier_nospace .and identifier .and parameter_declarator_1;
+parameter_declarator_space
+ type_specifier_space .and space .and identifier .and parameter_declarator_1;
+parameter_declarator_1
+ parameter_declarator_2 .emit PARAMETER_ARRAY_PRESENT .or
+ .true .emit PARAMETER_ARRAY_NOT_PRESENT;
+parameter_declarator_2
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <parameter_declaration> ::= <type_qualifier> <parameter_qualifier>
+ * <precision> <parameter_declarator>
+ * | <type_qualifier> <parameter_qualifier>
+ * <precision> <parameter_type_specifier>
+ * | <type_qualifier> <parameter_qualifier>
+ * <parameter_declarator>
+ * | <type_qualifier> <parameter_qualifier>
+ * <parameter_type_specifier>
+ * | <parameter_qualifier> <precision>
+ * <parameter_declarator>
+ * | <parameter_qualifier> <precision>
+ * <parameter_type_specifier>
+ * | <parameter_qualifier> <parameter_declarator>
+ * | <parameter_qualifier> <parameter_type_specifier>
+ */
+parameter_declaration
+ parameter_declaration_1 .emit PARAMETER_NEXT;
+parameter_declaration_1
+ parameter_declaration_2 .or parameter_declaration_3;
+parameter_declaration_2
+ type_qualifier .and space .and parameter_qualifier .and parameter_declaration_4;
+parameter_declaration_3
+ parameter_qualifier .emit TYPE_QUALIFIER_NONE .and parameter_declaration_4;
+parameter_declaration_4
+ parameter_declaration_optprec .and parameter_declaration_rest;
+parameter_declaration_optprec
+ parameter_declaration_prec .or .true .emit PRECISION_DEFAULT;
+parameter_declaration_prec
+ precision .and space;
+parameter_declaration_rest
+ parameter_declarator .or parameter_type_specifier;
+
+/*
+ * <parameter_qualifier> ::= "in"
+ * | "out"
+ * | "inout"
+ * | ""
+ */
+parameter_qualifier
+ parameter_qualifier_1 .or .true .emit PARAM_QUALIFIER_IN;
+parameter_qualifier_1
+ parameter_qualifier_2 .and space;
+parameter_qualifier_2
+ "in" .emit PARAM_QUALIFIER_IN .or
+ "out" .emit PARAM_QUALIFIER_OUT .or
+ "inout" .emit PARAM_QUALIFIER_INOUT;
+
+/*
+ * <parameter_type_specifier> ::= <type_specifier>
+ * | <type_specifier> "[" <constant_expression> "]"
+ */
+parameter_type_specifier
+ parameter_type_specifier_1 .and .true .emit '\0' .and parameter_type_specifier_2;
+parameter_type_specifier_1
+ type_specifier_nospace .or type_specifier_space;
+parameter_type_specifier_2
+ parameter_type_specifier_3 .emit PARAMETER_ARRAY_PRESENT .or
+ .true .emit PARAMETER_ARRAY_NOT_PRESENT;
+parameter_type_specifier_3
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <init_declarator_list> ::= <single_declaration>
+ * | <init_declarator_list> "," <identifier>
+ * | <init_declarator_list> "," <identifier> "[" "]"
+ * | <init_declarator_list> "," <identifier> "[" <constant_expression> "]"
+ * | <init_declarator_list> "," <identifier> "=" <initializer>
+ */
+init_declarator_list
+ single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and
+ .true .emit DECLARATOR_NONE;
+init_declarator_list_1
+ comma .and identifier .emit VARIABLE_IDENTIFIER .and init_declarator_list_2;
+init_declarator_list_2
+ init_declarator_list_3 .or init_declarator_list_4 .or .true .emit VARIABLE_NONE;
+init_declarator_list_3
+ equals .and initializer .emit VARIABLE_INITIALIZER;
+init_declarator_list_4
+ lbracket .and init_declarator_list_5 .and rbracket;
+init_declarator_list_5
+ constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;
+
+/*
+ * <single_declaration> ::= <fully_specified_type>
+ * | <fully_specified_type> <identifier>
+ * | <fully_specified_type> <identifier> "[" "]"
+ * | <fully_specified_type> <identifier> "[" <constant_expression> "]"
+ * | <fully_specified_type> <identifier> "=" <initializer>
+ */
+single_declaration
+ single_declaration_nospace .or single_declaration_space;
+single_declaration_space
+ fully_specified_type_space .and single_declaration_space_1;
+single_declaration_nospace
+ fully_specified_type_nospace .and single_declaration_nospace_1;
+single_declaration_space_1
+ single_declaration_space_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;
+single_declaration_nospace_1
+ single_declaration_nospace_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;
+single_declaration_space_2
+ space .and identifier .and single_declaration_3;
+single_declaration_nospace_2
+ identifier .and single_declaration_3;
+single_declaration_3
+ single_declaration_4 .or single_declaration_5 .or .true .emit VARIABLE_NONE;
+single_declaration_4
+ equals .and initializer .emit VARIABLE_INITIALIZER;
+single_declaration_5
+ lbracket .and single_declaration_6 .and rbracket;
+single_declaration_6
+ constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;
+
+/*
+ * <fully_specified_type> ::= <opt_invariant> <opt_centroid> <opt_qualifer> <opt_precision> <type_specifier>
+ *
+ * Example: "invariant varying highp vec3"
+ */
+fully_specified_type_space
+ fully_specified_type_optinvariant .and fully_specified_type_optcentroid .and fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_space;
+fully_specified_type_nospace
+ fully_specified_type_optinvariant .and fully_specified_type_optcentroid .and fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_nospace;
+fully_specified_type_optinvariant
+ fully_specified_type_invariant .or .true .emit TYPE_VARIANT;
+fully_specified_type_invariant
+ invariant_qualifier .and space;
+fully_specified_type_optcentroid
+ fully_specified_type_centroid .or .true .emit TYPE_CENTER;
+fully_specified_type_centroid
+ centroid_qualifier .and space;
+fully_specified_type_optqual
+ fully_specified_type_qual .or .true .emit TYPE_QUALIFIER_NONE;
+fully_specified_type_qual
+ type_qualifier .and space;
+fully_specified_type_optprec
+ fully_specified_type_prec .or .true .emit PRECISION_DEFAULT;
+fully_specified_type_prec
+ precision .and space;
+
+/*
+ * <invariant_qualifier> ::= "invariant"
+ */
+invariant_qualifier
+ "invariant" .emit TYPE_INVARIANT;
+
+centroid_qualifier
+ "centroid" .emit TYPE_CENTROID;
+
+
+/*
+ * <type_qualifier> ::= "const"
+ * | "attribute" // Vertex only.
+ * | "varying"
+ * | "uniform"
+ * | "__fixed_output"
+ * | "__fixed_input"
+ *
+ * note: this is an extension to the standard language specification,
+ * normally slang disallows __fixed_output and __fixed_input type qualifiers
+ */
+type_qualifier
+ "const" .emit TYPE_QUALIFIER_CONST .or
+ .if (shader_type == 2) "attribute" .emit TYPE_QUALIFIER_ATTRIBUTE .or
+ "varying" .emit TYPE_QUALIFIER_VARYING .or
+ "uniform" .emit TYPE_QUALIFIER_UNIFORM .or
+ .if (parsing_builtin != 0) "__fixed_output" .emit TYPE_QUALIFIER_FIXEDOUTPUT .or
+ .if (parsing_builtin != 0) "__fixed_input" .emit TYPE_QUALIFIER_FIXEDINPUT;
+
+/*
+ * <type_specifier_nonarray> ::= "void"
+ * | "float"
+ * | "int"
+ * | "bool"
+ * | "vec2"
+ * | "vec3"
+ * | "vec4"
+ * | "bvec2"
+ * | "bvec3"
+ * | "bvec4"
+ * | "ivec2"
+ * | "ivec3"
+ * | "ivec4"
+ * | "mat2"
+ * | "mat3"
+ * | "mat4"
+ * | "mat2x3"
+ * | "mat3x2"
+ * | "mat2x4"
+ * | "mat4x2"
+ * | "mat3x4"
+ * | "mat4x3"
+ * | "sampler1D"
+ * | "sampler2D"
+ * | "sampler3D"
+ * | "samplerCube"
+ * | "sampler1DShadow"
+ * | "sampler2DShadow"
+ * | "sampler2DRect"
+ * | "sampler2DRectShadow"
+ * | <struct_specifier>
+ * | <type_name>
+ */
+type_specifier_nonarray_space
+ "void" .emit TYPE_SPECIFIER_VOID .or
+ "float" .emit TYPE_SPECIFIER_FLOAT .or
+ "int" .emit TYPE_SPECIFIER_INT .or
+ "bool" .emit TYPE_SPECIFIER_BOOL .or
+ "vec2" .emit TYPE_SPECIFIER_VEC2 .or
+ "vec3" .emit TYPE_SPECIFIER_VEC3 .or
+ "vec4" .emit TYPE_SPECIFIER_VEC4 .or
+ "bvec2" .emit TYPE_SPECIFIER_BVEC2 .or
+ "bvec3" .emit TYPE_SPECIFIER_BVEC3 .or
+ "bvec4" .emit TYPE_SPECIFIER_BVEC4 .or
+ "ivec2" .emit TYPE_SPECIFIER_IVEC2 .or
+ "ivec3" .emit TYPE_SPECIFIER_IVEC3 .or
+ "ivec4" .emit TYPE_SPECIFIER_IVEC4 .or
+ "mat2" .emit TYPE_SPECIFIER_MAT2 .or
+ "mat3" .emit TYPE_SPECIFIER_MAT3 .or
+ "mat4" .emit TYPE_SPECIFIER_MAT4 .or
+ "mat2x3" .emit TYPE_SPECIFIER_MAT23 .or
+ "mat3x2" .emit TYPE_SPECIFIER_MAT32 .or
+ "mat2x4" .emit TYPE_SPECIFIER_MAT24 .or
+ "mat4x2" .emit TYPE_SPECIFIER_MAT42 .or
+ "mat3x4" .emit TYPE_SPECIFIER_MAT34 .or
+ "mat4x3" .emit TYPE_SPECIFIER_MAT43 .or
+ "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or
+ "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or
+ "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or
+ "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or
+ "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or
+ "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or
+ "sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or
+ "sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW .or
+ type_name .emit TYPE_SPECIFIER_TYPENAME;
+type_specifier_nonarray_nospace
+ struct_specifier .emit TYPE_SPECIFIER_STRUCT;
+type_specifier_nonarray
+ type_specifier_nonarray_nospace .or type_specifier_nonarray_space;
+
+/*
+ * <type_specifier> ::= <type_specifier_nonarray>
+ * | <type_specifier_nonarray> "[" <constant_expression> "]"
+ */
+type_specifier_space
+ type_specifier_nonarray_space .and .true .emit TYPE_SPECIFIER_NONARRAY;
+type_specifier_nospace
+ type_specifier_nospace_array .or type_specifier_nospace_1;
+type_specifier_nospace_1
+ type_specifier_nonarray_nospace .and .true .emit TYPE_SPECIFIER_NONARRAY;
+type_specifier_nospace_array
+ type_specifier_nonarray .and lbracket .emit TYPE_SPECIFIER_ARRAY .and constant_expression .and rbracket;
+
+/*
+ * <struct_specifier> ::= "struct" <identifier> "{" <struct_declaration_list> "}"
+ * | "struct" "{" <struct_declaration_list> "}"
+ */
+struct_specifier
+ "struct" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and
+ struct_declaration_list .and rbrace .emit FIELD_NONE;
+struct_specifier_1
+ struct_specifier_2 .or .true .emit '\0';
+struct_specifier_2
+ space .and identifier;
+
+/*
+ * <struct_declaration_list> ::= <struct_declaration>
+ * | <struct_declaration_list> <struct_declaration>
+ */
+struct_declaration_list
+ struct_declaration .and .loop struct_declaration .emit FIELD_NEXT;
+
+/*
+ * <struct_declaration> ::= <type_specifier> <struct_declarator_list> ";"
+ */
+struct_declaration
+ struct_declaration_nospace .or struct_declaration_space;
+struct_declaration_space
+ type_specifier_space .and space .and struct_declarator_list .and semicolon .emit FIELD_NONE;
+struct_declaration_nospace
+ type_specifier_nospace .and struct_declarator_list .and semicolon .emit FIELD_NONE;
+
+/*
+ * <struct_declarator_list> ::= <struct_declarator>
+ * | <struct_declarator_list> "," <struct_declarator>
+ */
+struct_declarator_list
+ struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT;
+struct_declarator_list_1
+ comma .and struct_declarator;
+
+/*
+ * <struct_declarator> ::= <identifier>
+ * | <identifier> "[" <constant_expression> "]"
+ */
+struct_declarator
+ identifier .and struct_declarator_1;
+struct_declarator_1
+ struct_declarator_2 .emit FIELD_ARRAY .or .true .emit FIELD_NONE;
+struct_declarator_2
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <initializer> ::= <assignment_expression>
+ */
+initializer
+ assignment_expression .and .true .emit OP_END;
+
+/*
+ * <declaration_statement> ::= <declaration>
+ */
+declaration_statement
+ declaration;
+
+/*
+ * <statement> ::= <compound_statement>
+ * | <simple_statement>
+ */
+statement
+ compound_statement .or simple_statement;
+statement_space
+ compound_statement .or statement_space_1;
+statement_space_1
+ space .and simple_statement;
+
+/*
+ * <simple_statement> ::= <__asm_statement>
+ * | <selection_statement>
+ * | <iteration_statement>
+ * | <jump_statement>
+ * | <expression_statement>
+ * | <declaration_statement>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows use of __asm statements
+ */
+simple_statement
+ .if (parsing_builtin != 0) __asm_statement .emit OP_ASM .or
+ selection_statement .or
+ iteration_statement .or
+ precision_stmt .emit OP_PRECISION .or
+ jump_statement .or
+ expression_statement .emit OP_EXPRESSION .or
+ declaration_statement .emit OP_DECLARE;
+
+/*
+ * <compound_statement> ::= "{" "}"
+ * | "{" <statement_list> "}"
+ */
+compound_statement
+ compound_statement_1 .emit OP_BLOCK_BEGIN_NEW_SCOPE .and .true .emit OP_END;
+compound_statement_1
+ compound_statement_2 .or compound_statement_3;
+compound_statement_2
+ lbrace .and rbrace;
+compound_statement_3
+ lbrace .and statement_list .and rbrace;
+
+/*
+ * <compound_statement_no_new_scope> ::= "{" "}"
+ * | "{" <statement_list> "}"
+ */
+compound_statement_no_new_scope
+ compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END;
+compound_statement_no_new_scope_1
+ compound_statement_no_new_scope_2 .or compound_statement_no_new_scope_3;
+compound_statement_no_new_scope_2
+ lbrace .and rbrace;
+compound_statement_no_new_scope_3
+ lbrace .and statement_list .and rbrace;
+
+
+/*
+ * <statement_list> ::= <statement>
+ * | <statement_list> <statement>
+ */
+statement_list
+ statement .and .loop statement;
+
+/*
+ * <expression_statement> ::= ";"
+ * | <expression> ";"
+ */
+expression_statement
+ expression_statement_1 .or expression_statement_2;
+expression_statement_1
+ semicolon .emit OP_PUSH_VOID .emit OP_END;
+expression_statement_2
+ expression .and semicolon .emit OP_END;
+
+/*
+ * <selection_statement> ::= "if" "(" <expression> ")" <selection_rest_statement>
+ */
+selection_statement
+ "if" .emit OP_IF .and lparen .error LPAREN_EXPECTED .and expression .and
+ rparen .error RPAREN_EXPECTED .emit OP_END .and selection_rest_statement;
+
+/*
+ * <selection_rest_statement> ::= <statement> "else" <statement>
+ * | <statement>
+ */
+selection_rest_statement
+ statement .and selection_rest_statement_1;
+selection_rest_statement_1
+ selection_rest_statement_2 .or .true .emit OP_EXPRESSION .emit OP_PUSH_VOID .emit OP_END;
+selection_rest_statement_2
+ "else" .and optional_space .and statement;
+
+/*
+ * <condition> ::= <expression>
+ * | <fully_specified_type> <identifier> "=" <initializer>
+ *
+ * note: if <condition_1> is executed, the emit format must
+ * match <declaration> emit format
+ */
+condition
+ condition_1 .emit OP_DECLARE .emit DECLARATION_INIT_DECLARATOR_LIST .or
+ condition_3 .emit OP_EXPRESSION;
+condition_1
+ condition_1_nospace .or condition_1_space;
+condition_1_nospace
+ fully_specified_type_nospace .and condition_2;
+condition_1_space
+ fully_specified_type_space .and space .and condition_2;
+condition_2
+ identifier .emit VARIABLE_IDENTIFIER .and equals .emit VARIABLE_INITIALIZER .and
+ initializer .and .true .emit DECLARATOR_NONE;
+condition_3
+ expression .and .true .emit OP_END;
+
+/*
+ * <iteration_statement> ::= "while" "(" <condition> ")" <statement>
+ * | "do" <statement> "while" "(" <expression> ")" ";"
+ * | "for" "(" <for_init_statement> <for_rest_statement> ")" <statement>
+ */
+iteration_statement
+ iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3;
+iteration_statement_1
+ "while" .emit OP_WHILE .and lparen .error LPAREN_EXPECTED .and condition .and
+ rparen .error RPAREN_EXPECTED .and statement;
+iteration_statement_2
+ "do" .emit OP_DO .and statement_space .and "while" .and lparen .error LPAREN_EXPECTED .and
+ expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon;
+iteration_statement_3
+ "for" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and
+ for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement;
+
+/*
+ * <for_init_statement> ::= <expression_statement>
+ * | <declaration_statement>
+ */
+for_init_statement
+ expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE;
+
+/*
+ * <conditionopt> ::= <condition>
+ * | ""
+ *
+ * note: <conditionopt> is used only by "for" statement.
+ * if <condition> is ommitted, parser simulates default behaviour,
+ * that is simulates "true" expression
+ */
+conditionopt
+ condition .or
+ .true .emit OP_EXPRESSION .emit OP_PUSH_BOOL .emit 2 .emit '1' .emit '\0' .emit OP_END;
+
+/*
+ * <for_rest_statement> ::= <conditionopt> ";"
+ * | <conditionopt> ";" <expression>
+ */
+for_rest_statement
+ conditionopt .and semicolon .and for_rest_statement_1;
+for_rest_statement_1
+ for_rest_statement_2 .or .true .emit OP_PUSH_VOID .emit OP_END;
+for_rest_statement_2
+ expression .and .true .emit OP_END;
+
+/*
+ * <jump_statement> ::= "continue" ";"
+ * | "break" ";"
+ * | "return" ";"
+ * | "return" <expression> ";"
+ * | "discard" ";" // Fragment shader only.
+ */
+jump_statement
+ jump_statement_1 .or jump_statement_2 .or jump_statement_3 .or jump_statement_4 .or
+ .if (shader_type == 1) jump_statement_5;
+jump_statement_1
+ "continue" .and semicolon .emit OP_CONTINUE;
+jump_statement_2
+ "break" .and semicolon .emit OP_BREAK;
+jump_statement_3
+ "return" .emit OP_RETURN .and optional_space .and expression .and semicolon .emit OP_END;
+jump_statement_4
+ "return" .emit OP_RETURN .and semicolon .emit OP_PUSH_VOID .emit OP_END;
+jump_statement_5
+ "discard" .and semicolon .emit OP_DISCARD;
+
+/*
+ * <__asm_statement> ::= "__asm" <identifier> <asm_arguments> ";"
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows __asm statements
+ */
+__asm_statement
+ "__asm" .and space .and identifier .and space .and asm_arguments .and semicolon .emit OP_END;
+
+/*
+ * <asm_arguments> ::= <asm_argument>
+ * | <asm_arguments> "," <asm_argument>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows __asm statements
+ */
+asm_arguments
+ asm_argument .and .true .emit OP_END .and .loop asm_arguments_1;
+asm_arguments_1
+ comma .and asm_argument .and .true .emit OP_END;
+
+/*
+ * <asm_argument> ::= <variable_identifier>
+ * | <floatconstant>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows __asm statements
+ */
+asm_argument
+ var_with_field .or
+ variable_identifier .or
+ floatconstant;
+
+var_with_field
+ variable_identifier .and dot .and field_selection .emit OP_FIELD;
+
+
+/*
+ * <translation_unit> ::= <external_declaration>
+ * | <translation_unit> <external_declaration>
+ */
+translation_unit
+ optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and
+ .loop external_declaration .and optional_space .and
+ '\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;
+
+
+/*
+ * <external_declaration> ::= <function_definition>
+ * | <declaration>
+ */
+external_declaration
+ precision_stmt .emit DEFAULT_PRECISION .or
+ function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or
+ invariant_stmt .emit INVARIANT_STMT .or
+ declaration .emit EXTERNAL_DECLARATION;
+
+
+/*
+ * <precision_stmt> ::= "precision" <precision> <prectype>
+ */
+precision_stmt
+ "precision" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;
+
+/*
+ * <precision> ::= "lowp"
+ * | "mediump"
+ * | "highp"
+ */
+precision
+ "lowp" .emit PRECISION_LOW .or
+ "mediump" .emit PRECISION_MEDIUM .or
+ "highp" .emit PRECISION_HIGH;
+
+/*
+ * <prectype> ::= "int"
+ * | "float"
+ * | "a sampler type"
+ */
+prectype
+ "int" .emit TYPE_SPECIFIER_INT .or
+ "float" .emit TYPE_SPECIFIER_FLOAT .or
+ "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or
+ "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or
+ "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or
+ "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or
+ "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or
+ "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or
+ "sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or
+ "sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;
+
+
+/*
+ * <invariant_stmt> ::= "invariant" identifier;
+ */
+invariant_stmt
+ "invariant" .and space .and identifier .and semicolon;
+
+
+/*
+ * <function_definition> :: <function_prototype> <compound_statement_no_new_scope>
+ */
+function_definition
+ function_prototype .and compound_statement_no_new_scope;
+
+
+
+/*
+ * helper rules, not part of the official language syntax
+ */
+
+digit_oct
+ '0'-'7';
+
+digit_dec
+ '0'-'9';
+
+digit_hex
+ '0'-'9' .or 'A'-'F' .or 'a'-'f';
+
+id_character_first
+ 'a'-'z' .or 'A'-'Z' .or '_';
+
+id_character_next
+ id_character_first .or digit_dec;
+
+identifier
+ id_character_first .emit * .and .loop id_character_next .emit * .and .true .emit '\0';
+
+float
+ float_1 .or float_2 .or float_3;
+float_1
+ float_fractional_constant .and float_optional_exponent_part .and optional_f_suffix;
+float_2
+ float_digit_sequence .and .true .emit '\0' .and float_exponent_part .and optional_f_suffix;
+float_3
+ float_digit_sequence .and .true .emit '\0' .and 'f' .emit '\0';
+
+float_fractional_constant
+ float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;
+float_fractional_constant_1
+ float_digit_sequence .and '.' .and float_digit_sequence;
+float_fractional_constant_2
+ float_digit_sequence .and '.' .and .true .emit '\0';
+float_fractional_constant_3
+ '.' .emit '\0' .and float_digit_sequence;
+
+float_optional_exponent_part
+ float_exponent_part .or .true .emit '\0';
+
+float_digit_sequence
+ digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\0';
+
+float_exponent_part
+ float_exponent_part_1 .or float_exponent_part_2;
+float_exponent_part_1
+ 'e' .and float_optional_sign .and float_digit_sequence;
+float_exponent_part_2
+ 'E' .and float_optional_sign .and float_digit_sequence;
+
+float_optional_sign
+ float_sign .or .true;
+
+float_sign
+ '+' .or '-' .emit '-';
+
+optional_f_suffix
+ 'f' .or .true;
+
+
+integer
+ integer_hex .or integer_oct .or integer_dec;
+
+integer_hex
+ '0' .and integer_hex_1 .emit 0x10 .and digit_hex .emit * .and .loop digit_hex .emit * .and
+ .true .emit '\0';
+integer_hex_1
+ 'x' .or 'X';
+
+integer_oct
+ '0' .emit 8 .emit * .and .loop digit_oct .emit * .and .true .emit '\0';
+
+integer_dec
+ digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0';
+
+boolean
+ "true" .emit 2 .emit '1' .emit '\0' .or
+ "false" .emit 2 .emit '0' .emit '\0';
+
+type_name
+ identifier;
+
+field_selection
+ identifier;
+
+floatconstant
+ float .emit OP_PUSH_FLOAT;
+
+intconstant
+ integer .emit OP_PUSH_INT;
+
+boolconstant
+ boolean .emit OP_PUSH_BOOL;
+
+optional_space
+ .loop single_space;
+
+space
+ single_space .and .loop single_space;
+
+single_space
+ white_char .or c_style_comment_block .or cpp_style_comment_block;
+
+white_char
+ ' ' .or '\t' .or new_line .or '\v' .or '\f';
+
+new_line
+ cr_lf .or lf_cr .or '\n' .or '\r';
+
+cr_lf
+ '\r' .and '\n';
+
+lf_cr
+ '\n' .and '\r';
+
+c_style_comment_block
+ '/' .and '*' .and c_style_comment_rest;
+
+c_style_comment_rest
+ .loop c_style_comment_char_no_star .and c_style_comment_rest_1;
+c_style_comment_rest_1
+ c_style_comment_end .or c_style_comment_rest_2;
+c_style_comment_rest_2
+ '*' .and c_style_comment_rest;
+
+c_style_comment_char_no_star
+ '\x2B'-'\xFF' .or '\x01'-'\x29';
+
+c_style_comment_end
+ '*' .and '/';
+
+cpp_style_comment_block
+ '/' .and '/' .and cpp_style_comment_block_1;
+cpp_style_comment_block_1
+ cpp_style_comment_block_2 .or cpp_style_comment_block_3;
+cpp_style_comment_block_2
+ .loop cpp_style_comment_char .and new_line;
+cpp_style_comment_block_3
+ .loop cpp_style_comment_char;
+
+cpp_style_comment_char
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+/* lexical rules */
+
+/*ampersand
+ optional_space .and '&' .and optional_space;*/
+
+ampersandampersand
+ optional_space .and '&' .and '&' .and optional_space;
+
+/*ampersandequals
+ optional_space .and '&' .and '=' .and optional_space;*/
+
+/*bar
+ optional_space .and '|' .and optional_space;*/
+
+barbar
+ optional_space .and '|' .and '|' .and optional_space;
+
+/*barequals
+ optional_space .and '|' .and '=' .and optional_space;*/
+
+bang
+ optional_space .and '!' .and optional_space;
+
+bangequals
+ optional_space .and '!' .and '=' .and optional_space;
+
+/*caret
+ optional_space .and '^' .and optional_space;*/
+
+caretcaret
+ optional_space .and '^' .and '^' .and optional_space;
+
+/*caretequals
+ optional_space .and '^' .and '=' .and optional_space;*/
+
+colon
+ optional_space .and ':' .and optional_space;
+
+comma
+ optional_space .and ',' .and optional_space;
+
+dot
+ optional_space .and '.' .and optional_space;
+
+equals
+ optional_space .and '=' .and optional_space;
+
+equalsequals
+ optional_space .and '=' .and '=' .and optional_space;
+
+greater
+ optional_space .and '>' .and optional_space;
+
+greaterequals
+ optional_space .and '>' .and '=' .and optional_space;
+
+/*greatergreater
+ optional_space .and '>' .and '>' .and optional_space;*/
+
+/*greatergreaterequals
+ optional_space .and '>' .and '>' .and '=' .and optional_space;*/
+
+lbrace
+ optional_space .and '{' .and optional_space;
+
+lbracket
+ optional_space .and '[' .and optional_space;
+
+less
+ optional_space .and '<' .and optional_space;
+
+lessequals
+ optional_space .and '<' .and '=' .and optional_space;
+
+/*lessless
+ optional_space .and '<' .and '<' .and optional_space;*/
+
+/*lesslessequals
+ optional_space .and '<' .and '<' .and '=' .and optional_space;*/
+
+lparen
+ optional_space .and '(' .and optional_space;
+
+minus
+ optional_space .and '-' .and optional_space;
+
+minusequals
+ optional_space .and '-' .and '=' .and optional_space;
+
+minusminus
+ optional_space .and '-' .and '-' .and optional_space;
+
+/*percent
+ optional_space .and '%' .and optional_space;*/
+
+/*percentequals
+ optional_space .and '%' .and '=' .and optional_space;*/
+
+plus
+ optional_space .and '+' .and optional_space;
+
+plusequals
+ optional_space .and '+' .and '=' .and optional_space;
+
+plusplus
+ optional_space .and '+' .and '+' .and optional_space;
+
+question
+ optional_space .and '?' .and optional_space;
+
+rbrace
+ optional_space .and '}' .and optional_space;
+
+rbracket
+ optional_space .and ']' .and optional_space;
+
+rparen
+ optional_space .and ')' .and optional_space;
+
+semicolon
+ optional_space .and ';' .and optional_space;
+
+slash
+ optional_space .and '/' .and optional_space;
+
+slashequals
+ optional_space .and '/' .and '=' .and optional_space;
+
+star
+ optional_space .and '*' .and optional_space;
+
+starequals
+ optional_space .and '*' .and '=' .and optional_space;
+
+/*tilde
+ optional_space .and '~' .and optional_space;*/
+
+/* string rules - these are used internally by the parser when parsing quoted strings */
+
+.string string_lexer;
+
+string_lexer
+ lex_first_identifier_character .and .loop lex_next_identifier_character;
+
+lex_first_identifier_character
+ 'a'-'z' .or 'A'-'Z' .or '_';
+
+lex_next_identifier_character
+ 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';
+
+/* error rules - these are used by error messages */
+
+err_token
+ '~' .or '`' .or '!' .or '@' .or '#' .or '$' .or '%' .or '^' .or '&' .or '*' .or '(' .or ')' .or
+ '-' .or '+' .or '=' .or '|' .or '\\' .or '[' .or ']' .or '{' .or '}' .or ':' .or ';' .or '"' .or
+ '\'' .or '<' .or ',' .or '>' .or '.' .or '/' .or '?' .or err_identifier;
+
+err_identifier
+ id_character_first .and .loop id_character_next;
+