Пример #1
0
//
// 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;
}
Пример #2
0
// An macro token was encountered and it expects a parameter list.
// The routine has to check if there is a following parenthesis
// and eventually skip it but it MUST NOT parse the next token
// if it is not a parenthesis. This is because the macro token
// may have a replacement and is that one that has to be returned
// back to the caller from cxxParserParseNextToken().
static bool cxxParserParseNextTokenSkipMacroParenthesis(CXXToken ** ppChain)
{
	CXX_DEBUG_ENTER();

	CXX_DEBUG_ASSERT(ppChain,"ppChain should not be null here");

	cxxParserSkipToNonWhiteSpace();

	if(g_cxx.iChar != '(')
	{
		*ppChain = NULL;
		return true; // no parenthesis
	}

	if(!cxxParserParseNextToken())
	{
		CXX_DEBUG_LEAVE_TEXT("No next token after ignored identifier");
		return false;
	}

	if(!cxxTokenTypeIs(g_cxx.pToken,CXXTokenTypeOpeningParenthesis))
	{
		CXX_DEBUG_ASSERT(false,"Should have found an open parenthesis token here!");
		CXX_DEBUG_LEAVE_TEXT("Internal error");
		return false;
	}

	if(!cxxParserParseAndCondenseCurrentSubchain(
			CXXTokenTypeOpeningParenthesis |
				CXXTokenTypeOpeningSquareParenthesis |
				CXXTokenTypeOpeningBracket,
			false
		))
	{
		CXX_DEBUG_LEAVE_TEXT("Failed to parse and condense subchains");
		return false;
	}

	CXX_DEBUG_ASSERT(
			cxxTokenTypeIs(g_cxx.pToken,CXXTokenTypeParenthesisChain),
			"Should have a parenthesis chain as last token!"
		);

	// Now just kill the chain.
	*ppChain = cxxTokenChainTakeLast(g_cxx.pTokenChain);

	CXX_DEBUG_LEAVE();
	return true;
}
Пример #3
0
void cxxScopePop(void)
{
	CXX_DEBUG_ASSERT(
			g_pScope->iCount > 0,
			"When popping as scope there must be a scope to pop"
		);

	cxxTokenDestroy(cxxTokenChainTakeLast(g_pScope));
	g_bScopeNameDirty = true;

#ifdef CXX_DO_DEBUGGING
	const char * szScopeName = cxxScopeGetFullName();

	CXX_DEBUG_PRINT("Popped scope: '%s'",szScopeName ? szScopeName : "");
#endif
}
Пример #4
0
void cxxTokenChainTake(CXXTokenChain * tc,CXXToken * t)
{
	if(!tc)
		return;
	if(!tc->pHead)
		return;

	/*
	Debug with this:

	CXXToken * t2 = tc->pHead;
	while(t2 && (t2 != t))
		t2 = t2->pNext;

	Assert(t2);
	*/

	if(t == tc->pHead)
	{
		cxxTokenChainTakeFirst(tc);
		return;
	}

	if(t == tc->pTail)
	{
		cxxTokenChainTakeLast(tc);
		return;
	}

	// in the middle

	CXXToken * n = t->pNext;
	CXXToken * p = t->pPrev;

	n->pPrev = p;
	p->pNext = n;

	tc->iCount--;

	Assert(tc->iCount > 1);
}
Пример #5
0
//
// 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;
}
Пример #6
0
void cxxParserUngetCurrentToken(void)
{
	CXX_DEBUG_ASSERT(
			g_cxx.pToken &&
			g_cxx.pTokenChain &&
			(g_cxx.pTokenChain->iCount > 0),
			"There should be at least one token to unget"
		);

	CXX_DEBUG_ASSERT(!g_cxx.pUngetToken,"The parser supports only one unget token at a time.");

	if(g_cxx.pUngetToken)
		cxxTokenDestroy(g_cxx.pUngetToken);
	
	
	g_cxx.pUngetToken = cxxTokenChainTakeLast(g_cxx.pTokenChain);
	
	CXX_DEBUG_ASSERT(g_cxx.pUngetToken == g_cxx.pToken,"Oops.. ungot a token that was not the chain tail");

	g_cxx.pToken = cxxTokenChainLast(g_cxx.pTokenChain);
}
Пример #7
0
// The __attribute__((...)) sequence complicates parsing quite a lot.
// For this reason we attempt to "hide" it from the rest of the parser
// at tokenizer level.
static bool cxxParserParseNextTokenCondenseAttribute(void)
{
	CXX_DEBUG_ENTER();

	CXX_DEBUG_ASSERT(
			cxxTokenIsKeyword(g_cxx.pToken,CXXKeyword__ATTRIBUTE__),
			"This function should be called only after we have parsed __attribute__"
		);

	// Kill it
	cxxTokenDestroy(cxxTokenChainTakeLast(g_cxx.pTokenChain));

	// And go ahead.

	if(!cxxParserParseNextToken())
	{
		CXX_DEBUG_LEAVE_TEXT("No next token after __attribute__");
		return false;
	}

	if(!cxxTokenTypeIs(g_cxx.pToken,CXXTokenTypeOpeningParenthesis))
	{
		CXX_DEBUG_LEAVE_TEXT("Something that is not an opening parenthesis");
		return true;
	}

	if(!cxxParserParseAndCondenseCurrentSubchain(
			CXXTokenTypeOpeningParenthesis |
				CXXTokenTypeOpeningSquareParenthesis |
				CXXTokenTypeOpeningBracket,
			false
		))
	{
		CXX_DEBUG_LEAVE_TEXT("Failed to parse and condense subchains");
		return false;
	}

	CXX_DEBUG_ASSERT(
			cxxTokenTypeIs(g_cxx.pToken,CXXTokenTypeParenthesisChain),
			"Should have a parenthesis chain as last token!"
		);

	// Try to make sense of certain kinds of __attribute__.
	// the proper syntax is __attribute__(()), so look at the inner chain

	CXXToken * pInner = cxxTokenChainFirst(g_cxx.pToken->pChain);
	if(pInner)
	{
		if(pInner->pNext && cxxTokenTypeIs(pInner->pNext,CXXTokenTypeParenthesisChain))
			pInner = cxxTokenChainFirst(pInner->pNext->pChain);

		while(pInner)
		{
			if(cxxTokenTypeIs(pInner,CXXTokenTypeIdentifier))
			{
				CXX_DEBUG_PRINT("Analyzing attribyte %s",vStringValue(pInner->pszWord));
				if(
						(strcmp(vStringValue(pInner->pszWord),"always_inline") == 0) ||
						(strcmp(vStringValue(pInner->pszWord),"__always_inline__") == 0)
					)
				{
					CXX_DEBUG_PRINT("Found attribute 'always_inline'");
					// assume "inline" has been seen.
					g_cxx.uKeywordState |= CXXParserKeywordStateSeenInline;
				} else if(
						(strcmp(vStringValue(pInner->pszWord),"deprecated") == 0) ||
						(strcmp(vStringValue(pInner->pszWord),"__deprecated__") == 0)
					)
				{
					CXX_DEBUG_PRINT("Found attribute 'deprecated'");
					// assume "inline" has been seen.
					g_cxx.uKeywordState |= CXXParserKeywordStateSeenAttributeDeprecated;
				}
			}

			// If needed, we could attach certain attributes to previous
			// identifiers. But note that __attribute__ may apply to a
			// following identifier too.

			pInner = pInner->pNext;
		}
	}

	// Now just kill the chain.
	cxxTokenDestroy(cxxTokenChainTakeLast(g_cxx.pTokenChain));

	// And finally extract yet another token.
	CXX_DEBUG_LEAVE();
	return cxxParserParseNextToken();
}