int CSymbolTable::Compare (int iKey1, int iKey2) const // Compare // // Compares two keys { CString *pKey1 = (CString *)iKey1; CString *pKey2 = (CString *)iKey2; return strCompareAbsolute(*pKey1, *pKey2); }
BOOL ICCItem::IsLambdaSymbol (void) // IsLambdaSymbol // // Returns TRUE if this is the symbol lambda { if (IsIdentifier() && strCompareAbsolute(GetStringValue(), CONSTLIT("lambda")) == 0) return TRUE; else return FALSE; }
void CMenuData::AddMenuItem (const CString &sKey, const CString &sLabel, const CObjectImageArray *pImage, const CString &sExtra, DWORD dwFlags, DWORD dwData, DWORD dwData2) // AddMenuItem // // Add an item { ASSERT(m_iCount < MAX_MENU_ITEMS); if (m_iCount == MAX_MENU_ITEMS) return; // If we have a key, sort by key. Otherwise, we // add it at the end. int iPos; if (sKey.IsBlank() || !(dwFlags & FLAG_SORT_BY_KEY)) iPos = m_iCount; else { iPos = 0; while (iPos < m_iCount && !m_List[iPos].sKey.IsBlank() && strCompareAbsolute(sKey, m_List[iPos].sKey) > 0) iPos++; // Move other items up for (int i = m_iCount - 1; i >= iPos; i--) m_List[i+1] = m_List[i]; } // Add item m_List[iPos].sKey = sKey; m_List[iPos].sLabel = sLabel; m_List[iPos].dwData = dwData; m_List[iPos].dwData2 = dwData2; m_List[iPos].sExtra = sExtra; m_List[iPos].dwFlags = dwFlags; m_List[iPos].pImage = pImage; m_iCount++; }
ICCItem *CCLambda::Execute (CEvalContext *pCtx, ICCItem *pArgs) // Execute // // Executes the function and returns a result { CCodeChain *pCC = pCtx->pCC; ICCItem *pItem; ICCItem *pOldSymbols; ICCItem *pLocalSymbols; ICCItem *pVar; ICCItem *pArg; ICCItem *pResult; int i; BOOL bNoEval; // We must have been initialized if (m_pArgList == NULL || m_pCode == NULL) return pCC->CreateNil(); // If the argument list if quoted, then it means that the arguments // have already been evaluated. This happens if we've been called by // (apply). bNoEval = pArgs->IsQuoted(); // Set up the symbol table pLocalSymbols = pCC->CreateSymbolTable(); if (pLocalSymbols->IsError()) return pLocalSymbols; // Loop over each item and associate it for (i = 0; i < m_pArgList->GetCount(); i++) { pVar = m_pArgList->GetElement(i); pArg = pArgs->GetElement(i); // If the name of this variable is %args, then the rest of the arguments // should go into a list if (strCompareAbsolute(pVar->GetStringValue(), CONSTLIT("%args")) == 0) { ICCItem *pVarArgs; // If there are arguments left, add them to a list if (pArg) { int j; ICCItem *pError; CCLinkedList *pList; // Create a list pVarArgs = pCC->CreateLinkedList(); if (pVarArgs->IsError()) { pLocalSymbols->Discard(pCC); return pVarArgs; } pList = (CCLinkedList *)pVarArgs; // Add each argument to the list for (j = i; j < pArgs->GetCount(); j++) { pArg = pArgs->GetElement(j); if (bNoEval) pResult = pArg->Reference(); else pResult = pCC->Eval(pCtx, pArg); pList->Append(pCC, pResult, &pError); pResult->Discard(pCC); if (pError->IsError()) { pVarArgs->Discard(pCC); pLocalSymbols->Discard(pCC); return pError; } pError->Discard(pCC); } } else pVarArgs = pCC->CreateNil(); // Add to the local symbol table pItem = pLocalSymbols->AddEntry(pCC, pVar, pVarArgs); pVarArgs->Discard(pCC); } // Bind the variable to the argument else if (pArg == NULL) pItem = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil()); else { ICCItem *pResult; // Evaluate the arg and add to the table if (bNoEval) pResult = pArg->Reference(); else pResult = pCC->Eval(pCtx, pArg); pItem = pLocalSymbols->AddEntry(pCC, pVar, pResult); pResult->Discard(pCC); } // Check for error if (pItem->IsError()) { pLocalSymbols->Discard(pCC); return pItem; } pItem->Discard(pCC); } // Setup the context pLocalSymbols->SetParent(pCtx->pLexicalSymbols); pOldSymbols = pCtx->pLocalSymbols; pCtx->pLocalSymbols = pLocalSymbols; // Evalute the code pResult = pCC->Eval(pCtx, m_pCode); // Clean up pCtx->pLocalSymbols = pOldSymbols; pLocalSymbols->Discard(pCC); return pResult; }
ICCItem *CCodeChain::Link (const CString &sString, int iOffset, int *retiLinked, int *ioiCurLine) // Link // // Parses the given string and converts it into a linked // chain of items { char *pStart; char *pPos; ICCItem *pResult = NULL; int iCurLine = (ioiCurLine ? *ioiCurLine : 1); pStart = sString.GetPointer() + iOffset; pPos = pStart; // Skip any whitespace pPos = SkipWhiteSpace(pPos, &iCurLine); // If we've reached the end, then we have // nothing if (*pPos == '\0') pResult = CreateNil(); // If we've got a literal quote, then remember it else if (*pPos == SYMBOL_QUOTE) { int iLinked; pPos++; pResult = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pResult->IsError()) return pResult; pPos += iLinked; // Make it a literal pResult->SetQuoted(); } // If we've got an open paren then we start a list else if (*pPos == SYMBOL_OPENPAREN) { ICCItem *pNew = CreateLinkedList(); if (pNew->IsError()) return pNew; CCLinkedList *pList = dynamic_cast<CCLinkedList *>(pNew); // Keep reading until we find the end pPos++; // If the list is empty, then there's nothing to do pPos = SkipWhiteSpace(pPos, &iCurLine); if (*pPos == SYMBOL_CLOSEPAREN) { pList->Discard(this); pResult = CreateNil(); pPos++; } // Get all the items in the list else { while (*pPos != SYMBOL_CLOSEPAREN && *pPos != '\0') { ICCItem *pItem; int iLinked; pItem = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pItem->IsError()) return pItem; // Add the item to the list pList->Append(this, pItem, NULL); pItem->Discard(this); // Move the position pPos += iLinked; // Skip whitespace pPos = SkipWhiteSpace(pPos, &iCurLine); } // If we have a close paren then we're done; Otherwise we've // got an error of some kind if (*pPos == SYMBOL_CLOSEPAREN) { pPos++; pResult = pList; } else { pList->Discard(this); pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched open parenthesis")); } } } // If this is an open brace then we've got a literal structure else if (*pPos == SYMBOL_OPENBRACE) { ICCItem *pNew = CreateSymbolTable(); if (pNew->IsError()) return pNew; CCSymbolTable *pTable = dynamic_cast<CCSymbolTable *>(pNew); // Always literal pTable->SetQuoted(); // Keep reading until we find the end pPos++; // If the list is empty, then there's nothing to do pPos = SkipWhiteSpace(pPos, &iCurLine); if (*pPos == SYMBOL_CLOSEBRACE) { pResult = pTable; pPos++; } // Get all the items in the list else { while (*pPos != SYMBOL_CLOSEBRACE && *pPos != '\0') { // Get the key ICCItem *pKey; int iLinked; pKey = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pKey->IsError()) { pTable->Discard(this); return pKey; } // Move the position and read a colon pPos += iLinked; pPos = SkipWhiteSpace(pPos, &iCurLine); if (*pPos != SYMBOL_COLON) { pKey->Discard(this); pTable->Discard(this); return CreateParseError(iCurLine, CONSTLIT("Struct value not found.")); } pPos++; // Get the value ICCItem *pValue; pValue = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pValue->IsError()) { pKey->Discard(this); pTable->Discard(this); return pValue; } // Move the position pPos += iLinked; // Add the item to the table pResult = pTable->AddEntry(this, pKey, pValue); pKey->Discard(this); pValue->Discard(this); if (pResult->IsError()) { pTable->Discard(this); return pResult; } // Skip whitespace because otherwise we won't know whether we // hit the end brace. pPos = SkipWhiteSpace(pPos, &iCurLine); } // If we have a close paren then we're done; Otherwise we've // got an error of some kind if (*pPos == SYMBOL_CLOSEBRACE) { pPos++; pResult = pTable; } else { pTable->Discard(this); pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched open brace")); } } } // If this is an open quote, then read everything until // the close quote else if (*pPos == SYMBOL_OPENQUOTE) { // Parse the string, until the end quote, parsing escape codes char *pStartFragment = NULL; CString sResultString; bool bDone = false; while (!bDone) { pPos++; switch (*pPos) { case SYMBOL_CLOSEQUOTE: case '\0': { if (pStartFragment) { sResultString.Append(CString(pStartFragment, pPos - pStartFragment)); pStartFragment = NULL; } bDone = true; break; } case SYMBOL_BACKSLASH: { if (pStartFragment) { sResultString.Append(CString(pStartFragment, pPos - pStartFragment)); pStartFragment = NULL; } pPos++; if (*pPos == '\0') bDone = true; else if (*pPos == 'n') sResultString.Append(CString("\n", 1)); else if (*pPos == 'r') sResultString.Append(CString("\r", 1)); else if (*pPos == 't') sResultString.Append(CString("\t", 1)); else if (*pPos == '0') sResultString.Append(CString("\0", 1)); else if (*pPos == 'x' || *pPos == 'X') { pPos++; int iFirstDigit = strGetHexDigit(pPos); pPos++; int iSecondDigit = 0; if (*pPos == '\0') bDone = true; else iSecondDigit = strGetHexDigit(pPos); char chChar = (char)(16 * iFirstDigit + iSecondDigit); sResultString.Append(CString(&chChar, 1)); } else sResultString.Append(CString(pPos, 1)); break; } default: { if (pStartFragment == NULL) pStartFragment = pPos; break; } } } // If we found the close, then create a string; otherwise, // it is an error if (*pPos == SYMBOL_CLOSEQUOTE) { pResult = CreateString(sResultString); // Always a literal pResult->SetQuoted(); // Skip past quote pPos++; } else pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched quote")); } // If this is a close paren, then it is an error else if (*pPos == SYMBOL_CLOSEPAREN) pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched close parenthesis")); // If this is a close brace, then it is an error else if (*pPos == SYMBOL_CLOSEBRACE) pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched close brace")); // Colons cannot appear alone else if (*pPos == SYMBOL_COLON) pResult = CreateParseError(iCurLine, CONSTLIT("':' character must appear inside quotes or in a struct definition.")); // Otherwise this is an string of some sort else { char *pStartString; CString sIdentifier; int iInt; bool bNotInteger; pStartString = pPos; // Look for whitespace while (*pPos != '\0' && *pPos != ' ' && *pPos != '\n' && *pPos != '\r' && *pPos != '\t' && *pPos != SYMBOL_OPENPAREN && *pPos != SYMBOL_CLOSEPAREN && *pPos != SYMBOL_OPENQUOTE && *pPos != SYMBOL_CLOSEQUOTE && *pPos != SYMBOL_OPENBRACE && *pPos != SYMBOL_CLOSEBRACE && *pPos != SYMBOL_COLON && *pPos != SYMBOL_QUOTE && *pPos != ';') pPos++; // If we did not advance, then we clearly hit an error if (pStartString == pPos) pResult = CreateParseError(iCurLine, strPatternSubst(CONSTLIT("Unexpected character: %s"), CString(pPos, 1))); // If we ended in a quote then that's a bug else if (*pPos == SYMBOL_QUOTE) pResult = CreateParseError(iCurLine, strPatternSubst(CONSTLIT("Identifiers must not use single quote characters: %s"), strSubString(sString, iOffset + (pStartString - pStart), (pPos + 1 - pStartString)))); // Otherwise, get the identifier else { // Create a string from the portion sIdentifier = strSubString(sString, iOffset + (pStartString - pStart), (pPos - pStartString)); // Check to see if this is a reserved identifier if (strCompareAbsolute(sIdentifier, CONSTLIT("Nil")) == 0) pResult = CreateNil(); else if (strCompareAbsolute(sIdentifier, CONSTLIT("True")) == 0) pResult = CreateTrue(); else { // If this is an integer, create an integer; otherwise // create a string iInt = strToInt(sIdentifier, 0, &bNotInteger); if (bNotInteger) pResult = CreateString(sIdentifier); else pResult = CreateInteger(iInt); } } } // Return the result and the number of characters // that we read if (retiLinked) *retiLinked = (pPos - pStart); if (ioiCurLine) *ioiCurLine = iCurLine; return pResult; }