Ejemplo n.º 1
0
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));
}
Ejemplo n.º 2
0
int TScanContext::identifierOrReserved(bool reserved)
{
    if (reserved) {
        reservedWord();

        return 0;
    }

    if (parseContext.forwardCompatible)
        parseContext.warn(loc, "using future reserved keyword", tokenText, "");

    return identifierOrType();
}
Ejemplo n.º 3
0
// 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;
}
Ejemplo n.º 4
0
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();
}
Ejemplo n.º 5
0
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();
}
Ejemplo n.º 6
0
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();
}
Ejemplo n.º 7
0
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;
    }
}
Ejemplo n.º 8
0
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;
    }
}
Ejemplo n.º 9
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;
}