// // Parse a subchain of input delimited by matching pairs: [],(),{},<> // [WARNING: no other subchain types are recognized!]. This function expects // g_cxx.pToken to point to the initial token of the pair ([{<. // It will parse input until the matching terminator token is found. // Inner parsing is done by cxxParserParseAndCondenseSubchainsUpToOneOf() // so this is actually a recursive subchain nesting algorithm. // boolean cxxParserParseAndCondenseCurrentSubchain( unsigned int uInitialSubchainMarkerTypes, boolean bAcceptEOF ) { CXXTokenChain * pCurrentChain = g_cxx.pTokenChain; g_cxx.pTokenChain = cxxTokenChainCreate(); CXXToken * pInitial = cxxTokenChainTakeLast(pCurrentChain); cxxTokenChainAppend(g_cxx.pTokenChain,pInitial); CXXToken * pChainToken = cxxTokenCreate(); pChainToken->iLineNumber = pInitial->iLineNumber; pChainToken->oFilePosition = pInitial->oFilePosition; // see the declaration of CXXTokenType enum. // Shifting by 8 gives the corresponding chain marker pChainToken->eType = (enum CXXTokenType)(g_cxx.pToken->eType << 8); pChainToken->pChain = g_cxx.pTokenChain; cxxTokenChainAppend(pCurrentChain,pChainToken); // see the declaration of CXXTokenType enum. // Shifting by 4 gives the corresponding closing token type unsigned int uTokenTypes = g_cxx.pToken->eType << 4; if(bAcceptEOF) uTokenTypes |= CXXTokenTypeEOF; boolean bRet = cxxParserParseAndCondenseSubchainsUpToOneOf( uTokenTypes, uInitialSubchainMarkerTypes ); g_cxx.pTokenChain = pCurrentChain; g_cxx.pToken = pCurrentChain->pTail; return bRet; }
static void cxxParserFirstInit() { memset(&g_cxx,0,sizeof(CXXParserState)); g_cxx.eCLanguage = -1; g_cxx.eCPPLanguage = -1; cxxTokenAPIInit(); g_cxx.pTokenChain = cxxTokenChainCreate(); cxxScopeInit(); g_bFirstRun = FALSE; }
// // Parses a template<anything> prefix. // The parsed template parameter definition is stored in a separate token chain. // boolean cxxParserParseTemplatePrefix(void) { CXX_DEBUG_ENTER(); CXX_DEBUG_ASSERT(cxxTokenTypeIs(cxxTokenChainLast(g_cxx.pTokenChain),CXXTokenTypeKeyword),"We should be pointing at the template keyword here"); cxxTokenChainDestroyLast(g_cxx.pTokenChain); // kill the template keyword if(!cxxParserParseUpToOneOf(CXXTokenTypeSmallerThanSign | CXXTokenTypeEOF | CXXTokenTypeSemicolon)) { CXX_DEBUG_LEAVE_TEXT("Failed to parse up to the < sign"); return FALSE; } if(cxxTokenTypeIsOneOf(g_cxx.pToken,CXXTokenTypeEOF | CXXTokenTypeSemicolon)) { CXX_DEBUG_LEAVE_TEXT("Found EOF or semicolon: assuming this is unparseable"); cxxParserNewStatement(); return TRUE; // tolerate syntax error } CXXTokenChain * pSave = g_cxx.pTokenChain; g_cxx.pTokenChain = cxxTokenChainCreate(); cxxTokenChainAppend(g_cxx.pTokenChain,cxxTokenChainTakeLast(pSave)); if(!cxxParserParseTemplatePrefixAngleBrackets()) { CXX_DEBUG_LEAVE_TEXT("Failed to parse angle brackets"); cxxTokenChainDestroy(pSave); return FALSE; } if(g_cxx.pTemplateTokenChain) cxxTokenChainDestroy(g_cxx.pTemplateTokenChain); g_cxx.pTemplateTokenChain = g_cxx.pTokenChain; g_cxx.pTokenChain = pSave; CXX_DEBUG_LEAVE(); return TRUE; }
CXXTokenChain * cxxTokenChainSplitOnComma(CXXTokenChain * tc) { if(!tc) return NULL; CXXTokenChain * pRet = cxxTokenChainCreate(); CXXToken * pToken = cxxTokenChainFirst(tc); if(!pToken) return pRet; CXXToken * pStart = pToken; while(pStart && pToken->pNext) { while(pToken->pNext && (!cxxTokenTypeIs(pToken->pNext,CXXTokenTypeComma))) pToken = pToken->pNext; CXXToken * pNew = cxxTokenChainExtractRange(pStart,pToken,0); if(pNew) cxxTokenChainAppend(pRet,pNew); pToken = pToken->pNext; // comma or nothing if(pToken) pToken = pToken->pNext; // after comma pStart = pToken; } if(pStart) { // finished without comma CXXToken * pNew = cxxTokenChainExtractRange(pStart,cxxTokenChainLast(tc),0); if(pNew) cxxTokenChainAppend(pRet,pNew); } return pRet; }
void cxxTokenAPIInit(void) { g_pTokenPool = cxxTokenChainCreate(); }
void cxxScopeInit(void) { g_pScope = cxxTokenChainCreate(); }
// In case of a lambda without parentheses this is the capture list token. boolean cxxParserHandleLambda(CXXToken * pParenthesis) { CXX_DEBUG_ENTER(); CXXToken * pIdentifier = cxxTokenCreateAnonymousIdentifier(CXXTagKindFUNCTION); CXXTokenChain * pSave = g_cxx.pTokenChain; CXXTokenChain * pNew = cxxTokenChainCreate(); g_cxx.pTokenChain = pNew; tagEntryInfo * tag = cxxTagBegin(CXXTagKindFUNCTION,pIdentifier); CXXToken * pAfterParenthesis = pParenthesis ? pParenthesis->pNext : NULL; CXXToken * pCaptureList = NULL; if(pParenthesis) { if(cxxTokenTypeIs(pParenthesis,CXXTokenTypeSquareParenthesisChain)) { // form (4) of lambda (see cxxParserOpeningBracketIsLambda()). pCaptureList = pParenthesis; } else if( pParenthesis->pPrev && cxxTokenTypeIs(pParenthesis->pPrev,CXXTokenTypeSquareParenthesisChain) ) { // other forms of lambda (see cxxParserOpeningBracketIsLambda()). pCaptureList = pParenthesis->pPrev; } } if( pAfterParenthesis && cxxTokenTypeIs(pAfterParenthesis,CXXTokenTypeKeyword) && (pAfterParenthesis->eKeyword == CXXKeywordCONST) ) pAfterParenthesis = pAfterParenthesis->pNext; CXXToken * pTypeStart = NULL; CXXToken * pTypeEnd; if( pAfterParenthesis && cxxTokenTypeIs(pAfterParenthesis,CXXTokenTypePointerOperator) && pAfterParenthesis->pNext && !cxxTokenTypeIs(pAfterParenthesis->pNext,CXXTokenTypeOpeningBracket) ) { pTypeStart = pAfterParenthesis->pNext; pTypeEnd = pTypeStart; while( pTypeEnd->pNext && (!cxxTokenTypeIs(pTypeEnd->pNext,CXXTokenTypeOpeningBracket)) ) pTypeEnd = pTypeEnd->pNext; while( (pTypeStart != pTypeEnd) && cxxTokenTypeIs(pTypeStart,CXXTokenTypeKeyword) && cxxKeywordExcludeFromTypeNames(pTypeStart->eKeyword) ) pTypeStart = pTypeStart->pNext; } int iCorkQueueIndex = CORK_NIL; if(tag) { tag->isFileScope = TRUE; CXXToken * pTypeName; if(pTypeStart) pTypeName = cxxTagSetTypeField(pTypeStart,pTypeEnd); else pTypeName = NULL; if(pCaptureList && cxxTagCPPFieldEnabled(CXXTagCPPFieldLambdaCaptureList)) { CXX_DEBUG_ASSERT(pCaptureList->pChain,"The capture list must be a chain"); cxxTokenChainCondense(pCaptureList->pChain,0); CXX_DEBUG_ASSERT( cxxTokenChainFirst(pCaptureList->pChain), "Condensation should have created a single token in the chain" ); cxxTagSetCPPField( CXXTagCPPFieldLambdaCaptureList, vStringValue(cxxTokenChainFirst(pCaptureList->pChain)->pszWord) ); } // FIXME: Properties? vString * pszSignature = NULL; if(cxxTokenTypeIs(pParenthesis,CXXTokenTypeParenthesisChain)) pszSignature = cxxTokenChainJoin(pParenthesis->pChain,NULL,0); if(pszSignature) tag->extensionFields.signature = vStringValue(pszSignature); iCorkQueueIndex = cxxTagCommit(); if(pTypeName) cxxTokenDestroy(pTypeName); if(pszSignature) vStringDelete(pszSignature); } cxxScopePush( pIdentifier, CXXTagKindFUNCTION, CXXScopeAccessUnknown ); if( pParenthesis && cxxTokenTypeIs(pParenthesis,CXXTokenTypeParenthesisChain) && cxxTagKindEnabled(CXXTagKindPARAMETER) ) { CXXFunctionParameterInfo oParamInfo; if(cxxParserTokenChainLooksLikeFunctionParameterList( pParenthesis->pChain,&oParamInfo )) cxxParserEmitFunctionParameterTags(&oParamInfo); } boolean bRet = cxxParserParseBlock(TRUE); if(iCorkQueueIndex > CORK_NIL) cxxParserMarkEndLineForTagInCorkQueue(iCorkQueueIndex); cxxScopePop(); pNew = g_cxx.pTokenChain; // May have been destroyed and re-created g_cxx.pTokenChain = pSave; g_cxx.pToken = pSave->pTail; // change the type of token so following parsing code is not confused too much g_cxx.pToken->eType = CXXTokenTypeAngleBracketChain; g_cxx.pToken->pChain = pNew; cxxTokenChainClear(pNew); CXXToken * t = cxxTokenCreate(); t->eType = CXXTokenTypeOpeningBracket; vStringCatS(t->pszWord,"{"); cxxTokenChainAppend(pNew,t); t = cxxTokenCreate(); t->eType = CXXTokenTypeClosingBracket; vStringCatS(t->pszWord,"}"); cxxTokenChainAppend(pNew,t); CXX_DEBUG_LEAVE(); return bRet; }