moc 源碼

http://cep.xor.aps.anl.gov/software/qt4-x11-4.2.2-browser/d5/d3c/moc_8cpp-source.html
moc源碼,網站不錯
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the tools applications of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at [email protected].
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "moc.h"
00025 #include "generator.h"
00026 #include "qdatetime.h"
00027 #include "utils.h"
00028 #include "outputrevision.h"
00029 
00030 // for normalizeTypeInternal
00031 #include <private/qmetaobject_p.h>
00032 
00033 // only moc needs this function
00034 static QByteArray normalizeType(const char *s, bool fixScope = false)
00035 {
00036     int len = qstrlen(s);
00037     char stackbuf[64];
00038     char *buf = (len >= 64 ? new char[len + 1] : stackbuf);
00039     char *d = buf;
00040     char last = 0;
00041     while(*s && is_space(*s))
00042         s++;
00043     while (*s) {
00044         while (*s && !is_space(*s))
00045             last = *d++ = *s++;
00046         while (*s && is_space(*s))
00047             s++;
00048         if (*s && is_ident_char(*s) && is_ident_char(last))
00049             last = *d++ = ' ';
00050     }
00051     *d = '/0';
00052     QByteArray result;
00053     if (strncmp("void", buf, d - buf) != 0)
00054         result = normalizeTypeInternal(buf, d, fixScope);
00055     if (buf != stackbuf)
00056         delete [] buf;
00057     return result;
00058 }
00059 
00060 bool Moc::parseClassHead(ClassDef *def)
00061 {
00062     // figure out whether this is a class declaration, or only a
00063     // forward or variable declaration.
00064     int i = 0;
00065     Token token;
00066     do {
00067         token = lookup(i++);
00068         if (token == COLON || token == LBRACE)
00069             break;
00070         if (token == SEMIC || token == RANGLE)
00071             return false;
00072     } while (token);
00073 
00074     if (!test(IDENTIFIER)) // typedef struct { ... }
00075         return false;
00076     QByteArray name = lexem();
00077 
00078     // support "class IDENT name" and "class IDENT(IDENT) name"
00079     if (test(LPAREN)) {
00080         until(RPAREN);
00081         next(IDENTIFIER);
00082         name = lexem();
00083     } else  if (test(IDENTIFIER)) {
00084         name = lexem();
00085     }
00086 
00087     def->qualified += name;
00088     while (test(SCOPE)) {
00089         def->qualified += lexem();
00090         if (test(IDENTIFIER)) {
00091             name = lexem();
00092             def->qualified += name;
00093         }
00094     }
00095     def->classname = name;
00096     if (test(COLON)) {
00097         do {
00098             test(VIRTUAL);
00099             FunctionDef::Access access = FunctionDef::Public;
00100             if (test(PRIVATE))
00101                 access = FunctionDef::Private;
00102             else if (test(PROTECTED))
00103                 access = FunctionDef::Protected;
00104             else
00105                 test(PUBLIC);
00106             test(VIRTUAL);
00107             const QByteArray type = parseType().name;
00108             // ignore the 'class Foo : BAR(Baz)' case
00109             if (test(LPAREN)) {
00110                 until(RPAREN);
00111             } else {
00112                 def->superclassList += qMakePair(type, access);
00113             }
00114         } while (test(COMMA));
00115     }
00116     if (!test(LBRACE))
00117         return false;
00118     def->begin = index - 1;
00119     bool foundRBrace = until(RBRACE);
00120     def->end = index;
00121     index = def->begin + 1;
00122     return foundRBrace;
00123 }
00124 
00125 Type Moc::parseType()
00126 {
00127     Type type;
00128     bool hasSignedOrUnsigned = false;
00129     bool isVoid = false;
00130     type.firstToken = lookup();
00131     for (;;) {
00132         switch (next()) {
00133             case SIGNED:
00134             case UNSIGNED:
00135                 hasSignedOrUnsigned = true;
00136                 // fall through
00137             case CONST:
00138             case VOLATILE:
00139                 type.name += lexem();
00140                 type.name += ' ';
00141                 if (lookup(0) == VOLATILE)
00142                     type.isVolatile = true;
00143                 continue;
00144             case Q_MOC_COMPAT_TOKEN:
00145             case Q_QT3_SUPPORT_TOKEN:
00146             case Q_INVOKABLE_TOKEN:
00147             case Q_SCRIPTABLE_TOKEN:
00148             case Q_SIGNALS_TOKEN:
00149             case Q_SLOTS_TOKEN:
00150                 type.name += lexem();
00151                 return type;
00152             default:
00153                 prev();
00154                 break;
00155         }
00156         break;
00157     }
00158     test(ENUM) || test(CLASS) || test(STRUCT);
00159     for(;;) {
00160         switch (next()) {
00161         case IDENTIFIER:
00162             // void mySlot(unsigned myArg)
00163             if (hasSignedOrUnsigned) {
00164                 prev();
00165                 break;
00166             }
00167         case CHAR:
00168         case SHORT:
00169         case INT:
00170         case LONG:
00171             type.name += lexem();
00172             // preserve '[unsigned] long long', 'short int', 'long int', 'long double'
00173             if (test(LONG) || test(INT) || test(DOUBLE)) {
00174                 type.name += ' ';
00175                 prev();
00176                 continue;
00177             }
00178             break;
00179         case FLOAT:
00180         case DOUBLE:
00181         case VOID:
00182         case BOOL:
00183             type.name += lexem();
00184             isVoid |= (lookup(0) == VOID);
00185             break;
00186         default:
00187             prev();
00188             ;
00189         }
00190         if (test(LANGLE)) {
00191             QByteArray templ = lexemUntil(RANGLE);
00192             for (int i = 0; i < templ.size(); ++i) {
00193                 type.name += templ.at(i);
00194                 if (templ.at(i) == '>' && i < templ.size()-1 && templ.at(i+1) == '>')
00195                     type.name += ' ';
00196             }
00197         }
00198         if (test(SCOPE)) {
00199             type.name += lexem();
00200             type.isScoped = true;
00201         } else {
00202             break;
00203         }
00204     }
00205     while (test(CONST) || test(VOLATILE) || test(SIGNED) || test(UNSIGNED)
00206            || test(STAR) || test(AND)) {
00207         type.name += ' ';
00208         type.name += lexem();
00209         if (lookup(0) == AND)
00210             type.referenceType = Type::Reference;
00211         else if (lookup(0) == STAR)
00212             type.referenceType = Type::Pointer;
00213     }
00214     // transform stupid things like 'const void' or 'void const' into 'void'
00215     if (isVoid && type.referenceType == Type::NoReference) {
00216         type.name = "void";
00217     }
00218     return type;
00219 }
00220 
00221 bool Moc::parseEnum(EnumDef *def)
00222 {
00223     if (!test(IDENTIFIER))
00224         return false; // anonymous enum
00225     def->name = lexem();
00226     if (!test(LBRACE))
00227         return false;
00228     do {
00229         if (lookup() == RBRACE) // accept trailing comma
00230             break;
00231         next(IDENTIFIER);
00232         def->values += lexem();
00233     } while (test(EQ) ? until(COMMA) : test(COMMA));
00234     next(RBRACE);
00235     return true;
00236 }
00237 
00238 void Moc::parseFunctionArguments(FunctionDef *def)
00239 {
00240     Q_UNUSED(def);
00241     while (hasNext()) {
00242         ArgumentDef  arg;
00243         arg.type = parseType();
00244         if (arg.type.name == "void")
00245             break;
00246         if (test(IDENTIFIER))
00247             arg.name = lexem();
00248         while (test(LBRACK)) {
00249             arg.rightType += lexemUntil(RBRACK);
00250         }
00251         if (test(CONST) || test(VOLATILE)) {
00252             arg.rightType += ' ';
00253             arg.rightType += lexem();
00254         }
00255         arg.normalizedType = normalizeType(arg.type.name + ' ' + arg.rightType);
00256         arg.typeNameForCast = normalizeType(noRef(arg.type.name) + "(*)" + arg.rightType);
00257         if (test(EQ))
00258             arg.isDefault = true;
00259         def->arguments += arg;
00260         if (!until(COMMA))
00261             break;
00262     }
00263 }
00264 
00265 // returns false if the function should be ignored
00266 bool Moc::parseFunction(FunctionDef *def, bool inMacro)
00267 {
00268     def->isVirtual = false;
00269     while (test(INLINE) || test(STATIC) || test(VIRTUAL)) {
00270         if (lookup() == VIRTUAL)
00271             def->isVirtual = true;
00272     }
00273     bool templateFunction = (lookup() == TEMPLATE);
00274     def->type = parseType();
00275     if (def->type.name.isEmpty()) {
00276         if (templateFunction)
00277             error("Template function as signal or slot");
00278         else
00279             error();
00280     }
00281     bool scopedFunctionName = false;
00282     if (test(LPAREN)) {
00283         def->name = def->type.name;
00284         scopedFunctionName = def->type.isScoped;
00285         def->type = Type("int");
00286     } else {
00287         Type tempType = parseType();;
00288         while (!tempType.name.isEmpty() && lookup() != LPAREN) {
00289             if (def->type.firstToken == Q_MOC_COMPAT_TOKEN || def->type.firstToken == Q_QT3_SUPPORT_TOKEN)
00290                 def->isCompat = true;
00291             else if (def->type.firstToken == Q_INVOKABLE_TOKEN)
00292                 def->isInvokable = true;
00293             else if (def->type.firstToken == Q_SCRIPTABLE_TOKEN)
00294                 def->isInvokable = def->isScriptable = true;
00295             else if (def->type.firstToken == Q_SIGNALS_TOKEN)
00296                 error();
00297             else if (def->type.firstToken == Q_SLOTS_TOKEN)
00298                 error();
00299             else {
00300                 if (!def->tag.isEmpty())
00301                     def->tag += ' ';
00302                 def->tag += def->type.name;
00303             }
00304             def->type = tempType;
00305             tempType = parseType();
00306         }
00307         next(LPAREN, "Not a signal or slot declaration");
00308         def->name = tempType.name;
00309         scopedFunctionName = tempType.isScoped;
00310     }
00311 
00312     // we don't support references as return types, it's too dangerous
00313     if (def->type.referenceType == Type::Reference)
00314         def->type = Type("void");
00315 
00316     def->normalizedType = normalizeType(def->type.name);
00317 
00318     if (!test(RPAREN)) {
00319         parseFunctionArguments(def);
00320         next(RPAREN);
00321     }
00322 
00323     // support optional macros with compiler specific options
00324     while (test(IDENTIFIER))
00325         ;
00326 
00327     def->isConst = test(CONST);
00328 
00329     while (test(IDENTIFIER))
00330         ;
00331 
00332     if (inMacro) {
00333         next(RPAREN);
00334     } else {
00335         if (test(SEMIC))
00336             ;
00337         else if ((def->inlineCode = test(LBRACE)))
00338             until(RBRACE);
00339         else if (test(EQ) || test(THROW))
00340             until(SEMIC);
00341         else
00342             error();
00343     }
00344 
00345     if (scopedFunctionName) {
00346         QByteArray msg("Function declaration ");
00347         msg += def->name;
00348         msg += " contains extra qualification. Ignoring as signal or slot.";
00349         warning(msg.constData());
00350         return false;
00351     }
00352     return true;
00353 }
00354 
00355 // like parseFunction, but never aborts with an error
00356 bool Moc::parseMaybeFunction(FunctionDef *def)
00357 {
00358     def->type = parseType();
00359     if (def->type.name.isEmpty())
00360         return false;
00361     bool scopedFunctionName = false;
00362     if (test(LPAREN)) {
00363         def->name = def->type.name;
00364         scopedFunctionName = def->type.isScoped;
00365         def->type = Type("int");
00366     } else {
00367         Type tempType = parseType();;
00368         while (!tempType.name.isEmpty() && lookup() != LPAREN) {
00369             if (def->type.name == "QT_MOC_COMPAT" || def->type.name == "QT3_SUPPORT")
00370                 def->isCompat = true;
00371             else if (def->type.name == "Q_INVOKABLE")
00372                 def->isInvokable = true;
00373             else if (def->type.name == "Q_SCRIPTABLE")
00374                 def->isInvokable = def->isScriptable = true;
00375             else if (def->type.name == "Q_SIGNAL")
00376                 def->isSignal = true;
00377             else if (def->type.name == "Q_SLOT")
00378                 def->isSlot = true;
00379             else {
00380                 if (!def->tag.isEmpty())
00381                     def->tag += ' ';
00382                 def->tag += def->type.name;
00383             }
00384             def->type = tempType;
00385             tempType = parseType();
00386         }
00387         if (!test(LPAREN))
00388             return false;
00389         def->name = tempType.name;
00390         scopedFunctionName = tempType.isScoped;
00391     }
00392 
00393     // we don't support references as return types, it's too dangerous
00394     if (def->type.referenceType == Type::Reference)
00395         def->type = Type("void");
00396 
00397     def->normalizedType = normalizeType(def->type.name);
00398 
00399     if (!test(RPAREN)) {
00400         parseFunctionArguments(def);
00401         if (!test(RPAREN))
00402             return false;
00403     }
00404     def->isConst = test(CONST);
00405     if (scopedFunctionName
00406         && (def->isSignal || def->isSlot || def->isInvokable)) {
00407         QByteArray msg("parsemaybe: Function declaration ");
00408         msg += def->name;
00409         msg += " contains extra qualification. Ignoring as signal or slot.";
00410         warning(msg.constData());
00411         return false;
00412     }
00413     return true;
00414 }
00415 
00416 
00417 void Moc::parse()
00418 {
00419     QList<NamespaceDef> namespaceList;
00420     bool templateClass = false;
00421     while (hasNext()) {
00422         Token t = next();
00423         switch (t) {
00424             case NAMESPACE: {
00425                 int rewind = index;
00426                 if (test(IDENTIFIER)) {
00427                     if (test(EQ)) {
00428                         // namespace Foo = Bar::Baz;
00429                         until(SEMIC);
00430                     } else if (!test(SEMIC)) {
00431                         NamespaceDef def;
00432                         def.name = lexem();
00433                         next(LBRACE);
00434                         def.begin = index - 1;
00435                         until(RBRACE);
00436                         def.end = index;
00437                         index = def.begin + 1;
00438                         namespaceList += def;
00439                         index = rewind;
00440                     }
00441                 }
00442                 break;
00443             }
00444             case SEMIC:
00445             case RBRACE:
00446                 templateClass = false;
00447                 break;
00448             case TEMPLATE:
00449                 templateClass = true;
00450                 break;
00451             case MOC_INCLUDE_BEGIN:
00452                 currentFilenames.push(symbol().unquotedLexem());
00453                 break;
00454             case MOC_INCLUDE_END:
00455                 currentFilenames.pop();
00456                 break;
00457             case Q_DECLARE_INTERFACE_TOKEN:
00458                 parseDeclareInterface();
00459                 break;
00460             case Q_DECLARE_METATYPE_TOKEN:
00461                 parseDeclareMetatype();
00462                 break;
00463             case USING:
00464                 if (test(NAMESPACE)) {
00465                     while (test(SCOPE) || test(IDENTIFIER))
00466                         ;
00467                     next(SEMIC);
00468                 }
00469                 break;
00470             default: break;
00471         }
00472         if ((t != CLASS && t != STRUCT)|| currentFilenames.size() > 1)
00473             continue;
00474         ClassDef def;
00475         FunctionDef::Access access = FunctionDef::Private;
00476         if (parseClassHead(&def)) {
00477             for (int i = namespaceList.size() - 1; i >= 0; --i)
00478                 if (inNamespace(&namespaceList.at(i)))
00479                     def.qualified.prepend(namespaceList.at(i).name + "::");
00480             while (inClass(&def) && hasNext()) {
00481                 switch ((t = next())) {
00482                 case PRIVATE:
00483                     access = FunctionDef::Private;
00484                     if (test(Q_SIGNALS_TOKEN))
00485                         error("Signals cannot have access specifier");
00486                     break;
00487                 case PROTECTED:
00488                     access = FunctionDef::Protected;
00489                     if (test(Q_SIGNALS_TOKEN))
00490                         error("Signals cannot have access specifier");
00491                     break;
00492                 case PUBLIC:
00493                     access = FunctionDef::Public;
00494                     if (test(Q_SIGNALS_TOKEN))
00495                         error("Signals cannot have access specifier");
00496                     break;
00497                 case CLASS: {
00498                     ClassDef nestedDef;
00499                     if (parseClassHead(&nestedDef)) {
00500                         while (inClass(&nestedDef) && inClass(&def)) {
00501                             t = next();
00502                             if (t >= Q_META_TOKEN_BEGIN && t < Q_META_TOKEN_END)
00503                                 error("Meta object features not supported for nested classes");
00504                         }
00505                     }
00506                 } break;
00507                 case Q_SIGNALS_TOKEN:
00508                     parseSignals(&def);
00509                     break;
00510                 case Q_SLOTS_TOKEN:
00511                     switch (lookup(-1)) {
00512                     case PUBLIC:
00513                     case PROTECTED:
00514                     case PRIVATE:
00515                         parseSlots(&def, access);
00516                         break;
00517                     default:
00518                         error("Missing access specifier for slots");
00519                     }
00520                     break;
00521                 case Q_OBJECT_TOKEN:
00522                     def.hasQObject = true;
00523                     if (templateClass)
00524                         error("Template classes not supported by Q_OBJECT");
00525                     if (def.classname != "Qt" && def.classname != "QObject" && def.superclassList.isEmpty())
00526                         error("Class contains Q_OBJECT macro but does not inherit from QObject");
00527                     break;
00528                 case Q_GADGET_TOKEN:
00529                     def.hasQGadget = true;
00530                     if (templateClass)
00531                         error("Template classes not supported by Q_GADGET");
00532                     break;
00533                 case Q_PROPERTY_TOKEN:
00534                     parseProperty(&def);
00535                     break;
00536                 case Q_ENUMS_TOKEN:
00537                     parseEnumOrFlag(&def, false);
00538                     break;
00539                 case Q_FLAGS_TOKEN:
00540                     parseEnumOrFlag(&def, true);
00541                     break;
00542                 case Q_DECLARE_FLAGS_TOKEN:
00543                     parseFlag(&def);
00544                     break;
00545                 case Q_CLASSINFO_TOKEN:
00546                     parseClassInfo(&def);
00547                     break;
00548                 case Q_INTERFACES_TOKEN:
00549                     parseInterfaces(&def);
00550                     break;
00551                 case Q_PRIVATE_SLOT_TOKEN:
00552                     parseSlotInPrivate(&def, access);
00553                     break;
00554                 case ENUM: {
00555                     EnumDef enumDef;
00556                     if (parseEnum(&enumDef))
00557                         def.enumList += enumDef;
00558                 } break;
00559                 default:
00560                     FunctionDef funcDef;
00561                     funcDef.access = access;
00562                     int rewind = index;
00563                     if (parseMaybeFunction(&funcDef)) {
00564                         if (access == FunctionDef::Public)
00565                             def.publicList += funcDef;
00566                         if (funcDef.isSlot) {
00567                             def.slotList += funcDef;
00568                             while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
00569                                 funcDef.wasCloned = true;
00570                                 funcDef.arguments.removeLast();
00571                                 def.slotList += funcDef;
00572                             }
00573                         } else if (funcDef.isSignal) {
00574                             def.signalList += funcDef;
00575                             while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
00576                                 funcDef.wasCloned = true;
00577                                 funcDef.arguments.removeLast();
00578                                 def.signalList += funcDef;
00579                             }
00580                         } else if (funcDef.isInvokable) {
00581                             def.methodList += funcDef;
00582                             while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
00583                                 funcDef.wasCloned = true;
00584                                 funcDef.arguments.removeLast();
00585                                 def.methodList += funcDef;
00586                             }
00587                         }
00588                     } else {
00589                         index = rewind;
00590                     }
00591                 }
00592             }
00593 
00594             next(RBRACE);
00595 
00596             if (!def.hasQObject && def.signalList.isEmpty() && def.slotList.isEmpty()
00597                 && def.propertyList.isEmpty() && def.enumDeclarations.isEmpty())
00598                 continue; // no meta object code required
00599 
00600 
00601             if (!def.hasQObject && !def.hasQGadget)
00602                 error("Class declarations lacks Q_OBJECT macro.");
00603 
00604             classList += def;
00605         }
00606     }
00607 
00608 }
00609 
00610 void Moc::generate(FILE *out)
00611 {
00612 
00613     QDateTime dt = QDateTime::currentDateTime();
00614     QByteArray dstr = dt.toString().toLatin1();
00615     QByteArray fn = filename;
00616     int i = filename.length()-1;
00617     while (i>0 && filename[i-1] != '/' && filename[i-1] != '//')
00618         --i;                                // skip path
00619     if (i >= 0)
00620         fn = filename.mid(i);
00621     fprintf(out, "/****************************************************************************/n"
00622             "** Meta object code from reading C++ file '%s'/n**/n" , (const char*)fn);
00623     fprintf(out, "** Created: %s/n"
00624             "**      by: The Qt Meta Object Compiler version %d (Qt %s)/n**/n" , dstr.data(), mocOutputRevision, QT_VERSION_STR);
00625     fprintf(out, "** WARNING! All changes made in this file will be lost!/n"
00626             "*****************************************************************************//n/n");
00627 
00628 
00629     if (!noInclude) {
00630         if (includePath.size() && includePath.right(1) != "/")
00631             includePath += "/";
00632         for (int i = 0; i < includeFiles.size(); ++i) {
00633             QByteArray inc = includeFiles.at(i);
00634             if (inc[0] != '<' && inc[0] != '"') {
00635                 if (includePath.size() && includePath != "./")
00636                     inc.prepend(includePath);
00637                 inc = "/"" + inc + "/"";
00638             }
00639             fprintf(out, "#include %s/n", inc.constData());
00640         }
00641     }
00642     if (classList.size() && classList.first().classname == "Qt")
00643         fprintf(out, "#include <QtCore/qobject.h>/n");
00644 
00645     fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)/n"
00646             "#error /"The header file '%s' doesn't include <QObject>./"/n", (const char *)fn);
00647     fprintf(out, "#elif Q_MOC_OUTPUT_REVISION != %d/n", mocOutputRevision);
00648     fprintf(out, "#error /"This file was generated using the moc from %s."
00649             " It/"/n#error /"cannot be used with the include files from"
00650             " this version of Qt./"/n#error /"(The moc has changed too"
00651             " much.)/"/n", QT_VERSION_STR);
00652     fprintf(out, "#endif/n/n");
00653 
00654 
00655     for (i = 0; i < classList.size(); ++i) {
00656         Generator generator(out, &classList[i], metaTypes);
00657         generator.generateCode();
00658     }
00659 }
00660 
00661 
00662 
00663 void Moc::parseSlots(ClassDef *def, FunctionDef::Access access)
00664 {
00665     next(COLON);
00666     while (inClass(def) && hasNext()) {
00667         switch (next()) {
00668         case PUBLIC:
00669         case PROTECTED:
00670         case PRIVATE:
00671         case Q_SIGNALS_TOKEN:
00672         case Q_SLOTS_TOKEN:
00673             prev();
00674             return;
00675         case SEMIC:
00676             continue;
00677         case FRIEND:
00678             until(SEMIC);
00679             continue;
00680         case USING:
00681             error("'using' directive not supported in 'slots' section");
00682         default:
00683             prev();
00684         }
00685 
00686         FunctionDef funcDef;
00687         funcDef.access = access;
00688         if (!parseFunction(&funcDef))
00689             continue;
00690         def->slotList += funcDef;
00691         while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
00692             funcDef.wasCloned = true;
00693             funcDef.arguments.removeLast();
00694             def->slotList += funcDef;
00695         }
00696     }
00697 }
00698 
00699 void Moc::parseSignals(ClassDef *def)
00700 {
00701     next(COLON);
00702     while (inClass(def) && hasNext()) {
00703         switch (next()) {
00704         case PUBLIC:
00705         case PROTECTED:
00706         case PRIVATE:
00707         case Q_SIGNALS_TOKEN:
00708         case Q_SLOTS_TOKEN:
00709             prev();
00710             return;
00711         case SEMIC:
00712             continue;
00713         case FRIEND:
00714             until(SEMIC);
00715             continue;
00716         case USING:
00717             error("'using' directive not supported in 'signals' section");
00718         default:
00719             prev();
00720         }
00721         FunctionDef funcDef;
00722         funcDef.access = FunctionDef::Protected;
00723         parseFunction(&funcDef);
00724         if (funcDef.isVirtual)
00725             error("Signals cannot be declared virtual");
00726         if (funcDef.inlineCode)
00727             error("Not a signal declaration");
00728         def->signalList += funcDef;
00729         while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
00730             funcDef.wasCloned = true;
00731             funcDef.arguments.removeLast();
00732             def->signalList += funcDef;
00733         }
00734     }
00735 }
00736 
00737 
00738 void Moc::parseProperty(ClassDef *def)
00739 {
00740     next(LPAREN);
00741     PropertyDef propDef;
00742     QByteArray type = parseType().name;
00743     if (type.isEmpty())
00744         error();
00745     propDef.designable = propDef.scriptable = propDef.stored = "true";
00746     propDef.user = "false";
00747     /*
00748       The Q_PROPERTY construct cannot contain any commas, since
00749       commas separate macro arguments. We therefore expect users
00750       to type "QMap" instead of "QMap<QString, QVariant>". For
00751       coherence, we also expect the same for
00752       QValueList<QVariant>, the other template class supported by
00753       QVariant.
00754     */
00755     type = normalizeType(type);
00756     if (type == "QMap")
00757         type = "QMap<QString,QVariant>";
00758     else if (type == "QValueList")
00759         type = "QValueList<QVariant>";
00760     else if (type == "LongLong")
00761         type = "qlonglong";
00762     else if (type == "ULongLong")
00763         type = "qulonglong";
00764     propDef.type = type;
00765 
00766     next();
00767     propDef.name = lexem();
00768     while (test(IDENTIFIER)) {
00769         QByteArray l = lexem();
00770         QByteArray v, v2;
00771         if (test(LPAREN)) {
00772             v = lexemUntil(RPAREN);
00773         } else {
00774             next(IDENTIFIER);
00775             v = lexem();
00776             if (test(LPAREN))
00777                 v2 = lexemUntil(RPAREN);
00778             else if (v != "true" && v != "false")
00779                 v2 = "()";
00780         }
00781         switch (l[0]) {
00782         case 'R':
00783             if (l == "READ")
00784                 propDef.read = v;
00785             else if (l == "RESET")
00786                 propDef.reset = v + v2;
00787             else
00788                 error(2);
00789             break;
00790         case 'S':
00791             if (l == "SCRIPTABLE")
00792                 propDef.scriptable = v + v2;
00793             else if (l == "STORED")
00794                 propDef.stored = v + v2;
00795             else
00796                 error(2);
00797             break;
00798         case 'W': if (l != "WRITE") error(2);
00799             propDef.write = v;
00800             break;
00801         case 'D': if (l != "DESIGNABLE") error(2);
00802             propDef.designable = v + v2;
00803             break;
00804         case 'E': if (l != "EDITABLE") error(2);
00805             propDef.editable = v + v2;
00806             break;
00807         case 'N': if (l != "NOTIFY") error(2);
00808             break;
00809         case 'U': if (l != "USER") error(2);
00810             propDef.user = v + v2;
00811             break;
00812         default:
00813             error(2);
00814         }
00815     }
00816     next(RPAREN);
00817     def->propertyList += propDef;
00818 }
00819 
00820 void Moc::parseEnumOrFlag(ClassDef *def, bool isFlag)
00821 {
00822     next(LPAREN);
00823     QByteArray identifier;
00824     while (test(IDENTIFIER)) {
00825         identifier = lexem();
00826         while (test(SCOPE) && test(IDENTIFIER)) {
00827             identifier += "::";
00828             identifier += lexem();
00829         }
00830         def->enumDeclarations[identifier] = isFlag;
00831     }
00832     next(RPAREN);
00833 }
00834 
00835 void Moc::parseFlag(ClassDef *def)
00836 {
00837     next(LPAREN);
00838     QByteArray flagName, enumName;
00839     while (test(IDENTIFIER)) {
00840         flagName = lexem();
00841         while (test(SCOPE) && test(IDENTIFIER)) {
00842             flagName += "::";
00843             flagName += lexem();
00844         }
00845     }
00846     next(COMMA);
00847     while (test(IDENTIFIER)) {
00848         enumName = lexem();
00849         while (test(SCOPE) && test(IDENTIFIER)) {
00850             enumName += "::";
00851             enumName += lexem();
00852         }
00853     }
00854 
00855     def->flagAliases.insert(enumName, flagName);
00856     next(RPAREN);
00857 }
00858 
00859 void Moc::parseClassInfo(ClassDef *def)
00860 {
00861     next(LPAREN);
00862     ClassInfoDef infoDef;
00863     next(STRING_LITERAL);
00864     infoDef.name = symbol().unquotedLexem();
00865     next(COMMA);
00866     if (test(STRING_LITERAL)) {
00867         infoDef.value = symbol().unquotedLexem();
00868     } else {
00869         // support Q_CLASSINFO("help", QT_TR_NOOP("blah"))
00870         next(IDENTIFIER);
00871         next(LPAREN);
00872         next(STRING_LITERAL);
00873         infoDef.value = symbol().unquotedLexem();
00874         next(RPAREN);
00875     }
00876     next(RPAREN);
00877     def->classInfoList += infoDef;
00878 }
00879 
00880 void Moc::parseInterfaces(ClassDef *def)
00881 {
00882     next(LPAREN);
00883     while (test(IDENTIFIER)) {
00884         QList<ClassDef::Interface> iface;
00885         iface += ClassDef::Interface(lexem());
00886         while (test(SCOPE)) {
00887             iface.last().className += lexem();
00888             next(IDENTIFIER);
00889             iface.last().className += lexem();
00890         }
00891         while (test(COLON)) {
00892             next(IDENTIFIER);
00893             iface += ClassDef::Interface(lexem());
00894             while (test(SCOPE)) {
00895                 iface.last().className += lexem();
00896                 next(IDENTIFIER);
00897                 iface.last().className += lexem();
00898             }
00899         }
00900         // resolve from classnames to interface ids
00901         for (int i = 0; i < iface.count(); ++i) {
00902             const QByteArray iid = interface2IdMap.value(iface.at(i).className);
00903             if (iid.isEmpty())
00904                 error("Undefined interface");
00905 
00906             iface[i].interfaceId = iid;
00907         }
00908         def->interfaceList += iface;
00909     }
00910     next(RPAREN);
00911 }
00912 
00913 void Moc::parseDeclareInterface()
00914 {
00915     next(LPAREN);
00916     QByteArray interface;
00917     next(IDENTIFIER);
00918     interface += lexem();
00919     while (test(SCOPE)) {
00920         interface += lexem();
00921         next(IDENTIFIER);
00922         interface += lexem();
00923     }
00924     next(COMMA);
00925     QByteArray iid;
00926     if (test(STRING_LITERAL)) {
00927         iid = lexem();
00928     } else {
00929         next(IDENTIFIER);
00930         iid = lexem();
00931     }
00932     interface2IdMap.insert(interface, iid);
00933     next(RPAREN);
00934 }
00935 
00936 void Moc::parseDeclareMetatype()
00937 {
00938     next(LPAREN);
00939     QByteArray typeName = lexemUntil(RPAREN);
00940     typeName.remove(0, 1);
00941     typeName.chop(1);
00942     metaTypes.append(typeName);
00943 }
00944 
00945 void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
00946 {
00947     next(LPAREN);
00948     FunctionDef funcDef;
00949     next(IDENTIFIER);
00950     funcDef.inPrivateClass = lexem();
00951     // also allow void functions
00952     if (test(LPAREN)) {
00953         next(RPAREN);
00954         funcDef.inPrivateClass += "()";
00955     }
00956     next(COMMA);
00957     funcDef.access = access;
00958     parseFunction(&funcDef, true);
00959     def->slotList += funcDef;
00960     while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
00961         funcDef.wasCloned = true;
00962         funcDef.arguments.removeLast();
00963         def->slotList += funcDef;
00964     }
00965 }
00966 
00967 QByteArray Moc::lexemUntil(Token target)
00968 {
00969     int from = index;
00970     until(target);
00971     QByteArray s;
00972     while (from <= index) {
00973         QByteArray n = symbols.at(from++-1).lexem();
00974         if (s.size() && n.size()
00975             && is_ident_char(s.at(s.size()-1))
00976             && is_ident_char(n.at(0)))
00977             s += ' ';
00978         s += n;
00979     }
00980     return s;
00981 }
00982 
00983 bool Moc::until(Token target) {
00984     int braceCount = 0;
00985     int brackCount = 0;
00986     int parenCount = 0;
00987     int angleCount = 0;
00988     if (index) {
00989         switch(symbols.at(index-1).token) {
00990         case LBRACE: ++braceCount; break;
00991         case LBRACK: ++brackCount; break;
00992         case LPAREN: ++parenCount; break;
00993         case LANGLE: ++angleCount; break;
00994         default: ;
00995         }
00996     }
00997     while (index < symbols.size()) {
00998         Token t = symbols.at(index++).token;
00999         switch (t) {
01000         case LBRACE: ++braceCount; break;
01001         case RBRACE: --braceCount; break;
01002         case LBRACK: ++brackCount; break;
01003         case RBRACK: --brackCount; break;
01004         case LPAREN: ++parenCount; break;
01005         case RPAREN: --parenCount; break;
01006         case LANGLE: ++angleCount; break;
01007         case RANGLE: --angleCount; break;
01008         default: break;
01009         }
01010         if (t == target
01011             && braceCount <= 0
01012             && brackCount <= 0
01013             && parenCount <= 0
01014             && (target != RANGLE || angleCount <= 0))
01015             return true;
01016 
01017         if (braceCount < 0 || brackCount < 0 || parenCount < 0
01018             || (target == RANGLE && angleCount < 0)) {
01019             --index;
01020             break;
01021         }
01022     }
01023     return false;
01024 }
01025 
01026 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章