// Tokenizer.cpp #ifndef NOT_USING_MODULES // !!! if you are not using modules, read BELOW !!! #include "Module.h" // if you are not using modules, // create an empty Module.h in your // project -- use of modules allows // the error handler to be overridden // with a custom CErrHandler #endif #include "Tokenizer.h" #pragma warning(disable : 4100) //unreferenced formal parameter #pragma warning(disable : 4127) //conditional expression is constant #pragma warning(disable : 4189) //local variable is initialized but not referenced #pragma warning(disable : 4244) //conversion from x to x, possible loss of data enum { DIR_INCLUDE = TK_USERDEF, DIR_IFDEF, DIR_IFNDEF, DIR_ENDIF, DIR_ELSE, DIR_DEFINE, DIR_UNDEFINE, }; keywordArray_t CTokenizer::directiveKeywords[] = { "include", DIR_INCLUDE, "ifdef", DIR_IFDEF, "ifndef", DIR_IFNDEF, "endif", DIR_ENDIF, "else", DIR_ELSE, "define", DIR_DEFINE, "undefine", DIR_UNDEFINE, "", TK_EOF, }; keywordArray_t CTokenizer::errorMessages[] = { "No Error", TKERR_NONE, "Unknown Error", TKERR_UNKNOWN, "Buffer creation failed", TKERR_BUFFERCREATE, "Unrecognized symbol", TKERR_UNRECOGNIZEDSYMBOL, "Duplicate symbol", TKERR_DUPLICATESYMBOL, "String length exceeded", TKERR_STRINGLENGTHEXCEEDED, "Identifier length exceeded", TKERR_IDENTIFIERLENGTHEXCEEDED, "Expected integer", TKERR_EXPECTED_INTEGER, "Expected identifier", TKERR_EXPECTED_IDENTIFIER, "Expected string", TKERR_EXPECTED_STRING, "Expected char", TKERR_EXPECTED_CHAR, "Expected float", TKERR_EXPECTED_FLOAT, "Unexpected token", TKERR_UNEXPECTED_TOKEN, "Invalid directive", TKERR_INVALID_DIRECTIVE, "Include file not found", TKERR_INCLUDE_FILE_NOTFOUND, "Unmatched directive", TKERR_UNMATCHED_DIRECTIVE, "", TKERR_USERERROR, }; // // CSymbol // CSymbol::CSymbol() { } CSymbol::~CSymbol() { } CSymbol* CSymbol::Create(LPCTSTR symbolName) { CSymbol* retval = new CSymbol(); retval->Init(symbolName); return retval; } LPCTSTR CSymbol::GetName() { if (m_symbolName == NULL) { return ""; } return m_symbolName; } void CSymbol::Init(LPCTSTR symbolName) { m_symbolName = (char*)malloc(strlen(symbolName) + 1); // ASSERT(m_symbolName); strcpy(m_symbolName, symbolName); } void CSymbol::Delete() { if (m_symbolName != NULL) { free(m_symbolName); m_symbolName = NULL; } delete this; } // // CDirectiveSymbol // CDirectiveSymbol::CDirectiveSymbol() { } CDirectiveSymbol::~CDirectiveSymbol() { } CDirectiveSymbol* CDirectiveSymbol::Create(LPCTSTR symbolName) { CDirectiveSymbol* retval = new CDirectiveSymbol(); retval->Init(symbolName); return retval; } void CDirectiveSymbol::Init(LPCTSTR symbolName) { CSymbol::Init(symbolName); m_value = NULL; } void CDirectiveSymbol::Delete() { if (m_value != NULL) { free(m_value); m_value = NULL; } CSymbol::Delete(); } void CDirectiveSymbol::SetValue(LPCTSTR value) { if (m_value != NULL) { free(m_value); } m_value = (char*)malloc(strlen(value) + 1); strcpy(m_value, value); } LPCTSTR CDirectiveSymbol::GetValue() { return m_value; } // // CIntSymbol // CIntSymbol::CIntSymbol() { } CIntSymbol* CIntSymbol::Create(LPCTSTR symbolName, int value) { CIntSymbol* retval = new CIntSymbol(); retval->Init(symbolName, value); return retval; } void CIntSymbol::Delete() { CSymbol::Delete(); } void CIntSymbol::Init(LPCTSTR symbolName, int value) { CSymbol::Init(symbolName); m_value = value; } int CIntSymbol::GetValue() { return m_value; } // // CSymbolTable // CSymbolTable::CSymbolTable() { Init(); } CSymbolTable::~CSymbolTable() { } CSymbolTable* CSymbolTable::Create() { CSymbolTable* retval = new CSymbolTable(); retval->Init(); return retval; } void CSymbolTable::Init() { } void CSymbolTable::DiscardSymbols() { for (symbolmap_t::iterator isymbol = m_symbols.begin(); isymbol != m_symbols.end(); isymbol++) { (*isymbol).second->Delete(); } m_symbols.erase(m_symbols.begin(), m_symbols.end()); } void CSymbolTable::Delete() { DiscardSymbols(); delete this; } bool CSymbolTable::AddSymbol(CSymbol* theSymbol) { LPCTSTR name = theSymbol->GetName(); symbolmap_t::iterator iter = m_symbols.find(name); if (iter != m_symbols.end()) { return false; } m_symbols.insert(symbolmap_t::value_type(name, theSymbol)); return true; } CSymbol* CSymbolTable::FindSymbol(LPCTSTR symbolName) { symbolmap_t::iterator iter = m_symbols.find(symbolName); if (iter != m_symbols.end()) { return (*iter).second; } return NULL; } CSymbol* CSymbolTable::ExtractSymbol(LPCTSTR symbolName) { symbolmap_t::iterator iter = m_symbols.find(symbolName); if (iter != m_symbols.end()) { CSymbol* retval = (*iter).second; m_symbols.erase(iter); } return NULL; } void CSymbolTable::RemoveSymbol(LPCTSTR symbolName) { m_symbols.erase(symbolName); } // // CParseStream // CParseStream::CParseStream() { } CParseStream::~CParseStream() { } CParseStream* CParseStream::Create() { return NULL; } void CParseStream::Delete() { delete this; } bool CParseStream::Init() { m_next = NULL; return true; } bool CParseStream::NextChar(byte& theByte) { return false; } long CParseStream::GetRemainingSize() { return 0; } CParseStream* CParseStream::GetNext() { return m_next; } void CParseStream::SetNext(CParseStream* next) { m_next = next; } int CParseStream::GetCurLine() { return 0; } void CParseStream::GetCurFilename(char** theBuff) { *theBuff = NULL; } bool CParseStream::IsThisDefinition(void* theDefinition) { return false; } // // CParsePutBack // CParsePutBack::CParsePutBack() { } CParsePutBack::~CParsePutBack() { } CParsePutBack* CParsePutBack::Create(byte theByte, int curLine, LPCTSTR filename) { CParsePutBack* curParsePutBack = new CParsePutBack(); curParsePutBack->Init(theByte, curLine, filename); return curParsePutBack; } void CParsePutBack::Delete() { if (m_curFile != NULL) { free(m_curFile); m_curFile = NULL; } delete this; } bool CParsePutBack::NextChar(byte& theByte) { if (m_consumed) { return false; } theByte = m_byte; m_consumed = true; return true; } void CParsePutBack::Init(byte theByte, int curLine, LPCTSTR filename) { CParseStream::Init(); m_consumed = false; m_byte = theByte; m_curLine = curLine; if (filename != NULL) { m_curFile = (char*)malloc(strlen(filename) + 1); strcpy(m_curFile, filename); } else { m_curFile = NULL; } } long CParsePutBack::GetRemainingSize() { if (m_consumed) { return 0; } else { return 1; } } int CParsePutBack::GetCurLine() { return m_curLine; } void CParsePutBack::GetCurFilename(char** theBuff) { if (m_curFile == NULL) { *theBuff = NULL; return; } *theBuff = (char*)malloc(strlen(m_curFile) + 1); strcpy(*theBuff, m_curFile); } // // CParseFile // CParseFile::CParseFile() { } CParseFile::~CParseFile() { } CParseFile* CParseFile::Create() { CParseFile* theParseFile = new CParseFile(); if ( !theParseFile->Init() ) { delete theParseFile; return NULL; } return theParseFile; } CParseFile* CParseFile::Create(LPCTSTR filename, CTokenizer* tokenizer) { CParseFile* theParseFile = new CParseFile(); if ( theParseFile->Init(filename, tokenizer) ) return theParseFile; return NULL; } void CParseFile::Delete() { if (m_buff != NULL) { free(m_buff); m_buff = NULL; } if (m_ownsFile && (m_fileHandle != NULL)) { CloseHandle(m_fileHandle); m_fileHandle = NULL; } if (m_fileName != NULL) { free(m_fileName); m_fileName = NULL; } delete this; } bool CParseFile::Init() { m_fileHandle = NULL; m_buff = NULL; m_ownsFile = false; m_curByte = NULL; m_curLine = 1; m_fileName = NULL; return CParseStream::Init(); } DWORD CParseFile::GetFileSize() { DWORD dwCur = SetFilePointer(m_fileHandle, 0L, NULL, FILE_CURRENT); DWORD dwLen = SetFilePointer(m_fileHandle, 0, NULL, FILE_END); SetFilePointer(m_fileHandle, dwCur, NULL, FILE_BEGIN); return dwLen; } void CParseFile::Read(void* buff, UINT buffsize) { DWORD bytesRead; ReadFile(m_fileHandle, buff, buffsize, &bytesRead, NULL); } bool CParseFile::Init(LPCTSTR filename, CTokenizer* tokenizer) { CParseStream::Init(); m_fileName = (char*)malloc(strlen(filename) + 1); strcpy(m_fileName, filename); DWORD dwAccess = GENERIC_READ; DWORD dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = 0; DWORD dwCreateFlag = OPEN_EXISTING; m_fileHandle = CreateFile(filename, dwAccess, dwShareMode, &sa, dwCreateFlag, FILE_ATTRIBUTE_NORMAL, NULL); if (m_fileHandle == (HANDLE)-1) { tokenizer->Error(TKERR_INCLUDE_FILE_NOTFOUND); Init(); return false; } m_filesize = GetFileSize(); m_buff = (byte*)malloc(m_filesize); if (m_buff == NULL) { tokenizer->Error(TKERR_BUFFERCREATE); Init(); return false; } Read(m_buff, m_filesize); m_curByte = 0; m_curPos = 1; m_ownsFile = true; m_curLine = 1; return true; } long CParseFile::GetRemainingSize() { return m_filesize - m_curByte; } bool CParseFile::NextChar(byte& theByte) { if (m_curByte < m_filesize) { if (m_buff[m_curByte] == '\n') { m_curLine += 1; m_curPos = 1; } else { m_curPos++; } theByte = m_buff[m_curByte++]; return true; } else { return false; } } int CParseFile::GetCurLine() { return m_curLine; } void CParseFile::GetCurFilename(char** theBuff) { *theBuff = NULL; if (m_fileName != NULL) { *theBuff = (char*)malloc(strlen(m_fileName) + 1); strcpy(*theBuff, m_fileName); } } // // CParseMemory // CParseMemory::CParseMemory() { } CParseMemory::~CParseMemory() { } CParseMemory* CParseMemory::Create(byte* data, long datasize) { CParseMemory* curParse = new CParseMemory(); curParse->Init(data, datasize); return curParse; } void CParseMemory::Delete() { delete this; } bool CParseMemory::NextChar(byte& theByte) { if (m_offset < m_datasize) { if (m_data[m_offset] == '\n') { m_curLine += 1; m_curPos = 1; } else { m_curPos++; } theByte = m_data[m_offset++]; return true; } else { return false; } } void CParseMemory::Init(byte* data, long datasize) { m_data = data; m_curLine = 1; m_curPos = 1; m_offset = 0; m_datasize = datasize; } long CParseMemory::GetRemainingSize() { return m_datasize - m_offset; } int CParseMemory::GetCurLine() { return m_curLine; } void CParseMemory::GetCurFilename(char** theBuff) { *theBuff = NULL; } // // CParseBlock // CParseBlock::CParseBlock() { } CParseBlock::~CParseBlock() { } CParseBlock* CParseBlock::Create(byte* data, long datasize) { CParseBlock* curParse = new CParseBlock(); curParse->Init(data, datasize); return curParse; } void CParseBlock::Delete() { if (m_data != NULL) { free(m_data); m_data = NULL; } delete this; } void CParseBlock::Init(byte* data, long datasize) { m_data = (byte*)malloc(datasize); memcpy(m_data, data, datasize); m_curLine = 1; m_curPos = 1; m_offset = 0; m_datasize = datasize; } // // CParseToken // CParseToken::CParseToken() { } CParseToken::~CParseToken() { } CParseToken* CParseToken::Create(CToken* token) { CParseToken* curParse = new CParseToken(); curParse->Init(token); return curParse; } void CParseToken::Delete() { if (m_data != NULL) { free(m_data); m_data = NULL; } delete this; } bool CParseToken::NextChar(byte& theByte) { if (m_offset < m_datasize) { if (m_data[m_offset] == '\n') { m_curLine += 1; m_curPos = 1; } else { m_curPos++; } theByte = m_data[m_offset++]; return true; } else { return false; } } void CParseToken::Init(CToken* token) { LPCTSTR tokenString = token->GetStringValue(); m_datasize = strlen(tokenString); if (m_datasize > 0) { m_data = (byte*) malloc(m_datasize); memcpy(m_data, tokenString, m_datasize); } else { m_data = NULL; } m_curLine = 1; m_curPos = 1; m_offset = 0; token->Delete(); } long CParseToken::GetRemainingSize() { return m_datasize - m_offset; } int CParseToken::GetCurLine() { return m_curLine; } void CParseToken::GetCurFilename(char** theBuff) { *theBuff = NULL; } // // CParseDefine // CParseDefine::CParseDefine() { } CParseDefine::~CParseDefine() { } CParseDefine* CParseDefine::Create(CDirectiveSymbol* definesymbol) { CParseDefine* retval = new CParseDefine(); retval->Init(definesymbol); return retval; } void CParseDefine::Delete() { CParseMemory::Delete(); } void CParseDefine::Init(CDirectiveSymbol* definesymbol) { CParseMemory::Init((byte*)definesymbol->GetValue(), strlen(definesymbol->GetValue())); m_defineSymbol = definesymbol; } bool CParseDefine::IsThisDefinition(void* theDefinition) { return (CDirectiveSymbol*)theDefinition == m_defineSymbol; } // // CToken // CToken::CToken() { } CToken::~CToken() { } CToken* CToken::Create() { CToken* theToken = new CToken(); theToken->Init(); return theToken; } void CToken::Delete() { if (m_string != NULL) { free(m_string); m_string = NULL; } delete this; } void CToken::Init() { m_next = NULL; m_string = NULL; } void CToken::SetNext(CToken* theToken) { m_next = theToken; } CToken* CToken::GetNext() { return m_next; } int CToken::GetType() { return TK_EOF; } int CToken::GetIntValue() { return 0; } LPCTSTR CToken::GetStringValue() { if (m_string == NULL) { return ""; } return m_string; } float CToken::GetFloatValue() { return 0.0; } // // CCharToken // CCharToken::CCharToken() { } CCharToken::~CCharToken() { } CCharToken* CCharToken::Create(byte theByte) { CCharToken* theToken = new CCharToken(); theToken->Init(theByte); return theToken; } void CCharToken::Delete() { CToken::Delete(); } void CCharToken::Init(byte theByte) { CToken::Init(); char charString[10]; switch(theByte) { case '\0': strcpy(charString, "\\0"); break; case '\n': strcpy(charString, "\\n"); break; case '\\': strcpy(charString, "\\\\"); break; case '\'': strcpy(charString, "\\'"); break; case '\?': strcpy(charString, "\\?"); break; case '\a': strcpy(charString, "\\a"); break; case '\b': strcpy(charString, "\\b"); break; case '\f': strcpy(charString, "\\f"); break; case '\r': strcpy(charString, "\\r"); break; case '\t': strcpy(charString, "\\t"); break; case '\v': strcpy(charString, "\\v"); break; default: charString[0] = (char)theByte; charString[1] = '\0'; break; } m_string = (char*)malloc(strlen(charString) + 1); strcpy(m_string, charString); } int CCharToken::GetType() { return TK_CHAR; } // // CStringToken // CStringToken::CStringToken() { } CStringToken::~CStringToken() { } CStringToken* CStringToken::Create(LPCTSTR theString) { CStringToken* theToken = new CStringToken(); theToken->Init(theString); return theToken; } void CStringToken::Delete() { CToken::Delete(); } void CStringToken::Init(LPCTSTR theString) { CToken::Init(); m_string = (char*)malloc(strlen(theString) + 1); // ASSERT(m_string); strcpy(m_string, theString); } int CStringToken::GetType() { return TK_STRING; } // // CIntToken // CIntToken::CIntToken() { } CIntToken::~CIntToken() { } CIntToken* CIntToken::Create(long value) { CIntToken* theToken = new CIntToken(); theToken->Init(value); return theToken; } void CIntToken::Delete() { CToken::Delete(); } void CIntToken::Init(long value) { CToken::Init(); m_value = value; } int CIntToken::GetType() { return TK_INT; } int CIntToken::GetIntValue() { return m_value; } float CIntToken::GetFloatValue() { return (float)m_value; } LPCTSTR CIntToken::GetStringValue() { if (m_string != NULL) { free(m_string); m_string = NULL; } char temp[128]; sprintf(temp, "%d", m_value); m_string = (char*)malloc(strlen(temp) + 1); strcpy(m_string, temp); return m_string; } // // CFloatToken // CFloatToken::CFloatToken() { } CFloatToken::~CFloatToken() { } CFloatToken* CFloatToken::Create(float value) { CFloatToken* theToken = new CFloatToken(); theToken->Init(value); return theToken; } void CFloatToken::Delete() { CToken::Delete(); } void CFloatToken::Init(float value) { CToken::Init(); m_value = value; } int CFloatToken::GetType() { return TK_FLOAT; } float CFloatToken::GetFloatValue() { return m_value; } LPCTSTR CFloatToken::GetStringValue() { if (m_string != NULL) { free(m_string); m_string = NULL; } char temp[128]; sprintf(temp, "%g", m_value); m_string = (char*)malloc(strlen(temp) + 1); strcpy(m_string, temp); return m_string; } // // CIdentifierToken // CIdentifierToken::CIdentifierToken() { } CIdentifierToken::~CIdentifierToken() { } CIdentifierToken* CIdentifierToken::Create(LPCTSTR name) { CIdentifierToken* theToken = new CIdentifierToken(); theToken->Init(name); return theToken; } void CIdentifierToken::Delete() { CToken::Delete(); } void CIdentifierToken::Init(LPCTSTR name) { CToken::Init(); m_string = (char*)malloc(strlen(name) + 1); // ASSERT(m_string); strcpy(m_string, name); } int CIdentifierToken::GetType() { return TK_IDENTIFIER; } // // CCommentToken // CCommentToken::CCommentToken() { } CCommentToken::~CCommentToken() { } CCommentToken* CCommentToken::Create(LPCTSTR name) { CCommentToken* theToken = new CCommentToken(); theToken->Init(name); return theToken; } void CCommentToken::Delete() { CToken::Delete(); } void CCommentToken::Init(LPCTSTR name) { CToken::Init(); m_string = (char*)malloc(strlen(name) + 1); // ASSERT(m_string); strcpy(m_string, name); } int CCommentToken::GetType() { return TK_COMMENT; } // // CUserToken // CUserToken::CUserToken() { } CUserToken::~CUserToken() { } CUserToken* CUserToken::Create(int value, LPCTSTR string) { CUserToken* theToken = new CUserToken(); theToken->Init(value, string); return theToken; } void CUserToken::Delete() { CToken::Delete(); } void CUserToken::Init(int value, LPCTSTR string) { CToken::Init(); m_value = value; m_string = (char*)malloc(strlen(string) + 1); strcpy(m_string, string); } int CUserToken::GetType() { return m_value; } // // CUndefinedToken // CUndefinedToken::CUndefinedToken() { } CUndefinedToken::~CUndefinedToken() { } CUndefinedToken* CUndefinedToken::Create(LPCTSTR string) { CUndefinedToken* theToken = new CUndefinedToken(); theToken->Init(string); return theToken; } void CUndefinedToken::Delete() { CToken::Delete(); } void CUndefinedToken::Init(LPCTSTR string) { CToken::Init(); m_string = (char*)malloc(strlen(string) + 1); strcpy(m_string, string); } int CUndefinedToken::GetType() { return TK_UNDEFINED; } // // CTokenizerState // CTokenizerState::CTokenizerState() { } CTokenizerState::~CTokenizerState() { } CTokenizerState* CTokenizerState::Create(bool skip) { CTokenizerState* retval = new CTokenizerState(); retval->Init(skip); return retval; } void CTokenizerState::Init(bool skip) { m_next = NULL; m_skip = skip; m_elseHit = false; } void CTokenizerState::Delete() { delete this; } CTokenizerState* CTokenizerState::GetNext() { return m_next; } bool CTokenizerState::ProcessElse() { if (!m_elseHit) { m_elseHit = true; m_skip = !m_skip; } return m_elseHit; } void CTokenizerState::SetNext(CTokenizerState* next) { m_next = next; } bool CTokenizerState::Skipping() { return m_skip; } // // CTokenizerHolderState // CTokenizerHolderState::CTokenizerHolderState() { } CTokenizerHolderState::~CTokenizerHolderState() { } CTokenizerHolderState* CTokenizerHolderState::Create() { CTokenizerHolderState* retval = new CTokenizerHolderState(); retval->Init(); return retval; } void CTokenizerHolderState::Init() { CTokenizerState::Init(true); } void CTokenizerHolderState::Delete() { delete this; } bool CTokenizerHolderState::ProcessElse() { if (!m_elseHit) { m_elseHit = true; } return m_elseHit; } // // CKeywordTable // CKeywordTable::CKeywordTable(CTokenizer* tokenizer, keywordArray_t* keywords) { m_tokenizer = tokenizer; m_holdKeywords = tokenizer->SetKeywords(keywords); } CKeywordTable::~CKeywordTable() { m_tokenizer->SetKeywords(m_holdKeywords); } // // CTokenizer // CTokenizer::CTokenizer() { } CTokenizer::~CTokenizer() { } CTokenizer* CTokenizer::Create(UINT dwFlags) { CTokenizer* theTokenizer = new CTokenizer(); theTokenizer->Init(dwFlags); return theTokenizer; } void CTokenizer::Delete() { while (m_curParseStream != NULL) { CParseStream* curStream = m_curParseStream; m_curParseStream = curStream->GetNext(); curStream->Delete(); } if (m_symbolLookup != NULL) { m_symbolLookup->Delete(); m_symbolLookup = NULL; } while (m_nextToken != NULL) { CToken* curToken = m_nextToken; m_nextToken = curToken->GetNext(); curToken->Delete(); } while (m_state != NULL) { Error(TKERR_UNMATCHED_DIRECTIVE); CTokenizerState* curState = m_state; m_state = curState->GetNext(); curState->Delete(); } /* if (m_lastErrMsg != NULL) { free(m_lastErrMsg); m_lastErrMsg = NULL; }*/ delete this; } void CTokenizer::Error(int theError) { char errString[128]; char lookupstring[128]; int i = 0; while ((errorMessages[i].m_tokenvalue != TKERR_USERERROR) && (errorMessages[i].m_tokenvalue != theError)) { i++; } if ((errorMessages[i].m_tokenvalue == TKERR_USERERROR) && (m_errors != NULL)) { i = 0; while ((m_errors[i].m_tokenvalue != TK_EOF) && (m_errors[i].m_tokenvalue != theError)) { i++; } strcpy(lookupstring, m_errors[i].m_keyword); } else { strcpy(lookupstring, errorMessages[i].m_keyword); } sprintf(errString, "Error -- %d, %s", theError, lookupstring); Error(errString, theError); } void CTokenizer::Error(int theError, LPCTSTR errString) { char errstring[128]; char lookupstring[128]; int i = 0; while ((errorMessages[i].m_tokenvalue != TKERR_USERERROR) && (errorMessages[i].m_tokenvalue != theError)) { i++; } if ((errorMessages[i].m_tokenvalue == TKERR_USERERROR) && (m_errors != NULL)) { i = 0; while ((m_errors[i].m_tokenvalue != TK_EOF) && (m_errors[i].m_tokenvalue != theError)) { i++; } strcpy(lookupstring, m_errors[i].m_keyword); } else { strcpy(lookupstring, errorMessages[i].m_keyword); } sprintf(errstring, "Error -- %d, %s - %s", theError, lookupstring, errString); Error(errstring, theError); } void CTokenizer::Error(LPCTSTR errString, int theError) { if (m_errorProc != NULL) { m_errorProc(errString); } #ifdef USES_MODULES else { ReportError(theError, errString); } #endif } bool CTokenizer::AddParseFile(LPCTSTR filename) { CParseStream* newStream = CParseFile::Create(filename, this); if ( newStream != NULL ) { newStream->SetNext(m_curParseStream); m_curParseStream = newStream; return true; } return false; } void CTokenizer::AddParseStream(byte* data, long datasize) { CParseStream* newStream = CParseMemory::Create(data, datasize); newStream->SetNext(m_curParseStream); m_curParseStream = newStream; } long CTokenizer::GetRemainingSize() { long retval = 0; CParseStream* curStream = m_curParseStream; while (curStream != NULL) { retval += curStream->GetRemainingSize(); curStream = curStream->GetNext(); } return retval; } LPCTSTR CTokenizer::LookupToken(int tokenID, keywordArray_t* theTable) { if (theTable == NULL) { theTable = m_keywords; } if (theTable == NULL) { return NULL; } int i = 0; while (theTable[i].m_tokenvalue != TK_EOF) { if (theTable[i].m_tokenvalue == tokenID) { return theTable[i].m_keyword; } i++; } return NULL; } void CTokenizer::PutBackToken(CToken* theToken, bool commented, LPCTSTR addedChars, bool bIgnoreThisTokenType) { if (commented) { CParseToken* newStream = CParseToken::Create(theToken); newStream->SetNext(m_curParseStream); m_curParseStream = newStream; if (addedChars != NULL) { CParsePutBack* spacer = CParsePutBack::Create(' ', 0, NULL); spacer->SetNext(m_curParseStream); m_curParseStream = spacer; CParseBlock* newBlock = CParseBlock::Create((byte*)addedChars, strlen(addedChars)); newBlock->SetNext(m_curParseStream); m_curParseStream = newBlock; } char temp[] = "// * "; CParseBlock* newBlock = CParseBlock::Create((byte*)temp, strlen(temp)); newBlock->SetNext(m_curParseStream); m_curParseStream = newBlock; return; } switch(theToken->GetType()) { case TK_INT: case TK_EOF: case TK_UNDEFINED: case TK_FLOAT: case TK_CHAR: case TK_STRING: case TK_EOL: case TK_COMMENT: if (!bIgnoreThisTokenType) { theToken->SetNext(m_nextToken); m_nextToken = theToken; break; } default: CParseToken* newStream = CParseToken::Create(theToken); newStream->SetNext(m_curParseStream); m_curParseStream = newStream; break; } if (addedChars != NULL) { CParseBlock* newBlock = CParseBlock::Create((byte*)addedChars, strlen(addedChars)); newBlock->SetNext(m_curParseStream); m_curParseStream = newBlock; } } CToken* CTokenizer::GetToken(keywordArray_t* keywords, UINT onFlags, UINT offFlags) { keywordArray_t* holdKeywords = SetKeywords(keywords); CToken* retval = GetToken(onFlags, offFlags); SetKeywords(holdKeywords); return retval; } CToken* CTokenizer::GetToken(UINT onFlags, UINT offFlags) { UINT holdFlags = m_flags; m_flags |= onFlags; m_flags &= (~offFlags); CToken* theToken = NULL; while (theToken == NULL) { theToken = FetchToken(); if (theToken == NULL) { continue; } if (theToken->GetType() == TK_EOF) { break; } if (m_state != NULL) { if (m_state->Skipping()) { theToken->Delete(); theToken = NULL; } } } m_flags = holdFlags; return theToken; } CToken* CTokenizer::GetToEndOfLine(int tokenType) { // update, if you just want the whole line returned as a string, then allow a much bigger size than // the default string size of only 128 chars... // if (tokenType == TK_STRING) { #define iRETURN_STRING_SIZE 2048 char theString[iRETURN_STRING_SIZE]; theString[0] = ' '; for (int i = 1; i < iRETURN_STRING_SIZE; i++) { if (NextChar((byte&)theString[i])) { if (theString[i] != '\n') { continue; } PutBackChar(theString[i]); } theString[i] = '\0'; return CStringToken::Create(theString); } // line would maks a string too big to fit in buffer... // Error(TKERR_STRINGLENGTHEXCEEDED); } else { char theString[MAX_IDENTIFIER_LENGTH]; theString[0] = ' '; while (theString[0] == ' ') { if (!NextChar((byte&)theString[0])) { return NULL; } } for (int i = 1; i < MAX_IDENTIFIER_LENGTH; i++) { if (NextChar((byte&)theString[i])) { if (theString[i] != '\n') { continue; } PutBackChar(theString[i]); } theString[i] = '\0'; switch(tokenType) { case TK_COMMENT: return CCommentToken::Create(theString); case TK_IDENTIFIER: default: return CIdentifierToken::Create(theString); } } Error(TKERR_IDENTIFIERLENGTHEXCEEDED); } return NULL; } void CTokenizer::SkipToLineEnd() { byte theByte; while(NextChar(theByte)) { if (theByte == '\n') { break; } } } CToken* CTokenizer::FetchToken() { if (m_nextToken != NULL) { CToken* curToken = m_nextToken; m_nextToken = curToken->GetNext(); curToken->SetNext(NULL); return curToken; } byte theByte; CToken* theToken = NULL; while (true) { if (!NextChar(theByte)) { return CToken::Create(); } if (theByte <= ' ') { if ((theByte == '\n') && ((TKF_USES_EOL & m_flags) != 0)) { return CUserToken::Create(TK_EOL, "-EOLN-"); } continue; } switch(theByte) { case '#': if ((m_flags & TKF_IGNOREDIRECTIVES) == 0) { theToken = HandleDirective(); } else { if ((m_flags & TKF_NODIRECTIVES) != 0) { return HandleSymbol('#'); } SkipToLineEnd(); } break; case '/': theToken = HandleSlash(); break; case '"': theToken = HandleString(); break; case '\'': theToken = HandleQuote(); break; default: if (((theByte >= 'a') && (theByte <= 'z')) || ((theByte >= 'A') && (theByte <= 'Z')) || ((theByte == '_') && ((m_flags & TKF_NOUNDERSCOREINIDENTIFIER) == 0))) { theToken = HandleIdentifier(theByte); } else if (((m_flags & TKF_NUMERICIDENTIFIERSTART) != 0) && (theByte >= '0') && (theByte <= '9')) { theToken = HandleIdentifier(theByte); } else if (((theByte >= '0') && (theByte <= '9')) || (theByte == '-')) { theToken = HandleNumeric(theByte); } else if (theByte == '.') { theToken = HandleDecimal(); } else if (theByte <= ' ') { break; } else { theToken = HandleSymbol(theByte); } } if (theToken != NULL) { return theToken; } } } bool CTokenizer::NextChar(byte& theByte) { while (m_curParseStream != NULL) { if (m_curParseStream->NextChar(theByte)) { return true; } CParseStream* curParseStream = m_curParseStream; m_curParseStream = curParseStream->GetNext(); curParseStream->Delete(); } return false; } bool CTokenizer::RequireToken(int tokenType) { CToken* theToken = GetToken(); bool retValue = theToken->GetType() == tokenType; theToken->Delete(); return retValue; } void CTokenizer::ScanUntilToken(int tokenType) { CToken* curToken; int tokenValue = TK_UNDEFINED; while (tokenValue != tokenType) { curToken = GetToken(); tokenValue = curToken->GetType(); if (tokenValue == TK_EOF) { PutBackToken(curToken); break; } if (tokenValue == tokenType) { PutBackToken(curToken); } else { curToken->Delete(); } } } void CTokenizer::Init(UINT dwFlags) { m_symbolLookup = NULL; m_nextToken = NULL; m_curParseStream = NULL; m_keywords = NULL; m_symbols = NULL; m_errors = NULL; m_state = NULL; m_flags = dwFlags; m_errorProc = NULL; } void CTokenizer::SetErrorProc(LPTokenizerErrorProc errorProc) { m_errorProc = errorProc; } void CTokenizer::SetAdditionalErrors(keywordArray_t* theErrors) { m_errors = theErrors; } keywordArray_t* CTokenizer::SetKeywords(keywordArray_t* theKeywords) { keywordArray_t* retval = m_keywords; m_keywords = theKeywords; return retval; } void CTokenizer::SetSymbols(keywordArray_t* theSymbols) { m_symbols = theSymbols; if (m_symbolLookup != NULL) { m_symbolLookup->Delete(); m_symbolLookup = NULL; } int i = 0; if (theSymbols == NULL) { return; } while(theSymbols[i].m_tokenvalue != TK_EOF) { InsertSymbol(theSymbols[i].m_keyword, theSymbols[i].m_tokenvalue); i++; } } void CTokenizer::InsertSymbol(LPCTSTR theSymbol, int theValue) { CSymbolLookup** curHead = &m_symbolLookup; CSymbolLookup* curParent = NULL; CSymbolLookup* curLookup = NULL; for (UINT i = 0; i < strlen(theSymbol); i++) { bool found = false; curLookup = *curHead; while (curLookup != NULL) { if (curLookup->GetByte() == theSymbol[i]) { found = true; break; } curLookup = curLookup->GetNext(); } if (!found) { curLookup = CSymbolLookup::Create(theSymbol[i]); curLookup->SetParent(curParent); curLookup->SetNext(*curHead); *curHead = curLookup; } curHead = curLookup->GetChildAddress(); curParent = curLookup; } if (curLookup->GetValue() != -1) { Error(TKERR_DUPLICATESYMBOL); } curLookup->SetValue(theValue); } CToken* CTokenizer::HandleString() { char theString[MAX_STRING_LENGTH]; for (int i = 0; i < MAX_STRING_LENGTH; i++) { if (!NextChar((byte&)theString[i])) { return NULL; } if (theString[i] == '"') { theString[i] = '\0'; return CStringToken::Create(theString); } if (theString[i] == '\\') { theString[i] = Escapement(); } } Error(TKERR_STRINGLENGTHEXCEEDED); return NULL; } void CTokenizer::GetCurFilename(char** filename) { if (m_curParseStream == NULL) { *filename = (char*)malloc(1); *filename[0] = '\0'; return; } m_curParseStream->GetCurFilename(filename); } int CTokenizer::GetCurLine() { if (m_curParseStream == NULL) { return 0; } return m_curParseStream->GetCurLine(); } void CTokenizer::PutBackChar(byte theByte, int curLine, LPCTSTR filename) { CParseStream* newStream; if (filename == NULL) { curLine = m_curParseStream->GetCurLine(); char* theFile = NULL; m_curParseStream->GetCurFilename(&theFile); newStream = CParsePutBack::Create(theByte, curLine, theFile); if (theFile != NULL) { free(theFile); } } else { newStream = CParsePutBack::Create(theByte, curLine, filename); } newStream->SetNext(m_curParseStream); m_curParseStream = newStream; } byte CTokenizer::Escapement() { byte theByte; if (NextChar(theByte)) { switch(theByte) { case 'n': return '\n'; case '\\': return '\\'; case '\'': return '\''; case '?': return '\?'; case 'a': return '\a'; case 'b': return '\b'; case 'f': return '\f'; case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; case '0': return '\0'; // support for octal or hex sequences?? \000 or \xhhh default: PutBackChar(theByte); } } return '\\'; } bool CTokenizer::AddDefineSymbol(CDirectiveSymbol* definesymbol) { CParseStream* curStream = m_curParseStream; while(curStream != NULL) { if (curStream->IsThisDefinition(definesymbol)) { return false; } curStream = curStream->GetNext(); } CParseStream* newStream = CParseDefine::Create(definesymbol); newStream->SetNext(m_curParseStream); m_curParseStream = newStream; return true; } CToken* CTokenizer::TokenFromName(LPCTSTR name) { CDirectiveSymbol* defineSymbol = (CDirectiveSymbol*)m_defines.FindSymbol(name); if (defineSymbol != NULL) { if (AddDefineSymbol(defineSymbol)) { return FetchToken(); } } if ((m_keywords != NULL) && ((m_flags & TKF_IGNOREKEYWORDS) == 0)) { int i = 0; if ((m_flags & TKF_NOCASEKEYWORDS) == 0) { while (m_keywords[i].m_tokenvalue != TK_EOF) { if (strcmp(m_keywords[i].m_keyword, name) == 0) { return CUserToken::Create(m_keywords[i].m_tokenvalue, name); } i++; } } else { while (m_keywords[i].m_tokenvalue != TK_EOF) { if (Q_stricmp(m_keywords[i].m_keyword, name) == 0) { return CUserToken::Create(m_keywords[i].m_tokenvalue, name); } i++; } } } return CIdentifierToken::Create(name); } int CTokenizer::DirectiveFromName(LPCTSTR name) { if (directiveKeywords != NULL) { int i = 0; while (directiveKeywords[i].m_tokenvalue != TK_EOF) { if (strcmp(directiveKeywords[i].m_keyword, name) == 0) { return directiveKeywords[i].m_tokenvalue; } i++; } } return -1; } CToken* CTokenizer::HandleIdentifier(byte theByte) { char theString[MAX_IDENTIFIER_LENGTH]; theString[0] = theByte; for (int i = 1; i < MAX_IDENTIFIER_LENGTH; i++) { if (NextChar((byte&)theString[i])) { if (((theString[i] != '_') || ((m_flags & TKF_NOUNDERSCOREINIDENTIFIER) == 0)) && ((theString[i] != '-') || ((m_flags & TKF_NODASHINIDENTIFIER) == 0))) { if (((theString[i] >= 'A') && (theString[i] <= 'Z')) || ((theString[i] >= 'a') && (theString[i] <= 'z')) || ((theString[i] >= '0') && (theString[i] <= '9')) || (theString[i] == '_') || (theString[i] == '-')) { continue; } } PutBackChar(theString[i]); } theString[i] = '\0'; return TokenFromName(theString); } Error(TKERR_IDENTIFIERLENGTHEXCEEDED); return NULL; } CToken* CTokenizer::HandleSlash() { byte theByte; if (!NextChar(theByte)) { return NULL; } if (theByte == '/') { if (m_flags & TKF_COMMENTTOKENS) { return GetToEndOfLine(TK_COMMENT); } SkipToLineEnd(); return NULL; } if (theByte == '*') { if (m_flags & TKF_COMMENTTOKENS) { char theString[MAX_IDENTIFIER_LENGTH + 1]; theString[0] = ' '; while (theString[0] == ' ') { if (!NextChar((byte&)theString[0])) { return NULL; } } for (int i = 1; i < MAX_IDENTIFIER_LENGTH; i++) { if (NextChar((byte&)theString[i])) { if (theString[i] != '*') { continue; } i++; if (NextChar((byte&)theString[i])) { if (theString[i] == '/') { i--; theString[i] = '\0'; return CCommentToken::Create(theString); } } } } Error(TKERR_IDENTIFIERLENGTHEXCEEDED); return NULL; } while(NextChar(theByte)) { while(theByte == '*') { if (!NextChar(theByte)) { break; } if (theByte == '/') { return NULL; } } } return NULL; } PutBackChar(theByte); return HandleSymbol('/'); } CToken* CTokenizer::HandleNumeric(byte theByte) { bool thesign = theByte == '-'; if (thesign) { if (!NextChar(theByte)) { return HandleSymbol('-'); } if (theByte == '.') { return HandleDecimal(thesign); } if ((theByte < '0') || (theByte > '9')) { PutBackChar(theByte); return HandleSymbol('-'); } } if (theByte == '0') { return HandleOctal(thesign); } long value = 0; bool digithit = false; while((theByte >= '0') && (theByte <= '9')) { value = (value * 10) + (theByte - '0'); if (!NextChar(theByte)) { if (thesign) { value = -value; } return CIntToken::Create(value); } digithit = true; } if (theByte == '.') { if (digithit) { return HandleFloat(thesign, value); } if (thesign) { PutBackChar(theByte); theByte = '-'; } return HandleSymbol(theByte); } PutBackChar(theByte); if (thesign) { value = -value; } return CIntToken::Create(value); } CToken* CTokenizer::HandleOctal(bool thesign) { byte theByte; int value = 0; if (!NextChar(theByte)) { return CIntToken::Create(value); } if (theByte == '.') { return HandleDecimal(thesign); } if ((theByte == 'x') || (theByte == 'X')) { return HandleHex(thesign); } while(true) { if((theByte >= '0') && (theByte <='7')) { value = (value * 8) + (theByte - '0'); } else { PutBackChar(theByte); if (thesign) { value = -value; } return CIntToken::Create(value); } if (!NextChar(theByte)) { if (thesign) { value = -value; } return CIntToken::Create(value); } } } CToken* CTokenizer::HandleHex(bool thesign) { int value = 0; while (true) { byte theByte; if (!NextChar(theByte)) { if (thesign) { value = -value; } return CIntToken::Create(value); } switch (theByte) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': theByte = theByte - '0'; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': theByte = theByte - 'A' + 10; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': theByte = theByte - 'a' + 10; break; default: PutBackChar(theByte); if (thesign) { value = -value; } return CIntToken::Create(value); } value = (value * 16) + theByte; } } CToken* CTokenizer::HandleDecimal(bool thesign) { byte theByte; if (!NextChar(theByte)) { if (thesign) { PutBackChar('.'); return HandleSymbol('-'); } HandleSymbol('.'); } PutBackChar(theByte); if ((theByte <= '9') && (theByte >= '0')) { return HandleFloat(thesign); } if (thesign) { PutBackChar('.'); theByte = '-'; } else { theByte = '.'; } return HandleSymbol(theByte); } CToken* CTokenizer::HandleFloat(bool thesign, long value) { float lower = 1.0; float newValue = (float)value; byte theByte; while(NextChar(theByte)) { if ((theByte >= '0') && (theByte <= '9')) { lower = lower / 10; newValue = newValue + ((theByte - '0') * lower); continue; } PutBackChar(theByte); break; } if (thesign) { newValue = -newValue; } return CFloatToken::Create(newValue); } CToken* CTokenizer::HandleQuote() { byte theByte; if (!NextChar(theByte)) { Error(TKERR_EXPECTED_CHAR); return NULL; } if (theByte == '\\') { theByte = Escapement(); } byte dummy; if (!NextChar(dummy)) { Error(TKERR_EXPECTED_CHAR); return NULL; } if (dummy != '\'') { PutBackChar(dummy); PutBackChar(theByte); Error(TKERR_EXPECTED_CHAR); return NULL; } return CCharToken::Create(theByte); } void CTokenizer::SetFlags(UINT flags) { m_flags = flags; } UINT CTokenizer::GetFlags() { return m_flags; } CToken* CTokenizer::HandleSymbol(byte theByte) { char symbolString[128]; int curStrLen = 0; symbolString[0] = '\0'; bool consumed = false; CSymbolLookup* curLookup; if ((m_flags & TKF_RAWSYMBOLSONLY) == 0) { curLookup = m_symbolLookup; } else { curLookup = NULL; } CSymbolLookup* lastLookup = NULL; while(curLookup != NULL) { if (curLookup->GetByte() == theByte) { symbolString[curStrLen++] = theByte; symbolString[curStrLen] = '\0'; lastLookup = curLookup; consumed = true; if (curLookup->GetChild() == NULL) { break; } if (!NextChar(theByte)) { PutBackToken(CToken::Create()); break; } consumed = false; curLookup = curLookup->GetChild(); continue; } curLookup = curLookup->GetNext(); } if ((!consumed) && (lastLookup != NULL)) { PutBackChar(theByte); } while ((lastLookup != NULL) && (lastLookup->GetValue() == -1)) { curStrLen--; symbolString[curStrLen] = '\0'; // symbolString = symbolString.Left(symbolString.GetLength() - 1); if (lastLookup->GetParent() == NULL) { if ((m_flags & TKF_WANTUNDEFINED) == 0) { Error(TKERR_UNRECOGNIZEDSYMBOL); } } else { PutBackChar(lastLookup->GetByte()); } lastLookup = lastLookup->GetParent(); } if (lastLookup == NULL) { if ((m_flags & TKF_WANTUNDEFINED) == 0) { return NULL; } curStrLen = 0; symbolString[curStrLen++] = char(theByte); symbolString[curStrLen] = '\0'; if ((m_flags & TKF_WIDEUNDEFINEDSYMBOLS) != 0) { while (true) { if (!NextChar(theByte)) { PutBackToken(CToken::Create()); break; } if (theByte == ' ') { break; } if (((theByte >= 'a') && (theByte <= 'z')) || ((theByte >= 'A') && (theByte <= 'Z')) || ((theByte >= '0') && (theByte <= '9'))) { PutBackChar(theByte); break; } if (theByte < ' ') { if ((theByte == '\n') && ((TKF_USES_EOL & m_flags) != 0)) { PutBackToken(CUserToken::Create(TK_EOL, "-EOLN-")); break; } continue; } symbolString[curStrLen++] = theByte; symbolString[curStrLen] = '\0'; } } return CUndefinedToken::Create(symbolString); } return CUserToken::Create(lastLookup->GetValue(), symbolString); } CToken* CTokenizer::HandleDirective() { int tokenValue = 0; CToken* theToken = FetchToken(); if (theToken->GetType() == TK_EOF) { return theToken; } if (theToken->GetType() != TK_IDENTIFIER) { Error(TKERR_INVALID_DIRECTIVE); theToken->Delete(); SkipToLineEnd(); return NULL; } CDirectiveSymbol* curSymbol; CTokenizerState* state; int theDirective = DirectiveFromName(theToken->GetStringValue()); theToken->Delete(); byte theByte; switch(theDirective) { case DIR_INCLUDE: if ((m_state != NULL) && (m_state->Skipping())) { break; } theToken = GetToken(); if (theToken->GetType() != TK_STRING) { Error(TKERR_INCLUDE_FILE_NOTFOUND); theToken->Delete(); SkipToLineEnd(); break; } AddParseFile(theToken->GetStringValue()); theToken->Delete(); break; case DIR_IFDEF: if ((m_state != NULL) && (m_state->Skipping())) { state = CTokenizerHolderState::Create(); state->SetNext(m_state); m_state = state; break; } theToken = GetToken(); if (theToken->GetType() != TK_IDENTIFIER) { Error(TKERR_EXPECTED_IDENTIFIER); theToken->Delete(); SkipToLineEnd(); break; } state = CTokenizerState::Create(m_defines.FindSymbol(theToken->GetStringValue()) == NULL); theToken->Delete(); state->SetNext(m_state); m_state = state; break; case DIR_IFNDEF: if ((m_state != NULL) && (m_state->Skipping())) { state = CTokenizerHolderState::Create(); state->SetNext(m_state); m_state = state; break; } theToken = GetToken(); if (theToken->GetType() != TK_IDENTIFIER) { Error(TKERR_EXPECTED_IDENTIFIER); theToken->Delete(); SkipToLineEnd(); break; } state = CTokenizerState::Create(m_defines.FindSymbol(theToken->GetStringValue()) != NULL); theToken->Delete(); state->SetNext(m_state); m_state = state; break; case DIR_ENDIF: if (m_state == NULL) { Error(TKERR_UNMATCHED_DIRECTIVE); break; } state = m_state; m_state = state->GetNext(); state->Delete(); break; case DIR_ELSE: if (m_state == NULL) { Error(TKERR_UNMATCHED_DIRECTIVE); break; } if (!m_state->ProcessElse()) { Error(TKERR_UNMATCHED_DIRECTIVE); break; } break; case DIR_DEFINE: if ((m_state != NULL) && (m_state->Skipping())) { break; } theToken = GetToken(); if (theToken->GetType() != TK_IDENTIFIER) { Error(TKERR_EXPECTED_IDENTIFIER); theToken->Delete(); SkipToLineEnd(); break; } // blind add - should check first for value changes { curSymbol = CDirectiveSymbol::Create(theToken->GetStringValue()); char temp[128]; int tempsize = 0; while(NextChar(theByte)) { if (theByte == '\n') { break; } temp[tempsize++] = char(theByte); } temp[tempsize] = '\0'; curSymbol->SetValue(temp); if (!m_defines.AddSymbol(curSymbol)) { curSymbol->Delete(); } } break; case DIR_UNDEFINE: if ((m_state != NULL) && (m_state->Skipping())) { break; } theToken = GetToken(); if (theToken->GetType() != TK_IDENTIFIER) { Error(TKERR_EXPECTED_IDENTIFIER); theToken->Delete(); SkipToLineEnd(); break; } m_defines.RemoveSymbol(theToken->GetStringValue()); break; default: Error(TKERR_INVALID_DIRECTIVE); SkipToLineEnd(); break; } return NULL; } COLORREF CTokenizer::ParseRGB() { CToken* theToken = GetToken(); if (theToken->GetType() != TK_INT) { Error(TKERR_EXPECTED_INTEGER); theToken->Delete(); return RGB(0, 0, 0); } int red = theToken->GetIntValue(); theToken->Delete(); theToken = GetToken(); if (theToken->GetType() != TK_INT) { Error(TKERR_EXPECTED_INTEGER); theToken->Delete(); return RGB(0, 0, 0); } int green = theToken->GetIntValue(); theToken->Delete(); theToken = GetToken(); if (theToken->GetType() != TK_INT) { Error(TKERR_EXPECTED_INTEGER); theToken->Delete(); return RGB(0, 0, 0); } int blue = theToken->GetIntValue(); theToken->Delete(); return RGB(red, green, blue); } // // CSymbolLookup // CSymbolLookup::CSymbolLookup() { } CSymbolLookup::~CSymbolLookup() { } CSymbolLookup* CSymbolLookup::Create(byte theByte) { CSymbolLookup* curLookup = new CSymbolLookup(); curLookup->Init(theByte); return curLookup; } void CSymbolLookup::Delete() { if (m_sibling != NULL) { m_sibling->Delete(); m_sibling = NULL; } if (m_child != NULL) { m_child->Delete(); m_child = NULL; } delete this; } void CSymbolLookup::Init(byte theByte) { m_parent = NULL; m_child = NULL; m_sibling = NULL; m_value = -1; m_byte = theByte; } CSymbolLookup* CSymbolLookup::GetNext() { return m_sibling; } void CSymbolLookup::SetNext(CSymbolLookup* next) { m_sibling = next; } void CSymbolLookup::SetParent(CSymbolLookup* parent) { m_parent = parent; } void CSymbolLookup::SetValue(int value) { m_value = value; } int CSymbolLookup::GetValue() { return m_value; } byte CSymbolLookup::GetByte() { return m_byte; } CSymbolLookup** CSymbolLookup::GetChildAddress() { return &m_child; } CSymbolLookup* CSymbolLookup::GetChild() { return m_child; } CSymbolLookup* CSymbolLookup::GetParent() { return m_parent; }