/* * Copyright 2009, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // // Parse HLSL shaders and separate the shader code from the Technique block // parse the technique block into shader declarations and stateassignments // using a Parser and Lexer generated by Antlr3.0 // // Compile from the command line using: // // $ set CLASSPATH=%CLASSPATH%;c:\bin\antlr\antlr-3.1.jar // $ java org.antlr.Tool Technique.g3pl // $ cl *.cc *.c /TP -I c:\bin\antlr\libantlr3c-3.1\include /c /nologo // $ link *.obj /LTCG /out:technique.exe c:\bin\antlr\antlr3c.lib \ // /NODEFAULTLIB:libcmt.lib /nologo grammar Technique; options { language = C; } @lexer::preincludes { #include #include "base/logging.h" #include "core/cross/types.h" #ifdef OS_WIN // These need to be defined here so that when antlr includes // winsock.h, it doesn't barf. For some reason these are undefined by // some header (and it appears to be a windows header). #define IN #define OUT #endif } @lexer::postinclude { namespace o3d { void TechniqueError(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_UINT8 * tokenNames); } } @lexer::apifuncs { // Install the custom error reporting function. RECOGNIZER->displayRecognitionError = o3d::TechniqueError; } @lexer::members { static int toInt(const pANTLR3_STRING string) { return atoi(reinterpret_cast(string->chars)); } static o3d::String toStringL(const pANTLR3_STRING string) { return o3d::String(reinterpret_cast(string->chars)); } // Removes escape sequences, as well as leading and trailing quotes. static ANTLR3_STRING* unescape(const pANTLR3_STRING string) { if (!string || !string->factory) return NULL; ANTLR3_STRING* s = string->factory->newRaw(string->factory); const char *f = reinterpret_cast(string->chars); if (!f) return s; if (*f == '"') f++; for (; *f; f++) { if (*f == '\\') { switch (*++f) { case '\0': return s; case 'b': s->addc(s, '\b'); break; case 't': s->addc(s, '\t'); break; case 'n': s->addc(s, '\n'); break; case 'f': s->addc(s, '\f'); break; case 'r': s->addc(s, '\r'); break; default: s->addc(s, *f); break; } } else if (*f == '"') { return s; } else { s->addc(s, *f); } } return s; } static void setFilename(pANTLR3_BASE_RECOGNIZER rec, const pANTLR3_STRING filename) { if (filename) { // We store the filename into the "custom" field in the lexer state, // which gets copied into each token. If we use the fileName field // in the stream itself, when the lexer runs ahead of the parser // (which is often), the file name can be incorrect. By storing it // in the token itself, the error code can retrieve the filename // associated with that token. rec->state->custom = unescape(filename); } } } @parser::preincludes { // NOTE: this header must be included before the "antlr.h" header // because on Windows it includes which will define // before , causing a cascade of struct redefinition errors. #ifdef OS_WIN // NOTE: disable compiler warning about C function returning a // struct. This is caused by the Antlr generated functions being declared // extern "C" but being compiled and used as C++. #pragma warning( disable: 4190 ) #endif #include #include "base/logging.h" #include "base/string_util.h" #include "core/cross/types.h" #include "compiler/technique/technique_structures.h" } @parser::includes { // NOTE: includes that occur after the "antlr3.h" header has been // declared which therefore can use the Antlr3 datatypes. } @parser::postinclude { namespace o3d { void TechniqueError(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_UINT8 * tokenNames); void TechniqueSetErrorString(String* e); } } @parser::apifuncs { // Install the custom error reporting function. RECOGNIZER->displayRecognitionError = o3d::TechniqueError; } @parser::members { o3d::String *shader_string_; o3d::TechniqueDeclarationList *technique_list_; o3d::SamplerStateList *sampler_list_; o3d::String *error_string_; // NOTE: the reinterpret casts below are // to cast from Antlr3's internal ANTLR_UINT8 strings to the UTF8 // char* that O3D uses. o3d::String toString(const pANTLR3_STRING string) { return o3d::String(reinterpret_cast(string->chars)); } void addString(const pANTLR3_STRING string) { shader_string_->append(toString(string)); } void addText(const pANTLR3_STRING string) { if (string && string->chars) { addString(string); shader_string_->append("\n"); } } void sampler_state_assignment(const pANTLR3_STRING id, const pANTLR3_STRING value) { const char* idc = reinterpret_cast(id->chars); if (!base::strcasecmp(idc, "MinFilter")) { sampler_list_->back().min_filter = toString(value); } else if (!base::strcasecmp(idc, "MagFilter")) { sampler_list_->back().mag_filter = toString(value); } else if (!base::strcasecmp(idc, "MipFilter")) { sampler_list_->back().mip_filter = toString(value); } else if (!base::strcasecmp(idc, "AddressU")) { sampler_list_->back().address_u = toString(value); } else if (!base::strcasecmp(idc, "AddressV")) { sampler_list_->back().address_v = toString(value); } else if (!base::strcasecmp(idc, "AddressW")) { sampler_list_->back().address_w = toString(value); } else if (!base::strcasecmp(idc, "BorderColor")) { sampler_list_->back().border_color = toString(value); } else if (!base::strcasecmp(idc, "MaxAnisotropy")) { sampler_list_->back().max_anisotropy = toString(value); } } } // rules ----------------------------------------------------------------------- // This is the entry rule - zero or more global declarations followed by an // end-of-file token. translation_unit [o3d::TechniqueDeclarationList *technique_list, o3d::SamplerStateList *sampler_list, o3d::String *shader_string, o3d::String *error_string] returns [bool success] @init { // On entry, reset the list of error strings. technique_list_ = technique_list; sampler_list_ = sampler_list; shader_string_ = shader_string; error_string_ = error_string; o3d::TechniqueSetErrorString(error_string_); } @after { // On exit, set the return value. success = error_string_->length() == 0; technique_list_ = NULL; sampler_list_ = NULL; shader_string_ = NULL; error_string_ = NULL; o3d::TechniqueSetErrorString(NULL); } : ( noise global_declaration )* EOF ; noise : ( COMMENT | WHITESPACE | MULTILINE_COMMENT )* { addText($text); } | LINE_DIRECTIVE ; global_declaration : (function_storage_class? function_type_specifier IDENTIFIER LPAREN) => function_declaration { addText($text); } | sampler_declaration | texture_declaration | struct_definition { addText($text); } | typedef_definition { addText($text); } | var_declaration { addText($text); } | technique_definition ; // variables ------------------------------------------- var_declaration : var_storage_class* var_type_modifier? var_datatype id_declaration semantic? annotation_list? ('=' initializer)? var_packoffset? var_register_bind? SEMI ; var_storage_class : EXTERN | NOINTERPOLATION | SHARED | STATIC | UNIFORM | VOLATILE ; var_type_modifier : T_CONST | ROW_MAJOR | COLUMN_MAJOR; var_datatype : buffer_type_specifier | scalar_type_or_string_specifier | vector_type_specifier | matrix_type_specifier | struct_type_specifier ; var_packoffset : 'packoffset' LPAREN register_name (DOT IDENTIFIER)? RPAREN ; var_register_bind : COLON register_name ; id_declaration : IDENTIFIER ( LBRACKET constant_expression RBRACKET )? ; // function -------------------------------------------- function_declaration : function_storage_class? function_type_specifier IDENTIFIER LPAREN argument_list RPAREN semantic? function_body (SEMI)? ; function_storage_class : INLINE // ignoring platform target ; function_type_specifier : scalar_type_specifier | vector_type_specifier | matrix_type_specifier | struct_type_specifier | T_VOID ; semantic : COLON semantic_specifier ; param_type_specifier : scalar_type_specifier | vector_type_specifier | matrix_type_specifier | struct_type_specifier | string_type_specifier | sampler_type_specifier ; basic_type_specifier : scalar_type_specifier | vector_type_specifier | matrix_type_specifier | string_type_specifier ; // typedef --------------------------------------- typedef_definition : TYPEDEF ; // basic datatypes ------------------------------- buffer_type_specifier : (BUFFER '<' var_datatype '>' IDENTIFIER) ; // effects --------------------------------------------------------------------- technique_definition @declarations { o3d::TechniqueDeclaration technique_decl; } @init { // clear the technique declaration before use technique_decl.clear(); } : TECHNIQUE IDENTIFIER { technique_decl.name = toString($IDENTIFIER.text); } annotation_list? '{' ( pass[technique_decl] )+ '}' SEMI? { technique_list_->push_back(technique_decl); } | TECHNIQUE { technique_decl.name = ""; } annotation_list? '{' ( pass[technique_decl] )+ '}' SEMI? { technique_list_->push_back(technique_decl); } ; pass [o3d::TechniqueDeclaration& technique_decl] @declarations { o3d::PassDeclaration pass_decl; } @after { $technique_decl.pass.push_back(pass_decl); } : PASS IDENTIFIER? { if ($IDENTIFIER != NULL && $IDENTIFIER.text->chars != NULL) { pass_decl.name = toString($IDENTIFIER.text); } else { *error_string_ += "Bad pass identifier, line "; *error_string_ += $PASS.line; } } annotation_list? '{' ( state_assignment[pass_decl] )* '}' SEMI? ; state_assignment [o3d::PassDeclaration& pass] : (VERTEXSHADER) => x=VERTEXSHADER '=' 'compile' IDENTIFIER fn=variable_or_call_expression { $pass.vertex_shader_entry = $fn.identifier; $pass.vertex_shader_profile = toString($IDENTIFIER.text); $pass.vertex_shader_arguments = $fn.arglist; } SEMI | (FRAGMENTSHADER) => x=FRAGMENTSHADER '=' 'compile' IDENTIFIER fn=variable_or_call_expression { $pass.fragment_shader_entry = $fn.identifier; $pass.fragment_shader_profile = toString($IDENTIFIER.text); $pass.fragment_shader_arguments = $fn.arglist; } SEMI | IDENTIFIER '=' val=primary_expression { if ($IDENTIFIER.text->chars == NULL) { *error_string_ += "Bad state assigment identifier, line "; *error_string_ += $IDENTIFIER.line; } else if ($val.text->chars == NULL) { *error_string_ = "Bad state assigment value, line "; *error_string_ += $IDENTIFIER.line; } else { o3d::StateAssignment state; state.name = toString($IDENTIFIER.text); state.value = toString($val.text); $pass.state_assignment.push_back(state); } } SEMI ; // data types ------------------------------------------------------------------ scalar_type_specifier : 'bool' | 'int' | 'uint' | 'half' | FLOAT | 'double' ; scalar_type_or_string_specifier : scalar_type_specifier | string_type_specifier ; vector_type_specifier : 'bool1' | 'bool2' | 'bool3' | 'bool4' | 'int1' | 'int2' | 'int3' | 'int4' | 'uint1' | 'uint2' | 'uint3' | 'uint4' | 'half1' | 'half2' | 'half3' | 'half4' | 'float1' | 'float2' | 'float3' | 'float4' | 'double1' | 'double2' | 'double3' | 'double4' | VECTOR '<' scalar_type_specifier ',' DECIMAL_LITERAL '>' ; matrix_type_specifier : 'float1x1' | 'float1x2' | 'float1x3' | 'float1x4' | 'float2x1' | 'float2x2' | 'float2x3' | 'float2x4' | 'float3x1' | 'float3x2' | 'float3x3' | 'float3x4' | 'float4x1' | 'float4x2' | 'float4x3' | 'float4x4' | MATRIX '<' scalar_type_specifier ',' DECIMAL_LITERAL ',' DECIMAL_LITERAL '>' ; string_type_specifier : STRING ; // Sampler declarations ---------------------------- sampler_declaration : sampler_type_specifier id_declaration { o3d::SamplerState s; s.name = toString($id_declaration.text); sampler_list_->push_back(s); addString($sampler_type_specifier.text); shader_string_->append(" "); addString($id_declaration.text); shader_string_->append(";\n"); } ( '=' 'sampler_state' '{' sampler_state_declaration+ '}' )? SEMI ; sampler_state_declaration : TEXTURE '=' '<' IDENTIFIER '>' SEMI { sampler_list_->back().texture = toString($IDENTIFIER.text); } | TEXTURE '=' '(' IDENTIFIER ')' SEMI { sampler_list_->back().texture = toString($IDENTIFIER.text); } | IDENTIFIER '=' initializer SEMI { sampler_state_assignment($IDENTIFIER.text, $initializer.text); } ; sampler_type_specifier : 'sampler' | 'sampler1D' | 'sampler2D' | 'sampler3D' | 'samplerCUBE' | 'sampler_state' | 'SamplerComparisonState' | 'samplercomparisonstate' // DX10 only ; // texture declaration ---------------------------- texture_declaration : texture_type_specifier IDENTIFIER semantic? annotation_list? SEMI ; texture_type_specifier : TEXTURE | TEXTURE1D | TEXTURE2D | TEXTURE3D | TEXTURECUBE | TEXTURERECT ; // struct declaration ----------------------------- struct_type_specifier : IDENTIFIER | ( STRUCT ( IDENTIFIER )? LCURLY ) => struct_definition | STRUCT IDENTIFIER ; annotation_list : '<' annotation* '>' ; annotation : basic_type_specifier IDENTIFIER '=' initializer SEMI ; initializer : expression | '{' expression ( ',' expression )* '}' ; register_name // registers for VS_3_0 : REGISTER '(' input_register_name | output_register_name ')'; input_register_name : IDENTIFIER DECIMAL_LITERAL // IDENTIFIER must be v, r, c, b, i, s, o (check semantically) | IDENTIFIER // IDENTIFIER must be a0 aL p0 (check semantically) ; output_register_name : IDENTIFIER // must be one of: 'oD0', 'oD1', 'oFog', 'oPos', 'oPts', // 'oT0', 'oT1', 'oT2', 'oT3', 'oT4', 'oT5', 'oT6', 'oT7' // (check semantically) ; pack_offset : .+ ; // no idea what this field looks like. argument_list : ( param_declaration ( COMMA param_declaration )* )? ; param_declaration : param_direction? param_variability? param_type_specifier id_declaration semantic? // | FUNCTION type_specifier IDENTIFIER ; param_variability : T_CONST | UNIFORM ; param_direction : T_IN | T_OUT | T_INOUT ; function_body : LCURLY ( decl_or_statement )* RCURLY ; decl_or_statement // We copied the following sub-rule here to expedite the parsing time // as this is a much more common case than the "Id init_declarator_list" // case which would normally spend a lot of time in exception handling. : (lvalue_expression assignment_operator ) => assignment_statement | ( ( T_CONST )? vector_type_specifier ) => ( T_CONST )? vector_type_specifier init_declarator_list SEMI | ( ( T_CONST )? scalar_type_specifier ) => ( T_CONST )? scalar_type_specifier init_declarator_list SEMI | ( ( T_CONST )? matrix_type_specifier ) => ( T_CONST )? matrix_type_specifier init_declarator_list SEMI | ( STRUCT ( IDENTIFIER )? LCURLY ) => struct_definition ( init_declarator_list )? SEMI | STRUCT IDENTIFIER init_declarator_list SEMI | ( IDENTIFIER init_declarator_list ) => IDENTIFIER init_declarator_list SEMI | statement ; init_declarator_list : init_declarator ( COMMA init_declarator )* ; init_declarator : declarator ( ASSIGN expression )? ; declarator : IDENTIFIER ( LBRACKET ( constant_expression )? RBRACKET )* ; struct_definition : STRUCT ( IDENTIFIER )? LCURLY struct_declaration_list RCURLY IDENTIFIER? SEMI ; struct_declaration_list // We currently don't support nested structs so the field type // can only be either a scalar or a vector. : ( struct_interpolation_modifier? (scalar_type_specifier|vector_type_specifier) IDENTIFIER (COLON semantic_specifier)? SEMI )+ ; struct_interpolation_modifier // DX10 only : T_LINEAR | CENTROID | NOINTERPOLATION | NOPERSPECTIVE ; semantic_specifier : IDENTIFIER ; statement : ( lvalue_expression assignment_operator ) => assignment_statement | ( lvalue_expression self_modify_operator ) => post_modify_statement | pre_modify_statement | expression_statement | compound_statement | selection_statement | iteration_statement | jump_statement | SEMI ; assignment_statement : lvalue_expression assignment_operator expression SEMI ; pre_modify_statement : pre_modify_expression SEMI ; pre_modify_expression : self_modify_operator lvalue_expression ; post_modify_statement : post_modify_expression SEMI ; post_modify_expression : lvalue_expression self_modify_operator ; self_modify_operator : PLUS_PLUS | MINUS_MINUS ; expression_statement : expression SEMI ; compound_statement : LCURLY ( ( IDENTIFIER init_declarator_list) => IDENTIFIER init_declarator_list SEMI | ( ( T_CONST )? vector_type_specifier ) => ( T_CONST )? vector_type_specifier init_declarator_list SEMI | ( ( T_CONST )? scalar_type_specifier ) => ( T_CONST )? scalar_type_specifier init_declarator_list SEMI | ( STRUCT ( IDENTIFIER )? LCURLY ) => struct_definition ( init_declarator_list )? SEMI | STRUCT IDENTIFIER init_declarator_list SEMI | statement )* RCURLY ; selection_statement : IF LPAREN expression RPAREN statement ( ELSE statement )? ; iteration_statement : WHILE LPAREN expression RPAREN statement | FOR LPAREN assignment_statement equality_expression SEMI modify_expression RPAREN statement | DO statement WHILE LPAREN expression RPAREN SEMI ; modify_expression : (lvalue_expression assignment_operator ) => lvalue_expression assignment_operator expression | pre_modify_expression | post_modify_expression ; jump_statement : BREAK SEMI | CONTINUE | RETURN ( expression )? SEMI | DISCARD ; expression : conditional_expression ; assignment_operator : ASSIGN | MUL_ASSIGN | DIV_ASSIGN | ADD_ASSIGN | SUB_ASSIGN | BITWISE_AND_ASSIGN | BITWISE_OR_ASSIGN | BITWISE_XOR_ASSIGN | BITWISE_SHIFTL_ASSIGN | BITWISE_SHIFTR_ASSIGN ; constant_expression : (IDENTIFIER) => variable_expression | literal_value ; conditional_expression : logical_or_expression ( QUESTION expression COLON conditional_expression )? ; logical_or_expression : exclusive_or_expression ( OR exclusive_or_expression )* ; // We remove the NOT operator from the unary expression and stick it here // so that it has a lower precedence than relational operations. logical_and_expression : ( NOT )? inclusive_or_expression ( AND ( NOT )? inclusive_or_expression )* ; inclusive_or_expression : exclusive_or_expression (BITWISE_OR exclusive_or_expression )* ; exclusive_or_expression : and_expression ( BITWISE_XOR and_expression )* ; and_expression : equality_expression ( BITWISE_AND equality_expression )* ; equality_expression : relational_expression ( (EQUAL|NOT_EQUAL) relational_expression )* ; relational_expression : shift_expression ( (LESS|GREATER|LESSEQUAL|GREATEREQUAL) shift_expression )* ; shift_expression : additive_expression ( (BITWISE_SHIFTL|BITWISE_SHIFTR) additive_expression )* ; additive_expression : multiplicative_expression ( (PLUS|MINUS) multiplicative_expression )* ; multiplicative_expression : cast_expression ( (MUL|DIV|MOD) cast_expression )* ; cast_expression : LPAREN IDENTIFIER RPAREN postfix_expression | LPAREN basic_type_specifier RPAREN postfix_expression | unary_expression ; unary_expression : (PLUS|MINUS) unary_expression | postfix_expression ; postfix_expression : primary_expression ( postfix_suffix )? ; lvalue_expression : variable_expression ( postfix_suffix )? ; postfix_suffix // choosing between struct field access or vector swizzling is a semantic choice. : ( DOT primary_expression )+ ; primary_expression : constructor | variable_or_call_expression | literal_value | LPAREN expression RPAREN ; variable_expression : IDENTIFIER ( LBRACKET expression RBRACKET )? ; // Combine variable expression and call expression here to get rid of the // syntactic predicate we used to use in the primary_expression rule. Using // predicates results in the parser spending a lot of time in exception // handling (when lookahead fails). variable_or_call_expression returns [o3d::String identifier, o3d::String arglist] : IDENTIFIER ( ( ( LBRACKET expression RBRACKET )? ) { $identifier = toString($IDENTIFIER.text); $arglist = ""; } | ( LPAREN argument_expression_list RPAREN ) { $identifier = toString($IDENTIFIER.text); if ($argument_expression_list.text->chars) { $arglist = toString($argument_expression_list.text); } else { $arglist = ""; } } ) ; constructor : ( vector_type_specifier | matrix_type_specifier ) LPAREN expression ( COMMA expression )* RPAREN ; argument_expression_list : ( expression ( COMMA expression )* )? ; int_literal : DECIMAL_LITERAL // | OCT_LITERAL // | HEX_LITERAL ; literal_value : DECIMAL_LITERAL | FLOAT_LITERAL | STRING_LITERAL+ | ( T_FALSE | T_TRUE ) ; float_literal : FLOAT_LITERAL ; // lexical elements ------------------------------------------------------------ NOT : '!' ; NOT_EQUAL : '!=' ; AND : '&&' ; LPAREN : '(' ; RPAREN : ')' ; MUL : '*' ; MUL_ASSIGN : '*=' ; PLUS : '+' ; PLUS_PLUS : '++' ; ADD_ASSIGN : '+=' ; COMMA : ',' ; MINUS : '-' ; MINUS_MINUS : '--' ; SUB_ASSIGN : '-=' ; DIV : '/' ; DIV_ASSIGN : '/=' ; MOD : '%'; MOD_ASSIGN : '%='; COLON : ':' ; SEMI : ';' ; LESS : '<' ; LESSEQUAL : '<=' ; ASSIGN : '=' ; EQUAL : '==' ; GREATER : '>' ; GREATEREQUAL : '>=' ; QUESTION : '?' ; LBRACKET : '[' ; RBRACKET : ']' ; LCURLY : '{' ; OR : '||' ; RCURLY : '}' ; DOT : '.' ; BITWISE_NOT : '~'; BITWISE_SHIFTL : '<<'; BITWISE_SHIFTR : '>>'; BITWISE_AND : '&'; BITWISE_OR : '|'; BITWISE_XOR : '^'; BITWISE_SHIFTL_ASSIGN : '<<='; BITWISE_SHIFTR_ASSIGN : '>>='; BITWISE_AND_ASSIGN : '&='; BITWISE_OR_ASSIGN : '|='; BITWISE_XOR_ASSIGN : '^='; // keywords ---------------------------- BREAK : 'break'; BUFFER : 'buffer'; COLUMN_MAJOR : 'column_major'; CBUFFER : 'cbuffer'; CENTROID : 'centroid'; T_CONST : 'const'; CONTINUE : 'continue'; DISCARD : 'discard'; DO : 'do'; ELSE : 'else'; EXTERN : 'extern'; T_FALSE : 'false'; FLOAT : (('f'|'F')('l'|'L')('o'|'O')('a'|'A')('t'|'T')); FOR : 'for'; IF : 'if'; T_IN : 'in'; INLINE : 'inline'; T_INOUT : 'inout'; T_LINEAR : 'linear'; MATRIX : ('m'|'M')('a'|'A')('t'|'T')('r'|'R')('i'|'I')('x'|'X'); NAMESPACE : 'namespace'; NOINTERPOLATION : 'nointerpolation'; NOPERSPECTIVE : 'noperspective'; T_OUT : 'out'; RETURN : 'return'; REGISTER : 'register'; ROW_MAJOR : 'row_major'; SHARED : 'shared'; STATEBLOCK : 'stateblock'; STATEBLOCK_STATE : 'stateblock_state'; STATIC : 'static'; STRING : ('s'|'S')('t'|'T')('r'|'R')('i'|'I')('n'|'N')('g'|'G'); STRUCT : 'struct'; SWITCH : 'switch'; TBUFFER : 'tbuffer'; TEXTURE : ('t'|'T')('e'|'E')('x'|'X')('t'|'T')('u'|'U')('r'|'R')('e'|'E'); TEXTURE1D : 'Texture1D'; TEXTURE1DARRAY : 'Texture1DArray'; TEXTURE2D : 'Texture2D'; TEXTURE2DARRAY : 'Texture2DArray'; TEXTURE2DMS : 'Texture2DMS'; TEXTURE2DMSARRAY : 'Texture2DMSArray'; TEXTURE3D : 'Texture3D'; TEXTURECUBE : 'TextureCUBE'; TEXTURECUBEARRAY : 'TextureCUBEArray'; TEXTURERECT : 'TextureRECT'; T_TRUE : 'true'; TYPEDEF : 'typedef'; UNIFORM : 'uniform'; VECTOR : ('v'|'V')('e'|'E')('c'|'C')('t'|'T')('o'|'O')('r'|'R'); T_VOID : 'void'; VOLATILE : 'volatile'; WHILE : 'while'; // sampler state tokens PASS : ('p'|'P')('a'|'A')('s'|'S')('s'|'S'); TECHNIQUE : ('t'|'T')('e'|'E')('c'|'C')('h'|'H') ('n'|'N')('i'|'I')('q'|'Q')('u'|'U')('e'|'E') ; VERTEXSHADER : (('v'|'V')('e'|'E')('r'|'R')('t'|'T')('e'|'E')('x'|'X')) ((('s'|'S')('h'|'H')('a'|'A')('d'|'D')('e'|'E')('r'|'R')) | (('p'|'P')('r'|'R')('o'|'O')('g'|'G')('r'|'R')('a'|'A')('m'|'M'))) ; FRAGMENTSHADER : (('f'|'F')('r'|'R')('a'|'A')('g'|'G')('m'|'M')('e'|'E')('n'|'N')('t'|'T') ('p'|'P')('r'|'R')('o'|'O')('g'|'G')('r'|'R')('a'|'A')('m'|'M')) | (('p'|'P')('i'|'I')('x'|'X')('e'|'E')('l'|'L') ('s'|'S')('h'|'H')('a'|'A')('d'|'D')('e'|'E')('r'|'R')) ; RESERVED_WORDS : (('a'|'A')('S'|'s')('m'|'M')) | 'asm_fragment' | 'auto' | 'case' | 'catch' | 'char' | 'class' | 'const_cast' | (('d'|'D')('e'|'E')('c'|'C')('l'|'L')) | 'default' | 'delete' | (('d'|'D')('w'|'W')('o'|'O')('r'|'R')('d'|'D')) | 'dynamic_cast' | 'emit' | 'enum' | 'explicit' | 'fixed' | 'friend' | 'get' | 'goto' | 'interface' | 'long' | 'mutable' | 'new' | 'operator' | 'packed' | (('p'|'P')('i'|'I')('x'|'X')('e'|'E')('l'|'L') ('f'|'F')('r'|'R')('a'|'A')('g'|'G')('m'|'M')('e'|'E')('n'|'N')('t'|'T')) | 'private' | 'protected' | 'public' | 'reinterpret_cast' | 'short' | 'signed' | 'sizeof' | 'snorm' | 'static_cast' | 'template' | 'this' | 'throw' | 'try' | 'typeid' | 'typename' | 'union' | 'unorm' | 'unsigned' | 'using' | (('v'|'V')('e'|'E')('r'|'R')('t'|'T')('e'|'E')('x'|'X') ('f'|'F')('r'|'R')('a'|'A') ('g'|'G')('m'|'M')('e'|'E')('n'|'N')('t'|'T')) | 'virtual' ; IDENTIFIER : ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'_'|'0'..'9')* ; DECIMAL_LITERAL : ('0'..'9')+ ; fragment ESCAPE_SEQUENCE : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') ; CHARACTER_LITERAL : '\'' ( ESCAPE_SEQUENCE | ~('\''|'\\') ) '\'' ; STRING_LITERAL : '"' ( ESCAPE_SEQUENCE | ~('\\'|'"') )* '"' ; fragment EXPONENT : ('e'|'E') (PLUS | MINUS)? ('0'..'9')+ ; fragment FLOATSUFFIX : ('f'|'F'|'h'|'H') ; FLOAT_LITERAL : ('0'..'9')+ '.' ('0'..'9')* (EXPONENT)? (FLOATSUFFIX)? | '.' ('0'..'9')+ (EXPONENT)? (FLOATSUFFIX)? ; // skipped elements ------------------------------------------------------------ LINE_DIRECTIVE : '#line' (' '|'\t')* line_num=DECIMAL_LITERAL '\r'? '\n' { INPUT->setLine(INPUT, toInt($line_num.text)); $channel = HIDDEN; } | '#line' (' '|'\t')* line_num=DECIMAL_LITERAL (' '|'\t')* file=STRING_LITERAL '\r'? '\n' { INPUT->setLine(INPUT, toInt($line_num.text)); $channel = HIDDEN; setFilename(RECOGNIZER, $file.text); } ; WHITESPACE : (' '|'\r'|'\t'|'\u000C'|'\n') { $channel = HIDDEN; } ; COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' { $channel = HIDDEN; } ; MULTILINE_COMMENT : '/*' ( options {greedy=false;} : . )* '*/' { $channel = HIDDEN; } ; // -----------------------------------------------------------------------------