http://cep.xor.aps.anl.gov/software/qt4-x11-4.2.2-browser/d5/d3c/moc_8cpp-source.html
moc源码,网站不错
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00031 #include <private/qmetaobject_p.h>
00032
00033
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
00063
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))
00075 return false;
00076 QByteArray name = lexem();
00077
00078
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
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
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
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
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
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;
00225 def->name = lexem();
00226 if (!test(LBRACE))
00227 return false;
00228 do {
00229 if (lookup() == RBRACE)
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
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
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
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
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
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
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;
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;
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
00749
00750
00751
00752
00753
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
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
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
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