void TreeWalker::parseDeclaration(DeclarationAST *node) { switch (node->nodeType()) { case NodeType_AccessDeclaration: parseAccessDeclaration(static_cast<AccessDeclarationAST*>(node)); break; case NodeType_LinkageSpecification: parseLinkageSpecification(static_cast<LinkageSpecificationAST*>(node)); break; case NodeType_Namespace: parseNamespace(static_cast<NamespaceAST*>(node)); break; case NodeType_NamespaceAlias: parseNamespaceAlias(static_cast<NamespaceAliasAST*>(node)); break; case NodeType_Using: parseUsing(static_cast<UsingAST*>(node)); break; case NodeType_UsingDirective: parseUsingDirective(static_cast<UsingDirectiveAST*>(node)); break; case NodeType_Typedef: parseTypedef(static_cast<TypedefAST*>(node)); break; case NodeType_TemplateDeclaration: parseTemplateDeclaration(static_cast<TemplateDeclarationAST*>(node)); break; case NodeType_SimpleDeclaration: parseSimpleDeclaration(static_cast<SimpleDeclarationAST*>(node)); break; case NodeType_FunctionDefinition: parseFunctionDefinition(static_cast<FunctionDefinitionAST*>(node)); break; default: break; } }
bool ClassParser::parseHeader(const char *strHeader, const char *strHeaderFullFilePath) { unsigned int i; unsigned int iCount = strlen(strHeader); int iSquareBracketsOfClassIndex = 0; unsigned int iPosition; bool bIsParsed; EParseAction eAction = PARSE_ACTION_NOTHING; EParseActionSecondary eSecondaryAction = PARSE_ACTION_SECONDARY_NOTHING; for (i=0; i<iCount; i++) { switch (eAction) { case PARSE_ACTION_NOTHING: if (strncmp(strHeader+i, "/*", 2) == 0) { eAction = PARSE_ACTION_COMMENTS_OUT_MULTI_LINE; i++; if (ClassParserFind::findToNextChar(strHeader+i+1, "*/", &iPosition)) { i+=iPosition+2; eAction = PARSE_ACTION_NOTHING; } } else if (strncmp(strHeader+i, "//", 2) == 0) { eAction = PARSE_ACTION_COMMENTS_OUT_SINGLE_LINE; i++; if (ClassParserFind::findToNextChar(strHeader+i+1, "\n", &iPosition)) { i+=iPosition+1; eAction = PARSE_ACTION_NOTHING; } } else { if (eSecondaryAction != PARSE_ACTION_SECONDARY_NOTHING && eSecondaryAction != PARSE_ACTION_SECONDARY_IN_CLASS_BEGIN && eSecondaryAction != PARSE_ACTION_SECONDARY_IN_GOT_CLASS_NAME) { if (strHeader[i] == '{') { iSquareBracketsOfClassIndex++; } else if (strHeader[i] == '}') { iSquareBracketsOfClassIndex--; if (iSquareBracketsOfClassIndex == 0) { eSecondaryAction = PARSE_ACTION_SECONDARY_NOTHING; if (ClassParserFind::findToNextChar(strHeader+i, ";", &iPosition)) { i+=iPosition; } } } } switch (eSecondaryAction) { case PARSE_ACTION_SECONDARY_NOTHING: if (strncmp(strHeader+i, "class", 5) == 0) { ClassParserInformation s; s.m_strClassType = "class"; s.m_strFromHeaderFile = strHeaderFullFilePath; m_listClassInformation.append(s); i += 5; i += parseClass(strHeader+i, m_listClassInformation.size()-1); } else if (strncmp(strHeader+i, "struct", 6) == 0) { ClassParserInformation s; s.m_strClassType = "struct"; s.m_strFromHeaderFile = strHeaderFullFilePath; m_listClassInformation.append(s); i += 6; i += parseClass(strHeader+i, m_listClassInformation.size()-1); } else if (strncmp(strHeader+i, "enum", 4) == 0) { ClassParserInformation s; s.m_strClassType = "enum"; s.m_strFromHeaderFile = strHeaderFullFilePath; m_listClassInformation.append(s); i += 4; i += parseEnum(strHeader+i, m_listClassInformation.size()-1); } else if (strncmp(strHeader+i, "typedef", 7) == 0) { ClassParserInformation s; s.m_strClassType = "typedef"; s.m_strFromHeaderFile = strHeaderFullFilePath; m_listClassInformation.append(s); i += 7; i += parseTypedef(strHeader+i, m_listClassInformation.size()-1); } else if (strncmp(strHeader+i, "template", 8) == 0) { ClassParserInformation s; s.m_strClassType = "template"; s.m_strFromHeaderFile = strHeaderFullFilePath; i += 8; i += ClassParserFind::parseTemplate(strHeader+i, &s); m_listClassInformation.append(s); } else if (strncmp(strHeader+i, "union", 5) == 0) { ClassParserInformation s; s.m_strClassType = "union"; s.m_strFromHeaderFile = strHeaderFullFilePath; i += 5; i += ClassParserFind::parseTemplate(strHeader+i, &s); m_listClassInformation.append(s); } else if (strncmp(strHeader+i, "#define", 7) == 0) { i += 7; i += ClassParserFind::parseDefine(strHeader+i, this); } else if (strncmp(strHeader+i, "#include", 8) == 0) { bool bInPublicIncludeFolders; QString strInclude = ClassParserFind::getIncludeHeader(strHeader+i+8, &iPosition, &bInPublicIncludeFolders); if (strInclude.length() != 0) { i+=8+iPosition; ClassParserIncludeHeaderInformation s; s.m_bInPublicIncludeFolders = bInPublicIncludeFolders; s.m_strIncludeHeader = strInclude; s.m_strIncludeHeaderWithFullFilePath = findFullFilePathForHeaderInformation(&s, strHeaderFullFilePath); bIsParsed = isIncludeHeaderParsed(&s); m_listIncludeHeader.append(s); if (bIsParsed == false && s.m_strIncludeHeaderWithFullFilePath.length() != 0) { QByteArray ba = s.m_strIncludeHeaderWithFullFilePath.toLatin1(); parse(ba.data()); } } } else if (ClassParserFind::skipThisLine(strHeader, i, &iPosition) ) { i=iPosition; } else { i+= ClassParserFind::parsePossibleFunctionFromThisLine(strHeader+i); } break; default: break; } } break; case PARSE_ACTION_COMMENTS_OUT_MULTI_LINE: if (strncmp(strHeader+i, "*/", 2) == 0) { eAction = PARSE_ACTION_NOTHING; i++; } break; case PARSE_ACTION_COMMENTS_OUT_SINGLE_LINE: if (strncmp(strHeader+i, "\n", 1) == 0) { eAction = PARSE_ACTION_NOTHING; i++; } break; } } return false; }
unsigned int ClassParser::parseClass(const char *strHeader, int iClassIndex) { unsigned int i; unsigned int iCount = strlen(strHeader); unsigned int iPreviousImportantActionIndex = 0; int iSquareBracketsIndex = 0; int iSquareBracketsOfClassIndex = 0; int iBracketsIndex = 0; unsigned int iPosition; unsigned int iPositionAdd; int iMacroIndex; bool bInTheQuotes = false; EParseAction eAction = PARSE_ACTION_NOTHING; EParseActionSecondary eSecondaryAction = PARSE_ACTION_SECONDARY_IN_CLASS_BEGIN; EClassParserMemberType eFunctionType = FUNCTION_TYPE_PRIVATE; EClassParserMemberType eMemberType; for (i=0; i<iCount; i++) { switch (eAction) { case PARSE_ACTION_NOTHING: if (bInTheQuotes == false && strncmp(strHeader+i, "/*", 2) == 0) { eAction = PARSE_ACTION_COMMENTS_OUT_MULTI_LINE; i++; if (ClassParserFind::findToNextChar(strHeader+i+1, "*/", &iPosition)) { i+=iPosition+2; eAction = PARSE_ACTION_NOTHING; } } else if (bInTheQuotes == false && strncmp(strHeader+i, "//", 2) == 0) { eAction = PARSE_ACTION_COMMENTS_OUT_SINGLE_LINE; i++; if (ClassParserFind::findToNextChar(strHeader+i+1, "\n", &iPosition)) { i+=iPosition+1; eAction = PARSE_ACTION_NOTHING; } } else { if (eSecondaryAction != PARSE_ACTION_SECONDARY_NOTHING && eSecondaryAction != PARSE_ACTION_SECONDARY_IN_CLASS_BEGIN && eSecondaryAction != PARSE_ACTION_SECONDARY_IN_GOT_CLASS_NAME) { if (strHeader[i] == '{') { iSquareBracketsOfClassIndex++; } else if (strHeader[i] == '}') { iSquareBracketsOfClassIndex--; if (iSquareBracketsOfClassIndex == 0) { eSecondaryAction = PARSE_ACTION_SECONDARY_NOTHING; if (ClassParserFind::findToNextChar(strHeader+i, ";", &iPosition)) { i+=iPosition; return i; } } } } if (bInTheQuotes == false) { if (strHeader[i] == '\"') { bInTheQuotes = true; continue; } } else { if (i == 0 && strHeader[i] == '\"') { bInTheQuotes = false; continue; } else if (i != 0 && strHeader[i-1] != '\\' && strHeader[i] == '\"') { bInTheQuotes = false; continue; } } if (bInTheQuotes == false) { switch (eSecondaryAction) { case PARSE_ACTION_SECONDARY_NOTHING: break; case PARSE_ACTION_SECONDARY_IN_CLASS_BEGIN: eSecondaryAction = PARSE_ACTION_SECONDARY_IN_GOT_CLASS_NAME; iPreviousImportantActionIndex = i; i += ClassParserFind::parseClassName(strHeader+i, &m_listClassInformation[iClassIndex]); if (strHeader[i] == ';') { eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; return i; } else { if (strHeader[i] == '{') { eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; eFunctionType = FUNCTION_TYPE_PRIVATE; iSquareBracketsOfClassIndex++; } } break; case PARSE_ACTION_SECONDARY_IN_GOT_CLASS_NAME: if (strHeader[i] == '{') { eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; eFunctionType = FUNCTION_TYPE_PRIVATE; iSquareBracketsOfClassIndex++; } break; case PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING: case PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FIRST_HAND_INFO: case PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_BRACETS_OUT: if ( !ClassParserFind::isThisEqualToSpace(strHeader[i]) && iSquareBracketsIndex == 0 && iBracketsIndex == 0 && strHeader[i] != '(' && strHeader[i] != '{' && strHeader[i] != ';' && strHeader[i] != ')' && strHeader[i] != '}' && strHeader[i] != '=') { if (eSecondaryAction == PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_BRACETS_OUT) { if (strncmp(strHeader+i, "const", 5) == 0) { i+=4; continue; } else if (iSquareBracketsIndex == 0 && iBracketsIndex == 0) { SClassParserPossibleMacroWithoutKnownledge s; s.m_pType = eFunctionType; s.m_strMacroLine = ClassParserFind::getStringBetween(strHeader, iPreviousImportantActionIndex, i) ; m_listClassInformation[iClassIndex].m_listPossibleMacroWithoutKnownledge.append( s ); } } eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; EClassParserClassMainType eClassType = ClassParserFind::isStartWithClassType(strHeader+i, &iPosition); if (eClassType == CLASS_MAIN_TYPE_CLASS) { ClassParserInformation s; s.m_strClassType = "class"; s.m_iParentClassIndex = iClassIndex; s.m_strFromHeaderFile = m_listClassInformation[iClassIndex].m_strFromHeaderFile; m_listClassInformation.append(s); i += iPosition; i += parseClass(strHeader+i, m_listClassInformation.size()-1); } else if (eClassType == CLASS_MAIN_TYPE_STRUCT) { ClassParserInformation s; s.m_strClassType = "struct"; s.m_iParentClassIndex = iClassIndex; s.m_strFromHeaderFile = m_listClassInformation[iClassIndex].m_strFromHeaderFile; m_listClassInformation.append(s); i += iPosition; i += parseClass(strHeader+i, m_listClassInformation.size()-1); } else if (eClassType == CLASS_MAIN_TYPE_ENUM) { ClassParserInformation s; s.m_strClassType = "enum"; s.m_iParentClassIndex = iClassIndex; s.m_strFromHeaderFile = m_listClassInformation[iClassIndex].m_strFromHeaderFile; m_listClassInformation.append(s); i += iPosition; i += parseEnum(strHeader+i, m_listClassInformation.size()-1); } else if (eClassType == CLASS_MAIN_TYPE_TYPEDEF) { ClassParserInformation s; s.m_strClassType = "typedef"; s.m_iParentClassIndex = iClassIndex; s.m_strFromHeaderFile = m_listClassInformation[iClassIndex].m_strFromHeaderFile; m_listClassInformation.append(s); i += iPosition; i += parseTypedef(strHeader+i, m_listClassInformation.size()-1); } else if (eClassType == CLASS_MAIN_TYPE_TEMPLATE) { ClassParserInformation s; s.m_strClassType = "template"; s.m_iParentClassIndex = iClassIndex; s.m_strFromHeaderFile = m_listClassInformation[iClassIndex].m_strFromHeaderFile; i += iPosition; i += ClassParserFind::parseTemplate(strHeader+i, &s); m_listClassInformation.append(s); } else if (eClassType == CLASS_MAIN_TYPE_UNION) { ClassParserInformation s; s.m_strClassType = "union"; s.m_iParentClassIndex = iClassIndex; s.m_strFromHeaderFile = m_listClassInformation[iClassIndex].m_strFromHeaderFile; i += iPosition; i += ClassParserFind::parseTemplate(strHeader+i, &s); m_listClassInformation.append(s); } else if (ClassParserFind::skipThisLine(strHeader, i, &iPosition) ) { i=iPosition; } else if (isStartWithMacroBeginForFunction(strHeader+i, &iMacroIndex)) { ClassParserFind::getFunctionWithMacroBegin(strHeader, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPosition, m_listMacroBeginForMember[iMacroIndex]); i += iPosition; } else { eMemberType = ClassParserFind::isStartWithMemberType(strHeader+i, &iPosition); if (eMemberType != FUNCTION_TYPE_NONE) { i+=iPosition; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FIRST_HAND_INFO; eFunctionType = eMemberType; } else { eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_OR_DATATYPE; iPreviousImportantActionIndex = i; } } } else if (eSecondaryAction == PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_BRACETS_OUT) { if (strHeader[i] == '{' ) { iSquareBracketsIndex = 1; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_INLINE; } else if (strHeader[i] == ';' ) { // This call creates function from // emit foo(); in inline function. // Also Q_OBJECT handled incorrectly. ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } else if (strHeader[i] == '=' && iBracketsIndex == 0 && iSquareBracketsIndex == 0) { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } } break; case PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_OR_DATATYPE: if (strHeader[i] == ';') { if (iSquareBracketsIndex == 0 && iBracketsIndex == 0) { ClassParserFind::getDataTypeBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex]); } else { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; } eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } else if (strHeader[i] == '(' ) { iBracketsIndex++; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_BRACETS_IN; } break; case PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_BRACETS_IN: if (strHeader[i] == ';' ) { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } else if (strHeader[i] == '(' ) { iBracketsIndex++; } else if (strHeader[i] == ')' ) { iBracketsIndex--; if (iBracketsIndex == 0) { char c = ClassParserFind::findToNextNextValidNonSpaceChar(strHeader+i+1, &iPosition); if (c == '(') { // function? still continues i += iPosition; iBracketsIndex++; } else { eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_BRACETS_OUT; } } } else if (strHeader[i] == '=' && iBracketsIndex == 0 && iSquareBracketsIndex == 0) { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } break; case PARSE_ACTION_SECONDARY_IN_THE_CLASS_GETTING_FUNCTION_INLINE: if (strHeader[i] == '{' ) { iSquareBracketsIndex++; } else if (strHeader[i] == '}' ) { iSquareBracketsIndex--; if (iSquareBracketsIndex==0) { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } } else if (strHeader[i] == ';' ) { if (iSquareBracketsIndex==0) { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } } else if (strHeader[i] == '=') { if (iSquareBracketsIndex == 0) { ClassParserFind::getFunctionBetween(strHeader, iPreviousImportantActionIndex, i, eFunctionType, &m_listClassInformation[iClassIndex], &iPositionAdd, ""); i+=iPositionAdd; eSecondaryAction = PARSE_ACTION_SECONDARY_IN_THE_CLASS_NOTHING; } } break; } } } break; case PARSE_ACTION_COMMENTS_OUT_MULTI_LINE: if (strncmp(strHeader+i, "*/", 2) == 0) { eAction = PARSE_ACTION_NOTHING; i++; } break; case PARSE_ACTION_COMMENTS_OUT_SINGLE_LINE: if (strncmp(strHeader+i, "\n", 1) == 0) { eAction = PARSE_ACTION_NOTHING; i++; } break; } } return i; }