| /* |
| * Mesa 3-D graphics library |
| * Version: 6.5 |
| * |
| * Copyright (C) 2004-2006 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 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 target, one must reserve 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 4 |
| |
| /* 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 |
| |
| /* 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 |
| |
| /* 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 |
| |
| |
| /* 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 |
| |
| /* 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_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> |
| |
| note: <constructor_identifier> has been deleted |
| */ |
| function_identifier |
| identifier; |
| |
| /* |
| <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> |
| <parameter_declarator> |
| | <type_qualifier> <parameter_qualifier> |
| <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_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> ::= <type_specifier> |
| | <type_qualifier> <type_specifier> |
| | <precision> <type_specifier> |
| | <type_qualifier> <precision> <type_specifier> |
| */ |
| fully_specified_type_space |
| fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_space; |
| fully_specified_type_nospace |
| fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_nospace; |
| 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; |
| |
| /* |
| <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> ::= "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_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_nospace |
| struct_specifier .emit TYPE_SPECIFIER_STRUCT; |
| |
| /* |
| <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 |
| 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; |
| |
| /* |
| <statement_no_new_scope> ::= <compound_statement_no_new_scope> |
| | <simple_statement> |
| */ |
| statement_no_new_scope |
| compound_statement_no_new_scope .or simple_statement; |
| |
| /* |
| <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_no_new_scope> |
| */ |
| 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_no_new_scope; |
| |
| /* |
| <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 |
| invariant_stmt .emit INVARIANT_STMT .or |
| function_definition .emit EXTERNAL_FUNCTION_DEFINITION .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 rulez, 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; |
| float_1 |
| float_fractional_constant .and float_optional_exponent_part; |
| float_2 |
| float_digit_sequence .and .true .emit '\0' .and float_exponent_part; |
| |
| 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 '-'; |
| |
| 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 rulez */ |
| |
| /*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 rulez - 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 rulez - 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; |
| |