void CxxPreProcessorScanner::Parse(CxxPreProcessor* pp) throw(CxxLexerException)
{
    CxxLexerToken token;
    bool searchingForBranch = false;
    CxxPreProcessorToken::Map_t& ppTable = pp->GetTokens();
    while(::LexerNext(m_scanner, token)) {
        // Pre Processor state
        switch(token.type) {
        case T_PP_INCLUDE_FILENAME: {
            // we found an include statement, recurse into it
            wxFileName include;
            if(pp->ExpandInclude(m_filename, token.text, include)) {
                CxxPreProcessorScanner* scanner = new CxxPreProcessorScanner(include, pp->GetOptions());
                try {
                    scanner->Parse(pp);
                } catch(CxxLexerException& e) {
                    // catch the exception
                    CL_DEBUG("Exception caught: %s\n", e.message);
                }
                // make sure we always delete the scanner
                wxDELETE(scanner);
                DEBUGMSG("<== Resuming parser on file: %s\n", m_filename.GetFullPath());
            }
            break;
        }
        case T_PP_IFDEF: {
            searchingForBranch = true;
            // read the identifier
            ReadUntilMatch(T_PP_IDENTIFIER, token);
            if(IsTokenExists(ppTable, token)) {
                DEBUGMSG("=> ifdef condition is TRUE (line: %d)\n", token.lineNumber);
                searchingForBranch = false;
                // condition is true
                Parse(pp);
            } else {
                DEBUGMSG("=> ifdef condition is FALSE (line: %d)\n", token.lineNumber);
                // skip until we find the next:
                // else, elif, endif (but do not consume these tokens)
                if(!ConsumeCurrentBranch()) return;
            }
            break;
        }
        case T_PP_IFNDEF: {
            searchingForBranch = true;
            // read the identifier
            ReadUntilMatch(T_PP_IDENTIFIER, token);
            if(!IsTokenExists(ppTable, token)) {
                DEBUGMSG("=> ifndef condition is TRUE (line: %d)\n", token.lineNumber);
                searchingForBranch = false;
                // condition is true
                Parse(pp);
            } else {
                DEBUGMSG("=> ifndef condition is FALSE (line: %d)\n", token.lineNumber);
                // skip until we find the next:
                // else, elif, endif (but do not consume these tokens)
                if(!ConsumeCurrentBranch()) return;
            }
            break;
        }
        case T_PP_IF:
            searchingForBranch = true;
        case T_PP_ELIF: {
            if(searchingForBranch) {
                // We expect a condition
                if(!CheckIf(ppTable)) {
                    DEBUGMSG("=> if condition is FALSE (line: %d)\n", token.lineNumber);
                    // skip until we find the next:
                    // else, elif, endif (but do not consume these tokens)
                    if(!ConsumeCurrentBranch()) return;

                } else {
                    DEBUGMSG("=> if condition is TRUE (line: %d)\n", token.lineNumber);
                    searchingForBranch = false;
                    // condition is true
                    Parse(pp);
                }
            } else {
                ConsumeBlock();
                return;
            }
            break;
        }
        case T_PP_ELSE: {
            if(searchingForBranch) {
                // if we reached an else, it means that we could not match
                // a if/elif/ifdef condition until now - enter it
                Parse(pp);
                searchingForBranch = false;
            } else {
                // we already found the branch for the current block
                // this means that the 'else' is a stop sign for us
                ConsumeBlock();
                return;
            }
            break;
        }
        case T_PP_ENDIF: {
            return;
        }
        case T_PP_DEFINE: {
            if(!::LexerNext(m_scanner, token) || token.type != T_PP_IDENTIFIER) {
                // Recover
                wxString dummy;
                GetRestOfPPLine(dummy);
                break;
            }
            wxString macroName = token.text;

            wxString macroValue;
            // Optionally get the value
            GetRestOfPPLine(macroValue, m_options & kLexerOpt_CollectMacroValueNumbers);

            CxxPreProcessorToken pp;
            pp.name = macroName;
            pp.value = macroValue;
            // mark this token for deletion when the entire TU parsing is done
            pp.deleteOnExit = (m_options & kLexerOpt_DontCollectMacrosDefinedInThisFile);
            DEBUGMSG("=> Adding macro: %s=%s (line %d)\n", pp.name, pp.value, token.lineNumber);
            ppTable.insert(std::make_pair(pp.name, pp));
            break;
        }
        }
    }
}
Esempio n. 2
0
void CElement::ExecInstructions(const CArray<CInstruction *> *papInstructions, const CParameters *paParameters,
								bool *pReturned, int *pReturnValue)
{
	*pReturned = false;
	for(CArray<CInstruction *>::CIterator i = papInstructions->GetIterator(); i.Exists(); i.Next())
	{
		if(m_Removed)
			break;

		CInstruction *pBaseInstr = i.Get();
		m_pDatabase->SetCurrentInstruction(pBaseInstr->m_LineCount, pBaseInstr->m_Filename);

		if(pBaseInstr->m_Type == INSTRUCTION_TYPE_SET_ATTRIBUTE)
		{
			CSetAttributeInstruction *pInstr = (CSetAttributeInstruction *)pBaseInstr;
			CAttribute *pAttribute = FindAttribute(pInstr->m_AttributeName);
			if(!pAttribute)
			{
				printf("error: unknown attribute '%s'\n", pInstr->m_AttributeName.GetString());
				m_pDatabase->PrintCallstack();
				continue;
			}
			if(pAttribute->m_Const && pAttribute->m_Defined)
			{
				printf("error: attribute const '%s' is already defined\n", pAttribute->m_pName);
				m_pDatabase->PrintCallstack();
			}
			else
			{
				pAttribute->m_Value = ComputeValue(pInstr->m_Value, paParameters);
				pAttribute->m_Defined = true;
#ifdef SPB_DEBUG
				printf("success: attribute '%s' set to %d\n", pAttribute->m_pName, pAttribute->m_Value);
#endif
			}
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_RETURN)
		{
			CReturnInstruction *pInstr = (CReturnInstruction *)pBaseInstr;
			*pReturned = true;
			*pReturnValue = ComputeValue(pInstr->m_Value, paParameters);
#ifdef SPB_DEBUG
			printf("success: returned %d\n", *pReturnValue);
#endif
			return;
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_IF)
		{
			CIfInstruction *pInstr = (CIfInstruction *)pBaseInstr;
			bool True = CheckIf(&pInstr->m_IfData, paParameters);
			if(True)
				ExecInstructions(&pInstr->m_IfData.m_Instructions.m_apList, paParameters, pReturned, pReturnValue);
			else
			{
				for(CArray<CIfData>::CIterator i = pInstr->m_aElsifDatas.GetIterator(); i.Exists(); i.Next())
				{
					CIfData *pElsifData = &i.Get();
					m_pDatabase->SetCurrentInstruction(pElsifData->m_LineCount, pBaseInstr->m_Filename);
					True = CheckIf(pElsifData, paParameters);
					if(True)
					{
						ExecInstructions(&pElsifData->m_Instructions.m_apList, paParameters, pReturned, pReturnValue);
						break;
					}
				}
				if(!True)
					ExecInstructions(&pInstr->m_InstructionsElse.m_apList, paParameters, pReturned, pReturnValue);
			}
			if(*pReturned)
				return;
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_FROM)
		{
			CFromInstruction *pInstr = (CFromInstruction *)pBaseInstr;
			int StartVal = ComputeValue(pInstr->m_StartValue, paParameters);
			int EndVal = ComputeValue(pInstr->m_EndValue, paParameters);
#ifdef SPB_DEBUG
			printf("success: from %d to %d (reverse %d)\n", StartVal, EndVal, pInstr->m_Reverse);
#endif
			CParameters aFromParameters;
			paParameters->GetCopy(&aFromParameters);
			int *pNewParameter = &aFromParameters.Add();
			if(pInstr->m_Reverse)
			{
				for(int v = StartVal; v >= EndVal; v--)
				{
					*pNewParameter = v;
					ExecInstructions(&pInstr->m_Instructions.m_apList, &aFromParameters, pReturned, pReturnValue);
					if(*pReturned)
						return;
				}
			}
			else
			{
				for(int v = StartVal; v <= EndVal; v++)
				{
					*pNewParameter = v;
					ExecInstructions(&pInstr->m_Instructions.m_apList, &aFromParameters, pReturned, pReturnValue);
					if(*pReturned)
						return;
				}
			}
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_CALL_FUNCTION)
		{
			CCallFunctionInstruction *pInstr = (CCallFunctionInstruction *)pBaseInstr;

			CParameters aFunctionParameters;
			for(CArray<CExpression>::CIterator p = pInstr->m_aFunctionParameters.GetIterator(); p.Exists(); p.Next())
				aFunctionParameters.Add(ComputeValue(p.Get(), paParameters));

			if(pInstr->m_This)
				CallFunction(pInstr->m_FunctionName, &aFunctionParameters);
			else if(pInstr->m_Super)
				CallFunction(pInstr->m_FunctionName, &aFunctionParameters, true, pInstr->m_Superclass);
			else
			{
				CParameters aSearchParameters;
				for(CArray<CExpression>::CIterator p = pInstr->m_aSearchParameters.GetIterator(); p.Exists(); p.Next())
					aSearchParameters.Add(ComputeValue(p.Get(), paParameters));

				CArray<CElement *> apElements;
				m_pDatabase->SearchElements(pInstr->m_ElementType, pInstr->m_ElementModelName, pInstr->m_SearchFunction, &aSearchParameters, &apElements);

				for(CArray<CElement *>::CIterator e = apElements.GetIterator(); e.Exists(); e.Next())
				{
					if(!e.Get()->m_Removed)
						e.Get()->CallFunction(pInstr->m_FunctionName, &aFunctionParameters);
				}
			}
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_REMOVE)
		{
			CRemoveInstruction *pInstr = (CRemoveInstruction *)pBaseInstr;
			if(pInstr->m_This)
				m_pDatabase->RemoveElement(this);
			else
			{
				CParameters aSearchParameters;
				for(CArray<CExpression>::CIterator p = pInstr->m_aSearchParameters.GetIterator(); p.Exists(); p.Next())
					aSearchParameters.Add(ComputeValue(p.Get(), paParameters));

				CArray<CElement *> apElements;
				m_pDatabase->SearchElements(pInstr->m_ElementType, pInstr->m_ElementModelName, pInstr->m_SearchFunction, &aSearchParameters, &apElements);

				bool DeleteThis = false;
				for(CArray<CElement *>::CIterator e = apElements.GetIterator(); e.Exists(); e.Next())
				{
					CElement *pElement = e.Get();
					if(pElement->m_Removed)
						continue;
					if(pElement == this)
						DeleteThis = true;
					else
						m_pDatabase->RemoveElement(pElement);
				}
				if(DeleteThis)
					m_pDatabase->RemoveElement(this);
			}
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_ADD)
		{
			CAddInstruction *pInstr = (CAddInstruction *)pBaseInstr;
			CParameters aAddParameters;
			for(CArray<CExpression>::CIterator p = pInstr->m_aAddParameters.GetIterator(); p.Exists(); p.Next())
				aAddParameters.Add(ComputeValue(p.Get(), paParameters));
			m_pDatabase->AddElement(pInstr->m_ElementType, pInstr->m_ElementModelName, &aAddParameters);
		}
		else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_CALL_SYS)
		{
			CCallSysInstruction *pInstr = (CCallSysInstruction *)pBaseInstr;

			CParameters aFunctionParameters;
			for(CArray<CExpression>::CIterator p = pInstr->m_aFunctionParameters.GetIterator(); p.Exists(); p.Next())
				aFunctionParameters.Add(ComputeValue(p.Get(), paParameters));

			m_pDatabase->CallSysFunction(pInstr->m_FunctionName, &aFunctionParameters);
		}
	}
}