#pragma once


#define WINDOWS

#include <stdio.h>
//#include <math.h>	// for atof
#include <string>

//#include "LICAnalyzer.h"

#ifndef	WINDOWS
#include <unistd.h>
#include <stdlib.h>
#endif

#include "LVariableItem.h"
#include "LVarContainer.h"
#include <ctype.h>

#define JUDGEMENT_PERCENTAGE		(0.75)
#define FILE_READ_SIZE				512

#define MAX_INT_VALUE				(2147483647*JUDGEMENT_PERCENTAGE)
#define MIN_INT_VALUE				((-2147483647)*JUDGEMENT_PERCENTAGE)
#define MAX_UNSIGNED_INT_VALUE		(4294967295*JUDGEMENT_PERCENTAGE)
#define MIN_UNSIGNED_INT_VALUE		0
#define MAX_CHAR_VALUE				(127*JUDGEMENT_PERCENTAGE)			// signed char in linux
#define MIN_CHAR_VALUE				((-127)*JUDGEMENT_PERCENTAGE)
#define MAX_UNSIGNED_CHAR_VALUE		(255*JUDGEMENT_PERCENTAGE)
#define MIN_UNSIGNED_CHAR_VALUE		0
#define MAX_SHORT_VALUE				(32768*JUDGEMENT_PERCENTAGE)
#define MIN_SHORT_VALUE				((-32768)*JUDGEMENT_PERCENTAGE)
#define MAX_UNSIGNED_SHORT_VALUE	(65535*JUDGEMENT_PERCENTAGE)
#define MIN_UNSIGNED_SHORT_VALUE	0

#define MAX_LONG_VALUE				MAX_INT_VALUE
#define MIN_LONG_VALUE				MIN_INT_VALUE
#define MAX_UNSIGNED_LONG_VALUE		MAX_UNSIGNED_INT_VALUE
#define MIN_UNSIGNED_LONG_VALUE		0

#define MAX_FLOAT_VALUE				((3.4E+38)*JUDGEMENT_PERCENTAGE)
#define MIN_FLOAT_VALUE				((-3.4E+38)*JUDGEMENT_PERCENTAGE)
#define MAX_DOUBLE_VALUE			((1.7E+308)*JUDGEMENT_PERCENTAGE)
#define MIN_DOUBLE_VALUE			((-1.7E+308)*JUDGEMENT_PERCENTAGE)





//Incorrect Calculation

class LICAnalyzer
{
public:
	LVarContainer	m_VarManager;
	stack<string>	m_stackVarValue;
	stack<char>		m_stackOperator;
	stack<char>		m_stackBrace;

	bool			m_bStopAnalyzer;
	FILE*			m_pFile;
	int				m_nFileSize;
	char			m_bufRead[ FILE_READ_SIZE + 1 ];
	char			m_bufTemp[ FILE_READ_SIZE + 1 ];

	int				m_nRead;
	int				m_nLine;

	char*			m_pAllocPoint;
	char*			m_pBraceBegin;
	char*			m_pCharacter;
	char*			m_pSemiColon;
	char*			m_pWord;
	string			m_strWord;
	//string			m_strBuffer;
	
	bool			m_bFirstWord;

public:
	LICAnalyzer();
	~LICAnalyzer();

	void RightTrim(string& strSrc);
	void LeftTrim(string& strSrc);

	int Priority(char cOperator);

	void CheckValue(long long llValue, bool bIsDouble);

	long long Calculate(string strFormula, int nType);
	string Operate(string& strValue1, string& strValue2, char cOperator);
	bool DeclareVar(string& strLine, int nType);
	int ReadFile(string& strBuffer);
	void AnalyzeFile(char* pFileName);
	void AnalyzeFunction(string& strFunction);
	bool ScanVarDeclare(string& strLine);
	

};

LICAnalyzer::LICAnalyzer()
{
	m_bStopAnalyzer = true;
	memset( m_bufRead, 0x00, FILE_READ_SIZE + 1 );
	memset( m_bufTemp, 0x00, FILE_READ_SIZE + 1 );
}
LICAnalyzer::~LICAnalyzer()
{
}

