📄 gcppparser.cpp
字号:
break; if(pTok->Equals(".") && GetToken(1)->Equals(".") && GetToken(2)->Equals(".")) { Advance(); Advance(); Advance(); hMethod.Get()->AddModifier(MM_VARARG); } else { GCppDeclaration* pVar = ParseDecl(true); if(!pVar) return NULL; if(pVar->GetDeclType() != GCppDeclaration::VAR) { OnError(GetToken(0), "Expected a variable declaration"); return NULL; } hMethod.Get()->AddParameter((GCppVariable*)pVar); } pTok = GetToken(0); if(pTok->Equals(",")) Advance(); else if(!pTok->Equals(")")) { OnError(pTok, "Expected a ',' or ')'"); return NULL; } } if(!pTok->Equals(")")) { OnError(pTok, "expected a ')'"); return NULL; } Advance(); pTok = GetToken(0); // Check for abstract "=0" suffix if(pTok->Equals("=")) { Advance(); // skip the '=' Advance(); // skip the '0' hMethod.Get()->AddModifier(MM_ABSTRACT); pTok = GetToken(0); } // Skip member initializers and base constructor calls if(bConstructor) { while(true) { pTok = GetToken(0); if(pTok->GetLength() <= 0 || pTok->Equals(";") || pTok->Equals("{")) break; Advance(); } } // Skip the body if(pTok->Equals("{")) { if(!ParseMethodBody(hMethod.Get())) return NULL; } return hMethod.Drop();}GCppType* GCppParser::ParseFunctionPointer(const char** ppName){ // Parse the return type GCppType* pRetType = ParseTypeRef(false, false); if(!pRetType) return NULL; GCppToken* pTok = GetToken(0); if(!pTok->Equals("(")) { OnError(pTok, "This doesn't look like the definition of a function pointer"); return NULL; } Advance(); // move past the "(" // Skip any modifiers while(true) { pTok = GetToken(0); if(pTok->Equals("*")) break; else if(pTok->GetLength() < 0 || pTok->Equals(")") || pTok->Equals(";")) { OnError(pTok, "This doesn't look like the definition of a function pointer"); return NULL; } Advance(); } Advance(); // Move past the '*' // Parse the name pTok = GetToken(0); char szTmp[8]; const char* pName; int nNameLen; if(pTok->Equals("(")) { // no name is specified, so make a random name GetRandomName(szTmp); pName = szTmp; nNameLen = 8; } else { pName = pTok->GetValue(); nNameLen = pTok->GetLength(); Advance(); pTok = GetToken(0); } *ppName = m_pStringHeap->Add(pName, nNameLen); // Move past the ")" if(!pTok->Equals(")")) { *ppName = NULL; OnError(pTok, "Expected a ')'"); return NULL; } Advance(); // Move past the ")" // Eat the parameters pTok = GetToken(0); if(!pTok->Equals("(")) { *ppName = NULL; OnError(pTok, "Expected a '(' -- possibly an extra semi-colon there"); return NULL; } Advance(); // Move past the "(" int nParams = 1; while(nParams > 0) { pTok = GetToken(0); if(pTok->Equals("(")) nParams++; else if(pTok->Equals(")")) nParams--; Advance(); } // Make a random name for the type char szTmp2[8]; GetRandomName(szTmp2); char* szTypeName = m_pStringHeap->Add(szTmp2, 8); // Make the type and add it to the current scope GCppType* pNewType = new GCppFuncPtr(szTypeName); GetCurrentScope()->m_pTypes->Add(szTypeName, pNewType); //if(GetCurrentFile()->IsProjectFile()) // pNewType->SetDeclaredInProjectFile(); return pNewType;}bool GCppParser::ParseTypeDef(){ Advance(); // move past the "typedef" token // Parse the type const char* szTypeName = NULL; GCppToken* pTok = GetToken(0); GCppType* pType; if(pTok->Equals("struct")) pType = ParseStruct2(false, true); else if(pTok->Equals("class")) pType = ParseStruct2(true, true); else if(pTok->Equals("enum")) pType = ParseEnum(true); else if(pTok->Equals("union")) pType = ParseUnion2(true); else if(GetToken(1)->Equals("(")) pType = ParseFunctionPointer(&szTypeName); else pType = ParseTypeRef(false, true); if(!pType) return false; // Add the type to the current scope pTok = GetToken(0); while(true) { // Ignore any modifiers ParseSuffixModifiers(false); // todo: consume the modifiers // Make the new type pTok = GetToken(0); if(szTypeName == NULL) { szTypeName = m_pStringHeap->Add(pTok->GetValue(), pTok->GetLength()); Advance(); pTok = GetToken(0); } GetCurrentScope()->m_pTypes->Add(szTypeName, pType); szTypeName = NULL; // hack for winnt.h if(pTok->Equals("[")) { Advance(); Advance(); Advance(); pTok = GetToken(0); } // See if there's another identifier for this type if(!pTok->Equals(",")) break; Advance(); // Move past the "," } return true;}GCppMethod* GCppParser::GetVarReferencedMethod(GCppType* pType){ while(true) { GCppToken* pTok = GetToken(0); if(pTok->Equals(".") || pTok->Equals("->")) Advance(); else break; pTok = GetToken(0); GCppMethod* pTargetMethod = FindMethod(pTok->GetValue(), pTok->GetLength(), pType); if(pTargetMethod) return pTargetMethod; GCppVariable* pVar = FindVariable(pTok->GetValue(), pTok->GetLength(), pType); if(!pVar) break; pType = pVar->GetType(); Advance(); // Move past the var name } return NULL;}bool GCppParser::ParseMethodBody(GCppMethod* pMethod){ Advance(); // move past the "{" token int nLevel = 1; bool bLineStart = true; while(nLevel > 0) { GCppToken* pTok = GetToken(0); if(pTok->GetLength() == 0) return OnError(pTok, "Unexpected end of file"); if(pTok->Equals("{")) { nLevel++; bLineStart = true; } else if(pTok->Equals("}")) { nLevel--; bLineStart = true; } else { // See if it's a local variable declaration if(bLineStart) { GCppType* pType = FindType(pTok->GetValue(), pTok->GetLength()); if(pType) { Advance(); // Move past the type while(true) { ParseSuffixModifiers(false); pTok = GetToken(0); if(pTok->GetLength() <= 0 || pTok->m_pFile->m_pFile[pTok->m_nStart] < 'A' || pTok->m_pFile->m_pFile[pTok->m_nStart] > 'z') break; // Make the local variable char* szName = m_pStringHeap->Add(pTok->GetValue(), pTok->GetLength()); GCppVariable* pNewVar = new GCppVariable(pType, szName, GetCurrentScope()->m_eCurrentAccess, (GCppVarModifier)m_eVarModifiers); m_eVarModifiers = 0; GCppFile* pFile = GetCurrentFile(); if(pFile->IsProjectFile()) pNewVar->SetDeclaredInProjectFile(); pNewVar->SetSource(pFile->GetFilename(), pFile->GetCurrentLine()); if(!pMethod->m_pLocals) pMethod->m_pLocals = new GConstStringHashTable(7, true); pMethod->m_pLocals->Add(szName, pNewVar); // See if there's more variables in a comma-list Advance(); pTok = GetToken(0); if(pTok->Equals(",")) Advance(); else break; } m_eVarModifiers = 0; } } // Look for direct method reference GCppMethod* pTargetMethod = FindMethod(pTok->GetValue(), pTok->GetLength()); // Look for variable-referenced method if(!pTargetMethod) { GCppVariable* pVar = FindVariable(pTok->GetValue(), pTok->GetLength(), pMethod); if(pVar) { Advance(); // move past the var name pTargetMethod = GetVarReferencedMethod(pVar->GetType()); } } // Look for type-referenced method if(!pTargetMethod) { GCppType* pType = FindType(pTok->GetValue(), pTok->GetLength()); if(pType) { Advance(); pTok = GetToken(0); if(pTok->Equals(":")) { Advance(); pTok = GetToken(0); if(pTok->Equals(":")) { Advance(); pTok = GetToken(0); pTargetMethod = FindMethod(pTok->GetValue(), pTok->GetLength(), pType); } } } } // Consume the method call(s) if(pTargetMethod) { while(true) { // Add the call if(!pMethod->m_pCalls) pMethod->m_pCalls = new GPointerArray(16); pMethod->m_pCalls->AddPointer(pTargetMethod); // Check for method calls on the return type Advance(); // Move past the method name pTok = GetToken(0); if(pTok->Equals("(")) { // Move past the parameters int nLevel = 1; while(nLevel > 0) { Advance(); pTok = GetToken(0); if(pTok->GetLength() <= 0 || pTok->Equals("{") || pTok->Equals("}")) return OnError(pTok, "Expected a ')'"); if(pTok->Equals("(")) nLevel++; else if(pTok->Equals(")")) nLevel--; } Advance(); pTok = GetToken(0); // Check for another call pTargetMethod = GetVarReferencedMethod(pTargetMethod->GetType()); if(!pTargetMethod) break; } } } bLineStart = false; if(pTok->Equals(";")) bLineStart = true; } Advance(); } return true;}bool MacroCompare(const char* szBody, const char* szParam, int* nSize){ *nSize = 0; while(true) { if(*szParam <= ' ' || *szParam == ',' || *szParam == ')') break; if(*szBody != *szParam) return false; szBody++; szParam++; (*nSize)++; } if((*szBody >= 'A' && *szBody <= 'Z') || (*szBody >= 'a' && *szBody <= 'z') || (*szBody >= '0' && *szBody <= '9') || *szBody == '_') return false; return true;}#define MAX_MACRO_PARAMS 25bool GCppParser::ParseMacro(const char* szDef){ // Parse the macro definition params int nDefPos = 0; int nParamCount = 0; const char* pParamDefs[MAX_MACRO_PARAMS]; if(szDef && szDef[nDefPos] == '(') { bool bNewParam = true; while(true) { nDefPos++; if(szDef[nDefPos] == ')' || szDef[nDefPos] == '\0') break; if(bNewParam && szDef[nDefPos] > ' ') { pParamDefs[nParamCount++] = &szDef[nDefPos]; bNewParam = false; } else if(szDef[nDefPos] == ',') bNewParam = true; if(nParamCount >= MAX_MACRO_PARAMS) break; } if(szDef[nDefPos] == ')') nDefPos++; } // Parse the macro implementation params GAssert(m_nActiveTokens > 0, "expected a macro token"); m_nActiveTokens--; // undo the macro name token if(!szDef) return true; const char* pParamImpls[MAX_MACRO_PARAMS]; if(nParamCount > 0) { GetNextToken(); // Read the next token GCppToken* pTok = GetToken(m_nActiveTokens - 1); if(!pTok->Equals("(")) return OnError(pTok, "Expected a '('"); m_nActiveTokens--; // undo the "(" token int nImplParams = 0; GetNextToken(); pTok = GetToken(m_nActiveTokens - 1); while(true) { if(pTok->Equals(")")) break; if(nImplParams >= MAX_MACRO_PARAMS) break; pParamImpls[nImplParams++] = pTok->GetValue(); m_nActiveTokens--; // undo the token GetNextToken(); pTok = GetToken(m_nActiveTokens - 1); if(pTok->Equals(")")) break; if(!pTok->Equals(",")) return OnError(pTok, "Expected a ',' or ')'"); m_nActiveTokens--; // undo the ',' token GetNextToken(); pTok = GetToken(m_nActiveTokens - 1); } if(nImplParams < nParamCount) return OnError(pTok, "Not enough macro parameters"); m_nActiveTokens--; // undo the ')' token } // Make an implementation of the macro (in two passes) char* szBuf = NULL; int nBufPos; int nPass; for(nPass = 0; nPass < 2; nPass++) { nBufPos = 0; const char* szDefBody = &szDef[nDefPos]; bool bTokenStart = true; int nParamSize = 0; while(*szDefBody != '\0') { if(*szDefBody == '#') { szDefBody++; continue; } // See if we've got a parameter const char* szParam = NULL; if(bTokenStart && *szDefBody >= 'A') { bTokenStart = false; int i; for(i = 0; i < nParamCount; i++) { if(MacroCompare(szDefBody, pParamDefs[i], &nParamSize)) { szParam = pParamImpls[i]; break; } } } // See if we're on a token delimeter if(*szDefBody < 'A' || *szDefBody > 'z' || (*szDefBody > 'Z' && *szDefBody < 'a' && *szDefBody != '_')) bTokenStart = true; // Update the buffer if(szParam) { // Do the parameter replacement szDefBody += nParamSize; while(true) { if(*szParam <= ' ' || *szParam == ',' || *szParam == ')') break; if(nPass > 0) szBuf[nBufPos] = *szParam; nBufPos++; szParam++; } } else { if(nPass > 0) szBuf[nBufPos] = *szDefBody; nBufPos++; szDefBody++; } } if(nPass == 0) szBuf = new char[nBufPos + 10]; else szBuf[nBufPos] = '\0'; } // Parse the buffer like a #include file char szOldDir[256]; getcwd(szOldDir, 256); bool bProjectFile = GetCurrentFile()->IsProjectFile(); PushBuffer(szBuf, szOldDir, bProjectFile, GetCurrentFile()->GetFilename()); return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -