bool CSeqParser::parseClassDeclare( char* &start, char *end, wd::CSeqLog &log, std::list< std::pair< char*, std::string > > &error_info ) { for( char chr = *start; chr != '\0'; chr = *start ) { switch ( chr ) { //类注释 case '/': log.classDescript = takeNextRemake( start, end ); break; //取得下一个可解释字符串 case '\r': case '\n': case ' ': case '\t': gotoNextChar( start, end ); break; case '#': gotoNextLine( start, end ); break; //不应该出现;号 case ';': ++start; pushErrorInfo( error_info, start, "不应该出现的符号 ';'" ); break; case ':': log.classParent = takeNextWord( ++start, end ); if ( log.classParent.empty() ) pushErrorInfo( error_info, start, "类继承缺少父类名称" ); break; case '{': parseClassInfo( ++start, end, log, error_info ); return true; default: if ( !checkChar( chr ) ) { pushErrorInfo( error_info, start, "遇到不可解释的符号, 期望是一个字母、数字和半角下划线" ); return false; } log.className = takeNextWord( start, end ); if ( log.className.empty() ) { pushErrorInfo( error_info, start, "声明类时缺失类名声明" ); return false; } break; } } pushErrorInfo( error_info, start, ( "找不到类 [" + log.className + "] 的 '{' , 类定义失败" ).c_str() ); return false; }
void MetaInfoPrivate::parseNonQmlClassRecursively(const QMetaObject *qMetaObject) { Q_ASSERT_X(qMetaObject, Q_FUNC_INFO, "invalid QMetaObject"); QString typeName; int majorVersion = -1; int minorVersion = -1; typeInfo(qMetaObject, &typeName, &majorVersion, &minorVersion); if (typeName.isEmpty()) { qWarning() << "Meta type system: Registered class has no name."; return; } NodeMetaInfo existingInfo = m_q->nodeMetaInfo(typeName, majorVersion, minorVersion); if (existingInfo.isValid() && existingInfo.majorVersion() == majorVersion && existingInfo.minorVersion() == minorVersion) { return; } NodeMetaInfo nodeMetaInfo(*m_q); nodeMetaInfo.setType(typeName, majorVersion, minorVersion); parseProperties(nodeMetaInfo, qMetaObject); parseClassInfo(nodeMetaInfo, qMetaObject); QString superTypeName; int superTypeMajorVersion = -1; int superTypeMinorVersion = -1; if (qMetaObject->superClass()) { typeInfo(qMetaObject->superClass(), &superTypeName, &superTypeMajorVersion, &superTypeMinorVersion); nodeMetaInfo.setSuperClass(superTypeName, superTypeMajorVersion, superTypeMinorVersion); } if (debug) qDebug() << "adding non qml type" << nodeMetaInfo.typeName() << nodeMetaInfo.majorVersion() << nodeMetaInfo.minorVersion() << ", parent type" << superTypeName << superTypeMajorVersion << superTypeMinorVersion; m_q->addNodeInfo(nodeMetaInfo); if (const QMetaObject *superClass = qMetaObject->superClass()) parseNonQmlClassRecursively(superClass); }
void Moc::parse() { QList<NamespaceDef> namespaceList; bool templateClass = false; while (hasNext()) { Token t = next(); switch (t) { case NAMESPACE: { int rewind = index; if (test(IDENTIFIER)) { if (test(EQ)) { // namespace Foo = Bar::Baz; until(SEMIC); } else if (!test(SEMIC)) { NamespaceDef def; def.name = lexem(); next(LBRACE); def.begin = index - 1; until(RBRACE); def.end = index; index = def.begin + 1; namespaceList += def; index = rewind; } } break; } case SEMIC: case RBRACE: templateClass = false; break; case TEMPLATE: templateClass = true; break; case MOC_INCLUDE_BEGIN: currentFilenames.push(symbol().unquotedLexem()); break; case MOC_INCLUDE_END: currentFilenames.pop(); break; case Q_DECLARE_INTERFACE_TOKEN: parseDeclareInterface(); break; case Q_DECLARE_METATYPE_TOKEN: parseDeclareMetatype(); break; case USING: if (test(NAMESPACE)) { while (test(SCOPE) || test(IDENTIFIER)) ; next(SEMIC); } break; case CLASS: case STRUCT: { if (currentFilenames.size() <= 1) break; ClassDef def; if (!parseClassHead(&def)) continue; while (inClass(&def) && hasNext()) { if (next() == Q_OBJECT_TOKEN) { def.hasQObject = true; break; } } if (!def.hasQObject) continue; for (int i = namespaceList.size() - 1; i >= 0; --i) if (inNamespace(&namespaceList.at(i))) def.qualified.prepend(namespaceList.at(i).name + "::"); knownQObjectClasses.insert(def.classname); knownQObjectClasses.insert(def.qualified); continue; } default: break; } if ((t != CLASS && t != STRUCT)|| currentFilenames.size() > 1) continue; ClassDef def; if (parseClassHead(&def)) { FunctionDef::Access access = FunctionDef::Private; for (int i = namespaceList.size() - 1; i >= 0; --i) if (inNamespace(&namespaceList.at(i))) def.qualified.prepend(namespaceList.at(i).name + "::"); while (inClass(&def) && hasNext()) { switch ((t = next())) { case PRIVATE: access = FunctionDef::Private; if (test(Q_SIGNALS_TOKEN)) error("Signals cannot have access specifier"); break; case PROTECTED: access = FunctionDef::Protected; if (test(Q_SIGNALS_TOKEN)) error("Signals cannot have access specifier"); break; case PUBLIC: access = FunctionDef::Public; if (test(Q_SIGNALS_TOKEN)) error("Signals cannot have access specifier"); break; case CLASS: { ClassDef nestedDef; if (parseClassHead(&nestedDef)) { while (inClass(&nestedDef) && inClass(&def)) { t = next(); if (t >= Q_META_TOKEN_BEGIN && t < Q_META_TOKEN_END) error("Meta object features not supported for nested classes"); } } } break; case Q_SIGNALS_TOKEN: parseSignals(&def); break; case Q_SLOTS_TOKEN: switch (lookup(-1)) { case PUBLIC: case PROTECTED: case PRIVATE: parseSlots(&def, access); break; default: error("Missing access specifier for slots"); } break; case Q_OBJECT_TOKEN: def.hasQObject = true; if (templateClass) error("Template classes not supported by Q_OBJECT"); if (def.classname != "Qt" && def.classname != "QObject" && def.superclassList.isEmpty()) error("Class contains Q_OBJECT macro but does not inherit from QObject"); break; case Q_GADGET_TOKEN: def.hasQGadget = true; if (templateClass) error("Template classes not supported by Q_GADGET"); break; case Q_PROPERTY_TOKEN: parseProperty(&def); break; case Q_ENUMS_TOKEN: parseEnumOrFlag(&def, false); break; case Q_FLAGS_TOKEN: parseEnumOrFlag(&def, true); break; case Q_DECLARE_FLAGS_TOKEN: parseFlag(&def); break; case Q_CLASSINFO_TOKEN: parseClassInfo(&def); break; case Q_INTERFACES_TOKEN: parseInterfaces(&def); break; case Q_PRIVATE_SLOT_TOKEN: parseSlotInPrivate(&def, access); break; case Q_PRIVATE_PROPERTY_TOKEN: parsePrivateProperty(&def); break; case ENUM: { EnumDef enumDef; if (parseEnum(&enumDef)) def.enumList += enumDef; } break; default: FunctionDef funcDef; funcDef.access = access; int rewind = index; if (parseMaybeFunction(&def, &funcDef)) { if (funcDef.isConstructor) { if ((access == FunctionDef::Public) && funcDef.isInvokable) { def.constructorList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.constructorList += funcDef; } } } else if (funcDef.isDestructor) { // don't care about destructors } else { if (access == FunctionDef::Public) def.publicList += funcDef; if (funcDef.isSlot) { def.slotList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.slotList += funcDef; } } else if (funcDef.isSignal) { def.signalList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.signalList += funcDef; } } else if (funcDef.isInvokable) { def.methodList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def.methodList += funcDef; } } } } else { index = rewind; } } } next(RBRACE); if (!def.hasQObject && !def.hasQGadget && def.signalList.isEmpty() && def.slotList.isEmpty() && def.propertyList.isEmpty() && def.enumDeclarations.isEmpty()) continue; // no meta object code required if (!def.hasQObject && !def.hasQGadget) error("Class declarations lacks Q_OBJECT macro."); checkSuperClasses(&def); checkProperties(&def); classList += def; knownQObjectClasses.insert(def.classname); knownQObjectClasses.insert(def.qualified); } } }