void LICAnalyzer::RightTrim(string& strSrc)
{
	int nIndex = strSrc.find_last_not_of(" \t\n\r");
	if( nIndex != string::npos )
		strSrc.erase( nIndex + 1 );
}

void LICAnalyzer::LeftTrim(string& strSrc)
{
	int nIndex = strSrc.find_first_not_of(" \t\n\r");
	if( nIndex != string::npos )
		strSrc.erase( 0, nIndex );
}

int LICAnalyzer::Priority(char cOperator)
{
	switch( cOperator )
	{
	case '(':
	case ')':
		return 20;
	case '*':
	case '/':
	case '%':
		return 19;
	case '+':
	case '-':
		return 18;
	default:
		return 0;
	}
}

void LICAnalyzer::CheckValue(long long llValue, bool bIsDouble)
{/*
	switch( nType )
	{
		case VAR_TYPE_INT:
		//	TODO here : !!!!!!!!!!!!!!!!!!!!!!!!!!!!
			int nInt ;
		case VAR_TYPE_UNSIGNED_INT:
		case VAR_TYPE_CHAR:
		case VAR_TYPE_UNSIGNED_CHAR:
		case VAR_TYPE_SHORT:
		case VAR_TYPE_UNSIGNED_SHORT:
		case VAR_TYPE_LONG:
		case VAR_TYPE_UNSIGNED_LONG:
		//case VAR_TYPE_LONG_LONG:
		//case VAR_TYPE_UNSIGNED_LONG_LONG:
		case VAR_TYPE_FLOAT:
		case VAR_TYPE_DOUBLE:
			break;
		default:
			break;
	}*/
}

