📄 gcppparser.cpp
字号:
Advance(); // move past the "class" or "struct" GCppToken* pTok = GetToken(0); char szTmp[8]; const char* pName; int nNameLen; bool bNoname; if(pTok->Equals("{")) { // no name is specified, so make a random name GetRandomName(szTmp); pName = szTmp; nNameLen = 8; bNoname = true; } else { pName = pTok->GetValue(); nNameLen = pTok->GetLength(); Advance(); pTok = GetToken(0); bNoname = false; } // See if the type already exists GCppType* pType = FindType(pName, nNameLen); GCppStruct* pStruct; if(pType) { // todo: make sure it's a struct or class as appropriate pStruct = (GCppStruct*)pType; } else { // Make a new struct or class char* pStructName = m_pStringHeap->Add(pName, nNameLen); if(bClass) pStruct = new GCppClass(pStructName); else pStruct = new GCppStruct(pStructName); // Add the type to the current scope GetCurrentScope()->m_pTypes->Add(pStructName, pStruct); // Set the comment if(m_pComment) { pStruct->m_pComment = m_pComment; m_pComment = NULL; } } // Parse inheritance and initializers if(bClass) { // Get the parent -- todo: support multiple inherritance if(pTok->Equals(":")) { Advance(); pTok = GetToken(0); if(pTok->Equals("public")) { Advance(); pTok = GetToken(0); } GCppType* pParent = FindType(pTok->GetValue(), pTok->GetLength()); if(!pParent) { //OnError(pTok, "Parent class not found"); } // todo: special-case the "Object" class GCppClass* pClass = (GCppClass*)pStruct; pClass->SetParent((GCppClass*)pParent); // todo: make sure it's a class Advance(); pTok = GetToken(0); } // Skip interfaces and member initializers while(!pTok->Equals(";") && !pTok->Equals("{")) { Advance(); pTok = GetToken(0); } } // If it's just a type declaration, we're done if(pTok->Equals(";")) return pStruct; // if we're doing a typedef and it's not a '{', we're done if(bTypeDef) { if(!pTok->Equals("{")) return pStruct; } // Parse the scope if(pTok->Equals("{")) { Advance(); // Move past the "{" GCppFile* pFile = GetCurrentFile(); if(pFile->IsProjectFile() && !bNoname) pStruct->SetDeclaredInProjectFile(); pStruct->SetSource(pFile->GetFilename(), pFile->GetCurrentLine()); PushScope(pStruct); if(!ParseScope()) return NULL; } // See if it's also a declaration pTok = GetToken(0); if(!bTypeDef && !pTok->Equals(";")) { GCppDeclaration* pDecl = parseDecl2(pStruct, false, false); if(!pDecl) return NULL; if(pDecl->GetDeclType() == GCppDeclaration::VAR) GetCurrentScope()->m_pVariables->Add(pDecl->GetName(), pDecl); else if(pDecl->GetDeclType() == GCppDeclaration::METHOD) GetCurrentScope()->m_pMethods->Add(pDecl->GetName(), pDecl); else { delete(pDecl); OnError(GetToken(0), "unexpected declaration type"); return NULL; } } return pStruct;}bool GCppParser::ParseEnum(){ GCppEnum* pEnum = ParseEnum(false); if(pEnum) return true; else return false;}GCppEnum* GCppParser::ParseEnum(bool bTypeDef){ // Find or make the enum Advance(); // move past the "enum" GCppToken* pTok = GetToken(0); GCppType* pType = NULL; if(!pTok->Equals("{")) pType = FindType(pTok->GetValue(), pTok->GetLength()); GCppEnum* pEnum; bool bNoname = false; if(pType) { // todo: make sure it's an enum pEnum = (GCppEnum*)pType; bNoname = !pEnum->IsDeclaredInProjectFile(); } else { // Get a name for the enum 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; bNoname = true; } else { // use the specified name pName = pTok->GetValue(); nNameLen = pTok->GetLength(); Advance(); bNoname = false; } // make the enum char* pEnumName = m_pStringHeap->Add(pName, nNameLen); pEnum = new GCppEnum(pEnumName); // Add the type to the current scope GetCurrentScope()->m_pTypes->Add(pEnumName, pEnum); // Set the comment if(m_pComment) { pEnum->m_pComment = m_pComment; m_pComment = NULL; } } // If it's just a declaration, we're done pTok = GetToken(0); if(pTok->Equals(";")) return pEnum; // if we're doing a typedef and it's not a '{', we're done if(bTypeDef) { if(!pTok->Equals("{")) return pEnum; } // Just skip the scope--todo: don't skip it if(pTok->Equals("{")) { if(GetCurrentFile()->IsProjectFile() && !bNoname) pEnum->SetDeclaredInProjectFile(); Advance(); // Move past the "{" while(true) { pTok = GetToken(0); if(pTok->GetLength() == 0) break; if(pTok->Equals("}")) break; GAssert(!pTok->Equals("{"), "unexpected '{' inside enum"); Advance(); } Advance(); // Move past the "}: } // See if it's also a declaration pTok = GetToken(0); if(!bTypeDef && !pTok->Equals(";")) { GCppDeclaration* pDecl = parseDecl2(pEnum, false, false); if(!pDecl) return NULL; if(pDecl->GetDeclType() == GCppDeclaration::VAR) GetCurrentScope()->m_pVariables->Add(pDecl->GetName(), pDecl); else if(pDecl->GetDeclType() == GCppDeclaration::METHOD) GetCurrentScope()->m_pMethods->Add(pDecl->GetName(), pDecl); else { delete(pDecl); OnError(GetToken(0), "unexpected declaration type"); return NULL; } } return pEnum;}bool GCppParser::ParseFriend(){ Advance(); // Move past the "friend" token while(true) { GCppToken* pTok = GetToken(0); if(pTok->GetLength() < 1 || pTok->Equals(";")) break; Advance(); } return true;}bool GCppParser::ParseSetAccess(GCppAccess eAccess){ Advance(); GCppToken* pTok = GetToken(0); if(!pTok->Equals(":")) return OnError(pTok, "Expected a ':'"); Advance(); // Move past the ':' GetCurrentScope()->m_eCurrentAccess = eAccess; return true;}bool GCppParser::ParseMethodModifier(GCppMethodModifier eModifier){ Advance(); m_eMethodModifiers |= eModifier; return true;}bool GCppParser::ParseVarModifier(GCppVarModifier eModifier){ Advance(); if(eModifier == VM_POINTER && ((m_eVarModifiers & VM_POINTER) != 0)) { m_eVarModifiers &= (~VM_POINTER); eModifier = VM_POINTERPOINTER; } m_eVarModifiers |= eModifier; return true;}bool GCppParser::ParseDeclaration(){ GCppDeclaration* pDecl = ParseDecl(false); if(!pDecl) return false; if(pDecl->GetDeclType() == GCppDeclaration::VAR) { GetCurrentScope()->m_pVariables->Add(pDecl->GetName(), pDecl); return true; } else if(pDecl->GetDeclType() == GCppDeclaration::METHOD) { GetCurrentScope()->m_pMethods->Add(pDecl->GetName(), pDecl); return true; } delete(pDecl); OnError(GetToken(0), "unexpected declaration type"); return false;}GCppType* GCppParser::ParseTypeRef(bool bParam, bool bTypeDef){ // Skip any type specifiers GCppToken* pTok = GetToken(0); if(pTok->Equals("class") || pTok->Equals("struct") || pTok->Equals("enum")) Advance(); // Parse any prefix modifiers while(true) { pTok = GetToken(0); if(pTok->Equals("const")) ParseVarModifier(VM_CONST); else if(pTok->Equals("unsigned")) ParseVarModifier(VM_UNSIGNED); else break; } // Find the type pTok = GetToken(0); GCppType* pType = FindType(pTok->GetValue(), pTok->GetLength()); if(!pType) { OnError(pTok, "undeclared identifier"); return NULL; } Advance(); if(!bTypeDef) ParseSuffixModifiers(bParam); return pType;}void GCppParser::ParseSuffixModifiers(bool bParam){ // Parse any suffix modifiers while(true) { GCppToken* pTok = GetToken(0); if(bParam && pTok->Equals("&")) ParseVarModifier(VM_REFERENCE); else if(pTok->Equals("*")) ParseVarModifier(VM_POINTER); else if(pTok->Equals("__cdecl")) Advance();// else if(pTok->Equals("near"))// Advance();// else if(pTok->Equals("far"))// Advance();// else if(pTok->Equals("NEAR"))// Advance();// else if(pTok->Equals("FAR"))// Advance();// else if(pTok->Equals("POINTER_64"))// Advance();// else if(pTok->Equals("APIENTRY"))// Advance();// else if(pTok->Equals("NTAPI"))// Advance();// else if(pTok->Equals("WINAPI"))// Advance();// else if(pTok->Equals("RESTRICTED_POINTER"))// Advance();// else if(pTok->Equals("UNALIGNED"))// Advance(); else break; }}GCppDeclaration* GCppParser::ParseDecl(bool bParam){ // See if it's a destructor bool bDestructor = false; GCppToken* pTok = GetToken(0); if(pTok->Equals("~")) { bDestructor = true; Advance(); } // Parse the type GCppType* pType = ParseTypeRef(bParam, false); if(!pType) return NULL; return parseDecl2(pType, bParam, bDestructor);}GCppDeclaration* GCppParser::parseDecl2(GCppType* pType, bool bParam, bool bDestructor){ ParseSuffixModifiers(bParam); // Parse scope specifiers bool bScopeSpecified = false; if(GetToken(1)->Equals(":") && GetToken(2)->Equals(":")) { GCppToken* pTok = GetToken(0); GCppType* pType = FindType(pTok->GetValue(), pTok->GetLength()); if(!pType) { OnError(pTok, "Unrecognized type"); return NULL; } bScopeSpecified = true; PushScope(pType); } // Parse the declaration GCppDeclaration* pDecl = parseDecl3(pType, bParam, bDestructor); // Undo any specified scope if(bScopeSpecified) { if(!PopScope()) return NULL; } return pDecl;}GCppDeclaration* GCppParser::parseDecl3(GCppType* pType, bool bParam, bool bDestructor){ // See if it's a constructor bool bConstructor = false; const char* szName; GCppToken* pTok = GetToken(0); if(pTok->Equals("(")) { if(pType != GetCurrentScope()) { OnError(pTok, "Constructor name doesn't match type"); return NULL; } if(bDestructor) { char* pTmp = (char*)alloca(strlen(pType->m_szName) + 2); strcpy(pTmp, "~"); strcat(pTmp, pType->m_szName); szName = m_pStringHeap->Add(pTmp); m_eMethodModifiers |= MM_DESTRUCTOR; } else { szName = pType->m_szName; bConstructor = true; m_eMethodModifiers |= MM_CONSTRUCTOR; } } else if(pTok->GetLength() <= 0 || (bParam && (pTok->Equals(")") || pTok->Equals(",")) || pTok->Equals(":"))) { szName = "<unnamed>"; } else { szName = m_pStringHeap->Add(pTok->GetValue(), pTok->GetLength()); Advance(); } pTok = GetToken(0); // See if it's an array declaration while(pTok->Equals("[")) { m_eVarModifiers |= VM_ARRAY; Advance(); // move past the "[" // Skip the count of elements while(true) { pTok = GetToken(0); if(pTok->GetLength() <= 0 || pTok->Equals("]")) break; Advance(); } Advance(); // move past the "]" pTok = GetToken(0); } // Swallow any bit specifiers if(pTok->Equals(":")) { Advance(); // Move past the ':' Advance(); // Move past the bit count pTok = GetToken(0); } // if it's a variable declaration, make it now if(pTok->Equals(";") || pTok->Equals("=") || pTok->Equals(",") || (bParam && pTok->Equals(")"))) { // Skip default parameter values if(bParam && pTok->Equals("=")) { Advance(); while(true) { pTok = GetToken(0); if(pTok->GetLength() <= 0 || pTok->Equals(",") || pTok->Equals(")")) break; Advance(); } } // Create the variable declaration unsigned int eVarModifiers = m_eVarModifiers; m_eVarModifiers = 0; GCppVariable* pNewVar = new GCppVariable(pType, szName, GetCurrentScope()->m_eCurrentAccess, (GCppVarModifier)eVarModifiers); GCppFile* pFile = GetCurrentFile(); if(pFile->IsProjectFile()) pNewVar->SetDeclaredInProjectFile(); pNewVar->SetSource(pFile->GetFilename(), pFile->GetCurrentLine()); if(m_pComment) { pNewVar->m_pComment = m_pComment; m_pComment = NULL; } return pNewVar; } // Move past the "(" if(bParam || !pTok->Equals("(")) { OnError(pTok, "unexpected token in declaration"); return NULL; } Advance(); // Move past the "(" token // Parse the parameters unsigned int eMethodModifiers = m_eMethodModifiers; Holder<GCppMethod*> hMethod(new GCppMethod(pType, GetCurrentScope(), szName, GetCurrentScope()->m_eCurrentAccess, (GCppMethodModifier)eMethodModifiers)); GCppFile* pFile = GetCurrentFile(); if(m_pComment) { hMethod.Get()->m_pComment = m_pComment; m_pComment = NULL; } if(pFile->IsProjectFile()) hMethod.Get()->SetDeclaredInProjectFile(); hMethod.Get()->SetSource(pFile->GetFilename(), pFile->GetCurrentLine()); m_eMethodModifiers = 0; while(true) { pTok = GetToken(0); if(pTok->Equals(")"))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -