void Scanner::getWord(char *str, char *token_ptr, Token **tok) { /* Write some code to Extract the word */ char ch = *theLinePtr; while ((char_table[ch] == LETTER) || (char_table[ch] == DIGIT)) { *token_ptr++ = *theLinePtr++; ch = *theLinePtr; } *token_ptr = '\0'; //Downshift the word, to make it lower case downshiftWord(str); /* Write some code to Check if the word is a reserved word. if it is not a reserved word its an identifier. */ const RwStruct *rw_ptr = reservedWord(str); if (rw_ptr == NULL) { //set token to identifier *tok = new Identify(); } else { *tok = new Token(); (*tok)->setCode(rw_ptr->token_code); } (*tok)->setTokenString(string(str)); }
int TScanContext::identifierOrReserved(bool reserved) { if (reserved) { reservedWord(); return 0; } if (parseContext.forwardCompatible) parseContext.warn(loc, "using future reserved keyword", tokenText, ""); return identifierOrType(); }
// For keywords that suddenly showed up on non-ES (not previously reserved) // but then got reserved by ES 3.0. int TScanContext::es30ReservedFromGLSL(int version) { if (parseContext.symbolTable.atBuiltInLevel()) return keyword; if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < version)) { if (parseContext.forwardCompatible) parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, ""); return identifierOrType(); } else if (parseContext.profile == EEsProfile && parseContext.version >= 300) reservedWord(); return keyword; }
int TScanContext::secondGenerationImage() { if (parseContext.profile == EEsProfile && parseContext.version >= 310) { reservedWord(); return keyword; } if (parseContext.symbolTable.atBuiltInLevel() || (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) return keyword; if (parseContext.forwardCompatible) parseContext.warn(loc, "using future type keyword", tokenText, ""); return identifierOrType(); }
int TScanContext::dMat() { afterType = true; if (parseContext.profile == EEsProfile && parseContext.version >= 300) { reservedWord(); return keyword; } if (parseContext.profile != EEsProfile && parseContext.version >= 400) return keyword; if (parseContext.forwardCompatible) parseContext.warn(loc, "using future type keyword", tokenText, ""); return identifierOrType(); }
int TScanContext::firstGenerationImage(bool inEs310) { afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &E_GL_ARB_shader_image_load_store))) || (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310)) return keyword; if ((parseContext.profile == EEsProfile && parseContext.version >= 300) || (parseContext.profile != EEsProfile && parseContext.version >= 130)) { reservedWord(); return keyword; } if (parseContext.forwardCompatible) parseContext.warn(loc, "using future type keyword", tokenText, ""); return identifierOrType(); }
EHlslTokenClass HlslScanContext::tokenizeIdentifier() { if (ReservedSet->find(tokenText) != ReservedSet->end()) return reservedWord(); auto it = KeywordMap->find(tokenText); if (it == KeywordMap->end()) { // Should have an identifier of some sort return identifierOrType(); } keyword = it->second; switch (keyword) { // qualifiers case EHTokStatic: case EHTokConst: case EHTokSNorm: case EHTokUnorm: case EHTokExtern: case EHTokUniform: case EHTokVolatile: case EHTokShared: case EHTokGroupShared: case EHTokLinear: case EHTokCentroid: case EHTokNointerpolation: case EHTokNoperspective: case EHTokSample: case EHTokRowMajor: case EHTokColumnMajor: case EHTokPackOffset: case EHTokIn: case EHTokOut: case EHTokInOut: case EHTokPrecise: case EHTokLayout: case EHTokGloballyCoherent: case EHTokInline: return keyword; // primitive types case EHTokPoint: case EHTokLine: case EHTokTriangle: case EHTokLineAdj: case EHTokTriangleAdj: return keyword; // stream out types case EHTokPointStream: case EHTokLineStream: case EHTokTriangleStream: return keyword; // Tessellation patches case EHTokInputPatch: case EHTokOutputPatch: return keyword; case EHTokBuffer: case EHTokVector: case EHTokMatrix: return keyword; // scalar types case EHTokVoid: case EHTokString: case EHTokBool: case EHTokInt: case EHTokUint: case EHTokDword: case EHTokHalf: case EHTokFloat: case EHTokDouble: case EHTokMin16float: case EHTokMin10float: case EHTokMin16int: case EHTokMin12int: case EHTokMin16uint: // vector types case EHTokBool1: case EHTokBool2: case EHTokBool3: case EHTokBool4: case EHTokFloat1: case EHTokFloat2: case EHTokFloat3: case EHTokFloat4: case EHTokInt1: case EHTokInt2: case EHTokInt3: case EHTokInt4: case EHTokDouble1: case EHTokDouble2: case EHTokDouble3: case EHTokDouble4: case EHTokUint1: case EHTokUint2: case EHTokUint3: case EHTokUint4: case EHTokHalf1: case EHTokHalf2: case EHTokHalf3: case EHTokHalf4: case EHTokMin16float1: case EHTokMin16float2: case EHTokMin16float3: case EHTokMin16float4: case EHTokMin10float1: case EHTokMin10float2: case EHTokMin10float3: case EHTokMin10float4: case EHTokMin16int1: case EHTokMin16int2: case EHTokMin16int3: case EHTokMin16int4: case EHTokMin12int1: case EHTokMin12int2: case EHTokMin12int3: case EHTokMin12int4: case EHTokMin16uint1: case EHTokMin16uint2: case EHTokMin16uint3: case EHTokMin16uint4: // matrix types case EHTokBool1x1: case EHTokBool1x2: case EHTokBool1x3: case EHTokBool1x4: case EHTokBool2x1: case EHTokBool2x2: case EHTokBool2x3: case EHTokBool2x4: case EHTokBool3x1: case EHTokBool3x2: case EHTokBool3x3: case EHTokBool3x4: case EHTokBool4x1: case EHTokBool4x2: case EHTokBool4x3: case EHTokBool4x4: case EHTokInt1x1: case EHTokInt1x2: case EHTokInt1x3: case EHTokInt1x4: case EHTokInt2x1: case EHTokInt2x2: case EHTokInt2x3: case EHTokInt2x4: case EHTokInt3x1: case EHTokInt3x2: case EHTokInt3x3: case EHTokInt3x4: case EHTokInt4x1: case EHTokInt4x2: case EHTokInt4x3: case EHTokInt4x4: case EHTokUint1x1: case EHTokUint1x2: case EHTokUint1x3: case EHTokUint1x4: case EHTokUint2x1: case EHTokUint2x2: case EHTokUint2x3: case EHTokUint2x4: case EHTokUint3x1: case EHTokUint3x2: case EHTokUint3x3: case EHTokUint3x4: case EHTokUint4x1: case EHTokUint4x2: case EHTokUint4x3: case EHTokUint4x4: case EHTokFloat1x1: case EHTokFloat1x2: case EHTokFloat1x3: case EHTokFloat1x4: case EHTokFloat2x1: case EHTokFloat2x2: case EHTokFloat2x3: case EHTokFloat2x4: case EHTokFloat3x1: case EHTokFloat3x2: case EHTokFloat3x3: case EHTokFloat3x4: case EHTokFloat4x1: case EHTokFloat4x2: case EHTokFloat4x3: case EHTokFloat4x4: case EHTokDouble1x1: case EHTokDouble1x2: case EHTokDouble1x3: case EHTokDouble1x4: case EHTokDouble2x1: case EHTokDouble2x2: case EHTokDouble2x3: case EHTokDouble2x4: case EHTokDouble3x1: case EHTokDouble3x2: case EHTokDouble3x3: case EHTokDouble3x4: case EHTokDouble4x1: case EHTokDouble4x2: case EHTokDouble4x3: case EHTokDouble4x4: return keyword; // texturing types case EHTokSampler: case EHTokSampler1d: case EHTokSampler2d: case EHTokSampler3d: case EHTokSamplerCube: case EHTokSamplerState: case EHTokSamplerComparisonState: case EHTokTexture: case EHTokTexture1d: case EHTokTexture1darray: case EHTokTexture2d: case EHTokTexture2darray: case EHTokTexture3d: case EHTokTextureCube: case EHTokTextureCubearray: case EHTokTexture2DMS: case EHTokTexture2DMSarray: case EHTokRWTexture1d: case EHTokRWTexture1darray: case EHTokRWTexture2d: case EHTokRWTexture2darray: case EHTokRWTexture3d: case EHTokRWBuffer: case EHTokAppendStructuredBuffer: case EHTokByteAddressBuffer: case EHTokConsumeStructuredBuffer: case EHTokRWByteAddressBuffer: case EHTokRWStructuredBuffer: case EHTokStructuredBuffer: return keyword; // variable, user type, ... case EHTokClass: case EHTokStruct: case EHTokTypedef: case EHTokCBuffer: case EHTokConstantBuffer: case EHTokTBuffer: case EHTokThis: case EHTokNamespace: return keyword; case EHTokBoolConstant: if (strcmp("true", tokenText) == 0) parserToken->b = true; else parserToken->b = false; return keyword; // control flow case EHTokFor: case EHTokDo: case EHTokWhile: case EHTokBreak: case EHTokContinue: case EHTokIf: case EHTokElse: case EHTokDiscard: case EHTokReturn: case EHTokCase: case EHTokSwitch: case EHTokDefault: return keyword; default: parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); return EHTokNone; } }
int TScanContext::tokenizeIdentifier() { if (ReservedSet->find(tokenText) != ReservedSet->end()) return reservedWord(); auto it = KeywordMap->find(tokenText); if (it == KeywordMap->end()) { // Should have an identifier of some sort return identifierOrType(); } keyword = it->second; field = false; switch (keyword) { case CONST: case UNIFORM: case IN: case OUT: case INOUT: case STRUCT: case BREAK: case CONTINUE: case DO: case FOR: case WHILE: case IF: case ELSE: case DISCARD: case RETURN: case CASE: return keyword; case SWITCH: case DEFAULT: if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < 130)) reservedWord(); return keyword; case VOID: case BOOL: case FLOAT: case INT: case BVEC2: case BVEC3: case BVEC4: case VEC2: case VEC3: case VEC4: case IVEC2: case IVEC3: case IVEC4: case MAT2: case MAT3: case MAT4: case SAMPLER2D: case SAMPLERCUBE: afterType = true; return keyword; case BOOLCONSTANT: if (strcmp("true", tokenText) == 0) parserToken->sType.lex.b = true; else parserToken->sType.lex.b = false; return keyword; case ATTRIBUTE: case VARYING: if (parseContext.profile == EEsProfile && parseContext.version >= 300) reservedWord(); return keyword; case BUFFER: if ((parseContext.profile == EEsProfile && parseContext.version < 310) || (parseContext.profile != EEsProfile && parseContext.version < 430)) return identifierOrType(); return keyword; case ATOMIC_UINT: if ((parseContext.profile == EEsProfile && parseContext.version >= 310) || parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters)) return keyword; return es30ReservedFromGLSL(420); case COHERENT: case RESTRICT: case READONLY: case WRITEONLY: if (parseContext.profile == EEsProfile && parseContext.version >= 310) return keyword; return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420); case VOLATILE: if (parseContext.profile == EEsProfile && parseContext.version >= 310) return keyword; if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) reservedWord(); return keyword; case LAYOUT: { const int numLayoutExts = 2; const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack, E_GL_ARB_explicit_attrib_location }; if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < 140 && ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts))) return identifierOrType(); return keyword; } case SHARED: if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < 140)) return identifierOrType(); return keyword; case PATCH: if (parseContext.symbolTable.atBuiltInLevel() || (parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) || (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader))) return keyword; return es30ReservedFromGLSL(400); case SAMPLE: if (parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation)) return keyword; return es30ReservedFromGLSL(400); case SUBROUTINE: return es30ReservedFromGLSL(400); case HIGH_PRECISION: case MEDIUM_PRECISION: case LOW_PRECISION: case PRECISION: return precisionKeyword(); case MAT2X2: case MAT2X3: case MAT2X4: case MAT3X2: case MAT3X3: case MAT3X4: case MAT4X2: case MAT4X3: case MAT4X4: return matNxM(); case DMAT2: case DMAT3: case DMAT4: case DMAT2X2: case DMAT2X3: case DMAT2X4: case DMAT3X2: case DMAT3X3: case DMAT3X4: case DMAT4X2: case DMAT4X3: case DMAT4X4: return dMat(); case IMAGE1D: case IIMAGE1D: case UIMAGE1D: case IMAGE1DARRAY: case IIMAGE1DARRAY: case UIMAGE1DARRAY: case IMAGE2DRECT: case IIMAGE2DRECT: case UIMAGE2DRECT: afterType = true; return firstGenerationImage(false); case IMAGEBUFFER: case IIMAGEBUFFER: case UIMAGEBUFFER: afterType = true; if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) return keyword; return firstGenerationImage(false); case IMAGE2D: case IIMAGE2D: case UIMAGE2D: case IMAGE3D: case IIMAGE3D: case UIMAGE3D: case IMAGECUBE: case IIMAGECUBE: case UIMAGECUBE: case IMAGE2DARRAY: case IIMAGE2DARRAY: case UIMAGE2DARRAY: afterType = true; return firstGenerationImage(true); case IMAGECUBEARRAY: case IIMAGECUBEARRAY: case UIMAGECUBEARRAY: afterType = true; if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) return keyword; return secondGenerationImage(); case IMAGE2DMS: case IIMAGE2DMS: case UIMAGE2DMS: case IMAGE2DMSARRAY: case IIMAGE2DMSARRAY: case UIMAGE2DMSARRAY: afterType = true; return secondGenerationImage(); case DOUBLE: case DVEC2: case DVEC3: case DVEC4: afterType = true; if (parseContext.profile == EEsProfile || parseContext.version < 400) reservedWord(); return keyword; case SAMPLERCUBEARRAY: case SAMPLERCUBEARRAYSHADOW: case ISAMPLERCUBEARRAY: case USAMPLERCUBEARRAY: afterType = true; if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) return keyword; if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array))) reservedWord(); return keyword; case ISAMPLER1D: case ISAMPLER1DARRAY: case SAMPLER1DARRAYSHADOW: case USAMPLER1D: case USAMPLER1DARRAY: afterType = true; return es30ReservedFromGLSL(130); case UINT: case UVEC2: case UVEC3: case UVEC4: case SAMPLERCUBESHADOW: case SAMPLER2DARRAY: case SAMPLER2DARRAYSHADOW: case ISAMPLER2D: case ISAMPLER3D: case ISAMPLERCUBE: case ISAMPLER2DARRAY: case USAMPLER2D: case USAMPLER3D: case USAMPLERCUBE: case USAMPLER2DARRAY: afterType = true; return nonreservedKeyword(300, 130); case ISAMPLER2DRECT: case USAMPLER2DRECT: afterType = true; return es30ReservedFromGLSL(140); case SAMPLERBUFFER: afterType = true; if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) return keyword; return es30ReservedFromGLSL(130); case ISAMPLERBUFFER: case USAMPLERBUFFER: afterType = true; if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) return keyword; return es30ReservedFromGLSL(140); case SAMPLER2DMS: case ISAMPLER2DMS: case USAMPLER2DMS: afterType = true; if (parseContext.profile == EEsProfile && parseContext.version >= 310) return keyword; return es30ReservedFromGLSL(150); case SAMPLER2DMSARRAY: case ISAMPLER2DMSARRAY: case USAMPLER2DMSARRAY: afterType = true; if (parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array)) return keyword; return es30ReservedFromGLSL(150); case SAMPLER1D: case SAMPLER1DSHADOW: afterType = true; if (parseContext.profile == EEsProfile) reservedWord(); return keyword; case SAMPLER3D: afterType = true; if (parseContext.profile == EEsProfile && parseContext.version < 300) { if (! parseContext.extensionTurnedOn(E_GL_OES_texture_3D)) reservedWord(); } return keyword; case SAMPLER2DSHADOW: afterType = true; if (parseContext.profile == EEsProfile && parseContext.version < 300) reservedWord(); return keyword; case SAMPLER2DRECT: case SAMPLER2DRECTSHADOW: afterType = true; if (parseContext.profile == EEsProfile) reservedWord(); else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) { if (parseContext.relaxedErrors()) parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword"); else reservedWord(); } return keyword; case SAMPLER1DARRAY: afterType = true; if (parseContext.profile == EEsProfile && parseContext.version == 300) reservedWord(); else if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < 130)) return identifierOrType(); return keyword; case SAMPLEREXTERNALOES: afterType = true; if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external)) return keyword; return identifierOrType(); case NOPERSPECTIVE: return es30ReservedFromGLSL(130); case SMOOTH: if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < 130)) return identifierOrType(); return keyword; case FLAT: if (parseContext.profile == EEsProfile && parseContext.version < 300) reservedWord(); else if (parseContext.profile != EEsProfile && parseContext.version < 130) return identifierOrType(); return keyword; case CENTROID: if (parseContext.version < 120) return identifierOrType(); return keyword; case PRECISE: if ((parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5)) || (parseContext.profile != EEsProfile && parseContext.version >= 400)) return keyword; if (parseContext.profile == EEsProfile && parseContext.version == 310) { reservedWord(); return keyword; } return identifierOrType(); case INVARIANT: if (parseContext.profile != EEsProfile && parseContext.version < 120) return identifierOrType(); return keyword; case PACKED: if ((parseContext.profile == EEsProfile && parseContext.version < 300) || (parseContext.profile != EEsProfile && parseContext.version < 330)) return reservedWord(); return identifierOrType(); case RESOURCE: { bool reserved = (parseContext.profile == EEsProfile && parseContext.version >= 300) || (parseContext.profile != EEsProfile && parseContext.version >= 420); return identifierOrReserved(reserved); } case SUPERP: { bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130; return identifierOrReserved(reserved); } default: parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); return 0; } }
index_t get_token(FILE *fin, TDynamic_buffer *buffer, TDynamic_structure_buffer *struct_buffer) { args_assert(buffer != NULL && struct_buffer != NULL, INTERNAL_ERROR); debug_print("%s\n", "GET_TOKEN"); char hx[3] = {0, 0, '\0'}; char x; int c; int previous = 0; int state = START; bool read = true; bool signed_scientific = false; bool wrong_identifier = false; bool is_number_after_sign = false; bool is_number_after_dot = false; bool is_end = true; index_t index = 0; TToken *token; new_item(struct_buffer, index, token); while (1) { if (read) { c = fgetc(fin); if (feof(fin) && is_end) { if (state == BLOCK_COMMENT) { token->token_index = save_token(buffer); token->token_type = ERRORT; } else { token->token_index = save_token(buffer); token->token_type = EOFT; } return index; } } else { c = previous; read = true; } switch (state) { case START: if ((c > 64 && c < 91) || (c > 96 && c < 123) || c == '_') // A-Z || a-z || _ { state = IDENTIFIER; catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); } else if (c > 47 && c < 58) // 0-9 { state = L_INT; catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); } else { switch (c) { case '+': token->token_index = save_token(buffer); token->token_type = O_PLUS; return index; break; case '-': token->token_index = save_token(buffer); token->token_type = O_MINUS; return index; break; case '/': state = COMMENT; is_end = false; break; case '*': token->token_index = save_token(buffer); token->token_type = O_MUL; return index; break; case ';': token->token_index = save_token(buffer); token->token_type = SEMICOLON; return index; break; case ',': token->token_index = save_token(buffer); token->token_type = COMMA; return index; break; case '(': token->token_index = save_token(buffer); token->token_type = OPENING_BRACKET; return index; break; case ')': token->token_index = save_token(buffer); token->token_type = CLOSING_BRACKET; return index; break; case '{': token->token_index = save_token(buffer); token->token_type = OPENING_CURLY_BRACKET; return index; break; case '}': token->token_index = save_token(buffer); token->token_type = CLOSING_CURLY_BRACKET; return index; break; case '=': state = O_EQUALS; is_end = false; break; case '<': state = O_L; is_end = false; break; case '>': state = O_G; is_end = false; break; case '!': state = UO_EXCLAMATION; is_end = false; break; case '"': state = L_STRING; is_end = false; break; default: if (!isspace(c)) { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); token->token_index = save_token(buffer); token->token_type = ERRORT; return index; } break; } // switch(c) } // else break; case COMMENT: debug_print("%s","COMMENT COMMENT COMMENT COMMENT COMMENT\n"); if (c == '/') // // { state = LINE_COMMENT; is_end = false; } else if (c == '*') // /* { state = BLOCK_COMMENT; is_end = false; } else // / { ungetc(c, fin); state = START; token->token_index = save_token(buffer); token->token_type = O_DIV; return index; } break; case LINE_COMMENT: is_end = true; if (c == '\n') { state = START; } break; case BLOCK_COMMENT: is_end = true; if (c == '*') { state = BLOCK_COMMENT_END; } break; case BLOCK_COMMENT_END: if (c == '/') { state = START; is_end = true; } else state = BLOCK_COMMENT; break; case O_EQUALS: if (c == '=') // == { token->token_index = save_token(buffer); token->token_type = O_EQUALS; state = START; return index; break; } else // = { ungetc(c, fin); state = START; token->token_index = save_token(buffer); token->token_type = O_ASSIGN; return index; break; } case O_G: if (c == '=') // >= { token->token_index = save_token(buffer); token->token_type = O_GE; state = START; return index; break; } else if (c == '>') // >> { token->token_index = save_token(buffer); token->token_type = O_RIGHT_ARROW; state = START; return index; break; } else // > { ungetc(c, fin); token->token_index = save_token(buffer); token->token_type = O_G; state = START; return index; break; } case O_L: if (c == '=') // <= { token->token_index = save_token(buffer); token->token_type = O_LE; state = START; return index; break; } else if (c == '<') // << { token->token_index = save_token(buffer); token->token_type = O_LEFT_ARROW; state = START; return index; break; } else // < { ungetc(c, fin); token->token_index = save_token(buffer); token->token_type = O_L; state = START; return index; break; } case UO_EXCLAMATION: if (c == '=') // != { token->token_index = save_token(buffer); token->token_type = O_NE; state = START; return index; break; } else // ! je zatial errort { ungetc(c, fin); token->token_index = save_token(buffer); token->token_type = ERRORT; // token->token_type = UO_EXCLAMATION; state = START; return index; break; } case IDENTIFIER: if ((c > 64 && c < 91) || (c > 96 && c < 123) || (c > 47 && c < 58) || c == '_') { // (A-Z, a-z, 0-9, _) catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); is_end = false; } else if (SEPARATOR) { token->token_index = save_token(buffer); if (!wrong_identifier) token->token_type = reservedWord(load_token(buffer, token->token_index)); else token->token_type = ERRORT; wrong_identifier = false; is_number_after_dot = false; is_number_after_sign = false; ungetc(c,fin); state = START; return index; } else { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); wrong_identifier = true; is_end = false; } break; case L_INT: if (c > 47 && c < 58) // 0-9 { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); is_end = false; } else if (c == 46) // c == "." { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); state = L_DOUBLE; is_end = false; } else if (SEPARATOR) { token->token_index = save_token(buffer); token->token_type = L_INT; ungetc(c,fin); state = START; return index; } else if (c == 'e' || c == 'E') { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); state = SCIENTIFIC; is_end = false; } else { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); wrong_identifier = true; state = IDENTIFIER; is_end = false; } break; case L_DOUBLE: if (c > 47 && c < 58) // 0-9 { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); is_number_after_dot = true; is_end = false; } else if ((SEPARATOR) && is_number_after_dot) { token->token_type = L_DOUBLE; token->token_index = save_token(buffer); ungetc(c,fin); state = START; return index; } else if ((SEPARATOR) && !is_number_after_dot) { token->token_type = ERRORT; token->token_index = save_token(buffer); ungetc(c,fin); state = START; return index; } else if ((c == 'e' || c == 'E') && is_number_after_dot) { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); state = SCIENTIFIC; is_end = false; } else { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); wrong_identifier = true; state = IDENTIFIER; is_end = false; } break; case SCIENTIFIC: if ((c == '+' || c == '-') && !signed_scientific && !is_number_after_sign) { signed_scientific = true; catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); state = SCIENTIFIC; is_end = false; } else if (c > 47 && c < 58) { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); is_number_after_sign = true; is_end = false; } else if ((SEPARATOR) && is_number_after_sign) { token->token_type = L_DOUBLE; token->token_index = save_token(buffer); ungetc(c,fin); state = START; return index; } else { // catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); wrong_identifier = true; state = IDENTIFIER; is_end = false; ungetc(c, fin); } break; case L_STRING: if (c == '"') { token->token_type = L_STRING; token->token_index = save_token(buffer); state = START; return index; } else if (c == '\\') { // catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); state = L_STRING_BACKSLASH; is_end = false; } else { catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); is_end = false; } break; case L_STRING_BACKSLASH: switch(c) { case 'n': catch_token_internal_error(add_char(buffer, '\n'), INTERNAL_ERROR, token, index); state = L_STRING; is_end = false; break; case 't': catch_token_internal_error(add_char(buffer, '\t'), INTERNAL_ERROR, token, index); state = L_STRING; is_end = false; break; case '"': catch_token_internal_error(add_char(buffer, '"'), INTERNAL_ERROR, token, index); state = L_STRING; is_end = false; break; case '\\': catch_token_internal_error(add_char(buffer, '\\'), INTERNAL_ERROR, token, index); state = L_STRING; is_end = false; break; case 'x': hx[0] = fgetc(fin); hx[1] = fgetc(fin); x = (char)(int)strtol(hx, NULL, 16); if (strcmp(&x, "")) { catch_token_internal_error(add_char(buffer, x), INTERNAL_ERROR, token, index); state = L_STRING; break; } default: token->token_type = ERRORT; token->token_index = save_token(buffer); ungetc(c,fin); state = START; return index; } // catch_token_internal_error(add_char(buffer, c), INTERNAL_ERROR, token, index); state = L_STRING; break; } // switch(state) } // while(1) return 0; }