long long LICAnalyzer::Calculate(string strFormula, int nType)
{
	// TODO here : 이 함수 구현
	// 계산도 하고 범위 검사도 한다. 범위가 위험 수치를 넘어서는 경우 경고 루틴 호출

	// ++ -- 구분해야 하고, -음수표현, .들어간 소수표현 도 해야함

	// = 연산자를 사용한 식에서는 ++, -- 를 사용하지 않는 다고 가정

	for( int i = 0; i < strFormula.length() ; i++ )	// 공백 제거
	{
		if( isspace( strFormula[i] ) )
			strFormula.erase( i, 1 );
	}

	LVariableItem *pVarItem;
	string strOperator = "+-*%/();";
	string strWord;
	int nOperatorIndex;
	char cLetter;
	char cOperator;
	
	strFormula += ";";	// 파싱을 위해 임의로 집어넣음

	for( int nPos = 0; nPos < strFormula.length(); nPos++ )
	{
		cLetter = strFormula[ nPos ];

		if( isalpha(cLetter) || cLetter == '_' )	// 변수 이름인 경우 변수값을 읽어서 스택에 저장한다.
		{
			if( string::npos != (nOperatorIndex = strFormula.find_first_of(strOperator)) )
			{
				strWord = strFormula.substr( nPos, nOperatorIndex - nPos );
				if( NULL != (pVarItem = m_VarManager.FindVarItem(strWord)) )
				{
					pVarItem->ValueToStr( strWord );
					m_stackVarValue.push( strWord );	// 변수는 값을 스트링으로 넣는다.
					nPos = nOperatorIndex;
				}
				else
					; //  TODO here : error report ( 선언되지 않은 변수 접근. 클래스나 뭐 이런것일수 있음) 실행중단
			}
			else
				;	// TODO here : error report ( 파싱오류. 소스코드 이상 의심 ). 실행중단
		}
		else if( isdigit(cLetter) )
		{
			if( string::npos != (nOperatorIndex = strFormula.find_first_of(strOperator)) )
			{
				strWord = strFormula.substr( nPos, nOperatorIndex - nPos );
				m_stackVarValue.push( strWord );	// 숫자는 그냥 넣는다.
				nPos = nOperatorIndex;
			}
			else
				;	// TODO here : error report ( 파싱오류. 소스코드 이상 의심 ). 실행중단
		}
		else if( cLetter == '-' )
		{
			if( nOperatorIndex == 0 || (isalpha(strFormula[nOperatorIndex-1]) || isdigit(strFormula[nOperatorIndex-1])) )
			{
				nPos++;
				cLetter = strFormula[ nPos ];

				if( isalpha(cLetter) || cLetter == '_' )	// 뒤에 나오는 변수값의 부호를 바꿔서 스택에 저장
				{
					if( string::npos != (nOperatorIndex = strFormula.find_first_of(strOperator)) )
					{
						strWord = strFormula.substr( nPos, nOperatorIndex - nPos );
						if( NULL != (pVarItem = m_VarManager.FindVarItem(strWord)) )
						{
							pVarItem->ValueToStr( strWord );
							if( strWord[ 0 ] == '-' )	// 부호를 바꿈
								strWord.erase( 0, 1 );
							else
								strWord = ("-" + strWord);
							m_stackVarValue.push( strWord );
							nPos = nOperatorIndex;
						}
						else
							; //  TODO here : error report ( 선언되지 않은 변수 접근. 클래스나 뭐 이런것일수 있음) 실행중단
					}
					else
						;	// TODO here : error report ( 파싱오류. 소스코드 이상 의심 ). 실행중단
				}
				else if( isdigit(cLetter) )	// 뒤에 나오는 숫자의 부호를 바꿔서 스택에 저장
				{
					if( string::npos != (nOperatorIndex = strFormula.find_first_of(strOperator)) )
					{
						strWord = strFormula.substr( nPos, nOperatorIndex - nPos );
						if( strWord[ 0 ] == '-' )	// 부호를 바꿈
							strWord.erase( 0, 1 );
						else
							strWord = ("-" + strWord);
						m_stackVarValue.push( strWord );
						nPos = nOperatorIndex;
					}
					else
						;	// TODO here : error report ( 파싱오류. 소스코드 이상 의심 ). 실행중단
				}
				else
					;	// TODO here : error report ( 파싱오류. 소스코드 이상 의심 ). 실행중단
			}
			else	// 그냥 빼기 연산자인 경우
			{
				m_stackOperator.push( '-' );
			}
		}// end == '-'
		else if( cLetter == ')' )	// ( 가 나올때 까지 팝하여 계산하여 다시 푸쉬
		{
			while( m_stackOperator.top() != '(' )
			{
				cLetter = m_stackOperator.top();
				m_stackOperator.pop();
				strWord = m_stackVarValue.top();
				m_stackVarValue.pop();
				strWord = Operate( m_stackVarValue.top(), strWord, cLetter );
				m_stackVarValue.pop();
				m_stackVarValue.push( strWord );
			}
			m_stackOperator.pop();
		}
		else	// 그외에 operator 인 경우
		{
			if( m_stackOperator.empty() )
				m_stackOperator.push( cLetter );
			else
			{
				if( Priority( m_stackOperator.top() ) < Priority( cLetter ) )
				{
					// 스택에 숫자 하나 꺼내고. 지금 연산자 다음 숫자를 이번연산자로 계산하여 스택에 푸쉬
				}
				else
					m_stackOperator.push( cLetter );
			}
		}

	}// end for( nPos++ )
	
	// 숫자와 연산자를 스택에서 꺼내어 계산시작
	while( m_stackOperator.empty() == false )
	{
		cLetter = m_stackOperator.top();
		m_stackOperator.pop();
		strWord = m_stackVarValue.top();
		m_stackVarValue.pop();
		strWord = Operate( m_stackVarValue.top(), strWord, cLetter );
		m_stackVarValue.pop();
		m_stackVarValue.push( strWord );
	}

	strWord = m_stackVarValue.top();
	m_stackVarValue.pop();

	// TODO here : 마지막 결과값과 변수형의 최대 표현 범위와 비교
	

	if( string::npos != strWord.find(".") )
	{
		double dbResult = atof( strWord.c_str() );
		switch( nType )
		{
			case VAR_TYPE_INT:
				if( dbResult > MAX_INT_VALUE || dbResult < MIN_INT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_INT:
				if( dbResult > MAX_UNSIGNED_INT_VALUE || dbResult < MIN_UNSIGNED_INT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_CHAR:
				if( dbResult > MAX_CHAR_VALUE || dbResult < MIN_CHAR_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_CHAR:
				if( dbResult > MAX_UNSIGNED_CHAR_VALUE || dbResult < MIN_UNSIGNED_CHAR_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_SHORT:
				if( dbResult > MAX_SHORT_VALUE || dbResult < MIN_SHORT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_SHORT:
				if( dbResult > MAX_UNSIGNED_SHORT_VALUE || dbResult < MIN_UNSIGNED_SHORT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_LONG:
				if( dbResult > MAX_LONG_VALUE || dbResult < MIN_LONG_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_LONG:
				if( dbResult > MAX_UNSIGNED_LONG_VALUE || dbResult < MIN_UNSIGNED_LONG_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			//case VAR_TYPE_LONG_LONG:
			//case VAR_TYPE_UNSIGNED_LONG_LONG:
			case VAR_TYPE_FLOAT:
				if( dbResult > MAX_FLOAT_VALUE || dbResult < MIN_FLOAT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_DOUBLE:
				if( dbResult > MAX_DOUBLE_VALUE || dbResult < MIN_DOUBLE_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			default:
				break;
		}
		return dbResult;
	}
	else
	{
		int nResult = atol( strWord.c_str() );
		switch( nType )
		{
			case VAR_TYPE_INT:
				if( nResult > MAX_INT_VALUE || nResult < MIN_INT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_INT:
				if( nResult > MAX_UNSIGNED_INT_VALUE || nResult < MIN_UNSIGNED_INT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_CHAR:
				if( nResult > MAX_CHAR_VALUE || nResult < MIN_CHAR_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_CHAR:
				if( nResult > MAX_UNSIGNED_CHAR_VALUE || nResult < MIN_UNSIGNED_CHAR_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_SHORT:
				if( nResult > MAX_SHORT_VALUE || nResult < MIN_SHORT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_SHORT:
				if( nResult > MAX_UNSIGNED_SHORT_VALUE || nResult < MIN_UNSIGNED_SHORT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_LONG:
				if( nResult > MAX_LONG_VALUE || nResult < MIN_LONG_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_UNSIGNED_LONG:
				if( nResult > MAX_UNSIGNED_LONG_VALUE || nResult < MIN_UNSIGNED_LONG_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			//case VAR_TYPE_LONG_LONG:
			//case VAR_TYPE_UNSIGNED_LONG_LONG:
			case VAR_TYPE_FLOAT:
				if( nResult > MAX_FLOAT_VALUE || nResult < MIN_FLOAT_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			case VAR_TYPE_DOUBLE:
				if( nResult > MAX_DOUBLE_VALUE || nResult < MIN_DOUBLE_VALUE )
					printf("line : %d\n", m_nLine);// TODO here : 변수 위험범위 보고
				break;
			default:
				break;
		}
		return nResult;
	}
}

string LICAnalyzer::Operate(string& strValue1, string& strValue2, char cOperator)
{
	bool bIsDouble1 = false, bIsDouble2 = false;
	long long llValue1=0, llValue2=0;
	double	dbValue1=0, dbValue2=0;

	if( string::npos != strValue1.find(".") )
	{
		dbValue1 = atof( strValue1.c_str() );
		bIsDouble1 = true;
	}
	else
	{
		llValue1 = atol( strValue1.c_str() );
	}

	if( string::npos != strValue2.find(".") )
	{
		dbValue2 = atof( strValue2.c_str() );
		bIsDouble2 = true;
	}
	else
	{
		llValue2 = atol( strValue2.c_str() );
	}

	char buf[30];
	memset( buf, 0x00, 30 );
	string strResult;

	if( bIsDouble1 || bIsDouble2 )
	{
		dbValue1 = llValue1 + dbValue1;
		dbValue2 = llValue2 + dbValue2;

		switch( cOperator )
		{
		case '+':
			strResult = gcvt( dbValue1 + dbValue2, 20, buf );
			break;
		case '-':
			strResult = gcvt( dbValue1 - dbValue2, 20, buf );
			break;
		case '*':
			strResult = gcvt( dbValue1 * dbValue2, 20, buf );
			break;
		case '/':
			strResult = gcvt( dbValue1 / dbValue2, 20, buf );
			break;
		case '%':
			strResult = gcvt( (long)dbValue1 % (long)dbValue2, 20, buf );
			break;
		default:
			break;
		}
	}
	else
	{
		switch( cOperator )
		{
		case '+':
			strResult = itoa( llValue1 + llValue2, buf, 10 );
			break;
		case '-':
			strResult = itoa( llValue1 - llValue2, buf, 10 );
			break;
		case '*':
			strResult = itoa( llValue1 * llValue2, buf, 10 );
			break;
		case '/':
			strResult = itoa( llValue1 / llValue2, buf, 10 );
			break;
		case '%':
			strResult = itoa( llValue1 % llValue2, buf, 10 );
			break;
		default:
			break;
		}
	}	

	return strResult;	
}

bool LICAnalyzer::DeclareVar(string& strLine, int nType)
{
	int nBeginIndex;
	int nEndIndex;
	int nTokenIndex;
	string strSpace = " \t\n\r";
	string strDeclareToken = ",;";
	//char cToken;
	string strOne;
	string strVar;
	long long llValue;

	// 왼쪽 공백 삭제
	//nBeginIndex = strLine.find_first_not_of( strSpace );
	//strLine.erase( 0, nBeginIndex - 1 );
	LeftTrim( strLine );
	nBeginIndex = 0;

	while( string::npos != (nEndIndex = strLine.find_first_of(strDeclareToken)) )
	{
		strOne = strLine.substr( 0, nEndIndex );	// 변수 선언 하나를 뽑아냄. 토큰은 제외

		if( string::npos != (nTokenIndex = strOne.find( "=" )) )
		{
			strVar = strOne.substr( 0, nTokenIndex );	// 변수 이름
			LeftTrim( strVar );
			RightTrim( strVar );
			strOne.erase( 0, nTokenIndex );	// 변수에 들어갈 식만 남기고 =까지 삭제
			llValue = Calculate( strOne, nType );	// 계산. ★ 여기서 위험성 검사 ; 제외되어 전달
			m_VarManager.PushVarItem( strVar, nType, llValue );
		}
		else
		{
			int nSpaceIndex;
			if( string::npos != (nSpaceIndex = strOne.find_first_of(strSpace)) )
				strVar = strOne.substr( 0, nSpaceIndex );		// 왼쪽 공백삭제
			else
				strVar = strOne;

			m_VarManager.PushVarItem( strVar, nType );
		}

		strLine = strLine.erase( 0, nEndIndex );
		
		// 왼쪽 공백 삭제
		//if( string::npos != (nBeginIndex = strLine.find_first_of(strSpace)) )
		//	strLine.erase( 0, nBeginIndex - 1 );
		LeftTrim( strLine );
	}

	return true;

}

bool LICAnalyzer::ScanVarDeclare(string& strLine)
{
	// ;이 빠진 한줄을 처리한다.
	int nIndex;
	
	if( string::npos != (nIndex = strLine.find( "unsigned int" )) )
	{
		nIndex = nIndex + strlen("unsigned int");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_UNSIGNED_INT );			
		}
	}	
	if( string::npos != (nIndex = strLine.find( "signed int" )) )
	{
		nIndex = nIndex + strlen("signed int");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_SIGNED_INT );			
		}
	}	
	if( string::npos != (nIndex = strLine.find( "signed char" )) )
	{
		nIndex = nIndex + strlen("signed char");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_SIGNED_CHAR );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "short int" )) )
	{
		nIndex = nIndex + strlen("short int");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_SHORT_INT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "unsigned short" )) )
	{
		nIndex = nIndex + strlen("unsigned short");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_UNSIGNED_SHORT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "signed short" )) )
	{
		nIndex = nIndex + strlen("signed short");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_SIGNED_SHORT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "long int" )) )
	{
		nIndex = nIndex + strlen("long int");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_LONG_INT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "unsigned long" )) )
	{
		nIndex = nIndex + strlen("unsigned long");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_UNSIGNED_LONG );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "signed long" )) )
	{
		nIndex = nIndex + strlen("signed long");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_SIGNED_LONG );			
		}
	}
	//if( string::npos != (nIndex = strLine.find( "long long" )) )
	//{
	//	nIndex = nIndex + strlen("long long");
	//	if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
	//	{
	//		strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
	//		return DeclareVar( strLine, VAR_TYPE_LONG_LONG );			
	//	}
	//}
	//if( string::npos != (nIndex = strLine.find( "unsigned long long" )) )
	//{
	//	nIndex = nIndex + strlen("unsigned long long");
	//	if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
	//	{
	//		strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
	//		return DeclareVar( strLine, VAR_TYPE_UNSIGNED_LONG_LONG );			
	//	}
	//}
	if( string::npos != (nIndex = strLine.find( "long double" )) )
	{
		nIndex = nIndex + strlen("long double");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_LONG_DOUBLE );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "float" )) )
	{
		nIndex = nIndex + strlen("float");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_FLOAT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "double" )) )
	{
		nIndex = nIndex + strlen("double");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_DOUBLE );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "int" )) )
	{
		nIndex = nIndex + strlen("int");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_INT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "char" )) )
	{
		nIndex = nIndex + strlen("char");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_CHAR );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "byte" )) )
	{
		nIndex = nIndex + strlen("byte");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_BYTE );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "short" )) )
	{
		nIndex = nIndex + strlen("short");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_SHORT );			
		}
	}
	if( string::npos != (nIndex = strLine.find( "long" )) )
	{
		nIndex = nIndex + strlen("long");
		if( isspace(strLine[ nIndex ]) )	// 뒤에 공백이 하나 있으면
		{
			strLine = strLine.substr( nIndex + 1 );	// 공백이후글자부터 끝까지
			return DeclareVar( strLine, VAR_TYPE_LONG );			
		}
	}

	return false;
}

int LICAnalyzer::ReadFile(string& strBuffer)
{
	memset( m_bufRead, 0x00, FILE_READ_SIZE + 1 );
	int nRead = fread( m_bufRead, 1, FILE_READ_SIZE, m_pFile );

	if( m_nRead < 0 )
	{
		// TODO here : alarm error
		m_bStopAnalyzer == true;
		return -1;
	}

	m_nRead += nRead;
	strBuffer += m_bufRead;
	return nRead;
}

void LICAnalyzer::AnalyzeFile(char* pFileName)
{
	m_pFile = fopen( pFileName, "r" );
	if( m_pFile == NULL )
	{
		// TODO here : 오류 보고
		printf("Open File failed : %s\n");
		return;
	}
	fseek( m_pFile, 0, SEEK_END );
	m_nFileSize = ftell( m_pFile );
	fseek( m_pFile, 0, SEEK_SET );

	string strBuffer = "";
	m_nLine = 1;
	m_nRead = 0;

	while( true )	// 파일하나를 다 분석할때 까지
	{
		if( m_bStopAnalyzer == true )
			break;

		if( ReadFile( strBuffer ) == false )
			break;

		int nBeginningIndex = 0;
		int nOpenBraceIndex = strBuffer.find( "{" );	// { 를 검색

		if( nOpenBraceIndex == string::npos )	// { 가 없는 경우
		{
			// 줄번호 계산
			while( string::npos != (nBeginningIndex = strBuffer.find("\n", nBeginningIndex)) )
			{
				nBeginningIndex++;
				m_nLine++;				
			}
			strBuffer = "";
			continue;
		}

		// 줄번호 계산
		while( string::npos != (nBeginningIndex = strBuffer.find("\n", nBeginningIndex)) )
		{
			if( nBeginningIndex > nOpenBraceIndex )
				break;

			nBeginningIndex++;
			m_nLine++;
		}

		m_stackBrace.push( '{' );

		int nBraceIndex = nBeginningIndex + 1;
		int nCloseBraceIndex;

		while( m_stackBrace.empty() == false )
		{
			if( string::npos == (nBraceIndex = strBuffer.find_first_of("{}", nBraceIndex)) )
			{
				if( ReadFile( strBuffer ) == false )
				{
					m_bStopAnalyzer = true;
					break;
				}	
			}
			else if( strBuffer[ nBraceIndex ] == '{' )
			{
				m_stackBrace.push( '{' );
				nBraceIndex++;
			}
			else
			{
				m_stackBrace.pop();
				nCloseBraceIndex = nBraceIndex;
				nBraceIndex++;
			}
		}

		if( m_bStopAnalyzer == true )
			break;

		// { + 1 부터 } - 1 까지 스트링만 서브스트링으로 잘라서 검사
		AnalyzeFunction( strBuffer.substr(nOpenBraceIndex + 1, nCloseBraceIndex - nOpenBraceIndex - 1) );

		if( m_bStopAnalyzer == true )
			break;

		strBuffer.erase( 0, nCloseBraceIndex - 1 );

	}// end while
	

	// TODO here : 변수 관리 스택에 내용이 남아있으면 } 이 나오지 않은 것이므로 오류 출력

	fclose( m_pFile );
	
}

void LICAnalyzer::AnalyzeFunction(string& strFunction)
{
	int nBeginningIndex = 0;
	int nSemicolonIndex;

	// 변수선언 부분 검사
	while( string::npos != (nSemicolonIndex = strFunction.find(";")) )
	{
		if( m_bStopAnalyzer == true )
			return;

		// 줄번호 계산
		while( string::npos != (nBeginningIndex = strFunction.find("\n", nBeginningIndex)) )
		{
			if( nBeginningIndex > nSemicolonIndex )
				break;

			nBeginningIndex++;
			m_nLine++;
		}

		// 한줄에 대해 변수 선언부분인지 검사( ;은 제외하고 전달. 맨앞에 공백은 있을 수 있음 )
		if( true == ScanVarDeclare( strFunction.substr( 0, nSemicolonIndex + 1) ) )
			strFunction.erase( 0, nSemicolonIndex - 1 );
		else
			break;

	}

	int nOperatorIndex;
	int nEndLineIndex;	// = 글자가 나오기 바로 이전 \n의 인덱스
	string strVar;
	long long llValue;
	int i;

	// 변수 값 검사
	while( string::npos != (nOperatorIndex = strFunction.find_first_of("=+-")) )
	{
		if( m_bStopAnalyzer == true )
			return;

		nEndLineIndex = 0;

		// 줄번호 계산
		while( string::npos != (nBeginningIndex = strFunction.find("\n", nBeginningIndex)) )
		{
			if( nBeginningIndex > nOperatorIndex )
				break;

			nEndLineIndex = nBeginningIndex;
			nBeginningIndex++;
			m_nLine++;
		}

		if( strFunction[ nOperatorIndex ] == '=' && strFunction[ nOperatorIndex + 1 ] != '=' )	// == 이 아닌지 확인
		{
			for( i = nEndLineIndex + 1; i < nOperatorIndex - 1; i++ )
			{
				if( isalpha(strFunction[ i ]) || strFunction[ i ] == '_' )	// 변수이름인지 확인
				{
					if( string::npos != (nSemicolonIndex = strFunction.find( ";", nOperatorIndex )) )
					{
						// TODO here : ★ 변수이름과  =글자 이후 값을 계산하여 값이 위험범위가 아닌지 검사
						// 등록된 변수이름이 아닐경우에는 뭐 클래스 이름일수도 있으므로 그냥 넘어감
						
						strVar = strFunction.substr( i, nOperatorIndex - 2 );
						RightTrim( strVar );
						// 변수 이름이 관리스택에 있으면 Calculate()
						LVariableItem* pVarItem = m_VarManager.FindVarItem( strVar );
						if( NULL != pVarItem )
						{
							// 세미콜론 제외하고 전달
							llValue = Calculate( strFunction.substr(nOperatorIndex, nSemicolonIndex - 2), pVarItem->GetType() );
							m_VarManager.SetVarItem( strVar, llValue );
						}

						break;
					}
					else
					{
						return;	// TODO here : error report : =은 있는데 ;이 없음
					}
				}
			}
			if( i == nOperatorIndex - 1 )
				return;	// TODO here : error report : 이퀄 앞에 변수 이름 없음

			strFunction.erase( 0, nSemicolonIndex - 1 );	// ; 까지 삭제
		}
		else
			strFunction.erase( 0, nOperatorIndex );	// == 까지 삭제

		// TODO here
		/*
		else if( strFunction[ nOperatorIndex ] == '+' && strFunction[ nOperatorIndex + 1 ] == '+' )	// ++ 이 아닌지 확인
		{
		}
		else if( strFunction[ nOperatorIndex ] == '-' && strFunction[ nOperatorIndex + 1 ] == '-' )	// -- 이 아닌지 확인
		{
		}*/
	}
}

