summaryrefslogtreecommitdiffstats
path: root/umbrello/umbrello/codeimport
diff options
context:
space:
mode:
Diffstat (limited to 'umbrello/umbrello/codeimport')
-rw-r--r--umbrello/umbrello/codeimport/Makefile.am6
-rw-r--r--umbrello/umbrello/codeimport/adaimport.cpp588
-rw-r--r--umbrello/umbrello/codeimport/adaimport.h88
-rw-r--r--umbrello/umbrello/codeimport/classimport.cpp58
-rw-r--r--umbrello/umbrello/codeimport/classimport.h61
-rw-r--r--umbrello/umbrello/codeimport/cppimport.cpp109
-rw-r--r--umbrello/umbrello/codeimport/cppimport.h59
-rw-r--r--umbrello/umbrello/codeimport/idlimport.cpp356
-rw-r--r--umbrello/umbrello/codeimport/idlimport.h54
-rw-r--r--umbrello/umbrello/codeimport/import_utils.cpp464
-rw-r--r--umbrello/umbrello/codeimport/import_utils.h175
-rw-r--r--umbrello/umbrello/codeimport/javaimport.cpp549
-rw-r--r--umbrello/umbrello/codeimport/javaimport.h106
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/Makefile.am5
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/README56
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast.cpp1183
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast.h1449
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp176
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h29
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp640
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h98
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/driver.cpp435
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/driver.h230
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/errors.cpp25
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/errors.h45
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h123
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp1002
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lexer.h791
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp113
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/lookup.h119
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/parser.cpp4238
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/parser.h221
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp207
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h59
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp310
-rw-r--r--umbrello/umbrello/codeimport/kdevcppparser/urlutil.h132
-rw-r--r--umbrello/umbrello/codeimport/nativeimportbase.cpp340
-rw-r--r--umbrello/umbrello/codeimport/nativeimportbase.h227
-rw-r--r--umbrello/umbrello/codeimport/pascalimport.cpp413
-rw-r--r--umbrello/umbrello/codeimport/pascalimport.h66
-rw-r--r--umbrello/umbrello/codeimport/pythonimport.cpp190
-rw-r--r--umbrello/umbrello/codeimport/pythonimport.h76
42 files changed, 15671 insertions, 0 deletions
diff --git a/umbrello/umbrello/codeimport/Makefile.am b/umbrello/umbrello/codeimport/Makefile.am
new file mode 100644
index 00000000..5f821fab
--- /dev/null
+++ b/umbrello/umbrello/codeimport/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = -I./kdevcppparser $(all_includes)
+
+noinst_LTLIBRARIES = libcodeimport.la
+libcodeimport_la_SOURCES = adaimport.cpp classimport.cpp cppimport.cpp idlimport.cpp import_utils.cpp javaimport.cpp nativeimportbase.cpp pascalimport.cpp pythonimport.cpp
+
+SUBDIRS = kdevcppparser
diff --git a/umbrello/umbrello/codeimport/adaimport.cpp b/umbrello/umbrello/codeimport/adaimport.cpp
new file mode 100644
index 00000000..54ac3907
--- /dev/null
+++ b/umbrello/umbrello/codeimport/adaimport.cpp
@@ -0,0 +1,588 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "adaimport.h"
+
+#include <stdio.h>
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../package.h"
+#include "../folder.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../association.h"
+
+AdaImport::AdaImport() : NativeImportBase("--") {
+ initVars();
+}
+
+AdaImport::~AdaImport() {
+}
+
+void AdaImport::initVars() {
+ m_inGenericFormalPart = false;
+ m_classesDefinedInThisScope.clear();
+ m_renaming.clear();
+}
+
+/// Split the line so that a string is returned as a single element of the list,
+/// when not in a string then split at white space.
+QStringList AdaImport::split(const QString& lin) {
+ QStringList list;
+ QString listElement;
+ bool inString = false;
+ bool seenSpace = false;
+ QString line = lin.stripWhiteSpace();
+ uint len = line.length();
+ for (uint i = 0; i < len; i++) {
+ const QChar& c = line[i];
+ if (inString) {
+ listElement += c;
+ if (c == '"') {
+ if (i < len - 1 && line[i + 1] == '"') {
+ i++; // escaped quotation mark
+ continue;
+ }
+ list.append(listElement);
+ listElement = QString();
+ inString = false;
+ }
+ } else if (c == '"') {
+ inString = true;
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ listElement = QString(c);
+ seenSpace = false;
+ } else if (c == '\'') {
+ if (i < len - 2 && line[i + 2] == '\'') {
+ // character constant
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ listElement = line.mid(i, 3);
+ i += 2;
+ list.append(listElement);
+ listElement = QString();
+ continue;
+ }
+ listElement += c;
+ seenSpace = false;
+ } else if (c.isSpace()) {
+ if (seenSpace)
+ continue;
+ seenSpace = true;
+ if (!listElement.isEmpty()) {
+ list.append(listElement);
+ listElement = QString();
+ }
+ } else {
+ listElement += c;
+ seenSpace = false;
+ }
+ }
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ return list;
+}
+
+void AdaImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ QChar c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.' || c == '#') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ if (c == ':' && word[i + 1] == '=') {
+ m_source.append(":=");
+ i++;
+ } else {
+ m_source.append(QString(c));
+ }
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+QString AdaImport::expand(const QString& name) {
+ QRegExp pfxRegExp("^(\\w+)\\.");
+ pfxRegExp.setCaseSensitive(false);
+ int pos = pfxRegExp.search(name);
+ if (pos == -1)
+ return name;
+ QString result = name;
+ QString pfx = pfxRegExp.cap(1);
+ if (m_renaming.contains(pfx)) {
+ result.remove(pfxRegExp);
+ result.prepend(m_renaming[pfx] + '.');
+ }
+ return result;
+}
+
+void AdaImport::parseStems(const QStringList& stems) {
+ if (stems.isEmpty())
+ return;
+ QString base = stems.first();
+ uint i = 0;
+ while (1) {
+ QString filename = base + ".ads";
+ if (! m_parsedFiles.contains(filename)) {
+ // Save current m_source and m_srcIndex.
+ QStringList source(m_source);
+ uint srcIndex = m_srcIndex;
+ m_source.clear();
+ parseFile(filename);
+ // Restore m_source and m_srcIndex.
+ m_source = source;
+ m_srcIndex = srcIndex;
+ // Also reset m_currentAccess.
+ // CHECK: need to reset more stuff?
+ m_currentAccess = Uml::Visibility::Public;
+ }
+ if (++i >= stems.count())
+ break;
+ base += '-' + stems[i];
+ }
+}
+
+bool AdaImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ QString keyword = m_source[m_srcIndex];
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword == "with") {
+ if (m_inGenericFormalPart) {
+ // mapping of generic formal subprograms or packages is not yet implemented
+ return false;
+ }
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ";") {
+ QStringList components = QStringList::split(".", m_source[m_srcIndex].lower());
+ const QString& prefix = components.first();
+ if (prefix == "system" || prefix == "ada" || prefix == "gnat" ||
+ prefix == "interfaces" || prefix == "text_io" ||
+ prefix == "unchecked_conversion" ||
+ prefix == "unchecked_deallocation") {
+ if (advance() != ",")
+ break;
+ continue;
+ }
+ parseStems(components);
+ if (advance() != ",")
+ break;
+ }
+ return true;
+ }
+ if (keyword == "generic") {
+ m_inGenericFormalPart = true;
+ return true;
+ }
+ if (keyword == "package") {
+ const QString& name = advance();
+ QStringList parentPkgs = QStringList::split(".", name.lower());
+ parentPkgs.pop_back(); // exclude the current package
+ parseStems(parentPkgs);
+ UMLObject *ns = NULL;
+ if (advance() == "is") {
+ ns = Import_Utils::createUMLObject(Uml::ot_Package, name,
+ m_scope[m_scopeIndex], m_comment);
+ if (m_source[m_srcIndex + 1] == "new") {
+ m_srcIndex++;
+ QString pkgName = advance();
+ UMLObject *gp = Import_Utils::createUMLObject(Uml::ot_Package, pkgName,
+ m_scope[m_scopeIndex]);
+ gp->setStereotype("generic");
+ // Add binding from instantiator to instantiatee
+ UMLAssociation *assoc = new UMLAssociation(Uml::at_Dependency, ns, gp);
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ assoc->setStereotype("bind");
+ // Work around missing display of stereotype in AssociationWidget:
+ assoc->setName(assoc->getStereotype(true));
+ umldoc->addAssociation(assoc);
+ skipStmt();
+ } else {
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ }
+ } else if (m_source[m_srcIndex] == "renames") {
+ m_renaming[name] = advance();
+ } else {
+ kError() << "AdaImport::parseStmt: unexpected: " << m_source[m_srcIndex] << endl;
+ skipStmt("is");
+ }
+ if (m_inGenericFormalPart) {
+ ns->setStereotype("generic");
+ m_inGenericFormalPart = false;
+ }
+ return true;
+ }
+ if (m_inGenericFormalPart)
+ return false; // skip generic formal parameter (not yet implemented)
+ if (keyword == "subtype") {
+ QString name = advance();
+ advance(); // "is"
+ QString base = expand(advance());
+ base.remove("Standard.", false);
+ UMLObject *type = umldoc->findUMLObject(base, Uml::ot_UMLObject, m_scope[m_scopeIndex]);
+ if (type == NULL) {
+ type = Import_Utils::createUMLObject(Uml::ot_Datatype, base, m_scope[m_scopeIndex]);
+ }
+ UMLObject *subtype = Import_Utils::createUMLObject(type->getBaseType(), name,
+ m_scope[m_scopeIndex], m_comment);
+ UMLAssociation *assoc = new UMLAssociation(Uml::at_Dependency, subtype, type);
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ assoc->setStereotype("subtype");
+ // Work around missing display of stereotype in AssociationWidget:
+ assoc->setName(assoc->getStereotype(true));
+ umldoc->addAssociation(assoc);
+ skipStmt();
+ return true;
+ }
+ if (keyword == "type") {
+ QString name = advance();
+ QString next = advance();
+ if (next == "(") {
+ kDebug() << "AdaImport::parseStmt(" << name << "): "
+ << "discriminant handling is not yet implemented" << endl;
+ // @todo Find out how to map discriminated record to UML.
+ // For now, we just create a pro forma empty record.
+ Import_Utils::createUMLObject(Uml::ot_Class, name, m_scope[m_scopeIndex],
+ m_comment, "record");
+ skipStmt("end");
+ if ((next = advance()) == "case")
+ m_srcIndex += 2; // skip "case" ";"
+ skipStmt();
+ return true;
+ }
+ if (next == ";") {
+ // forward declaration
+ Import_Utils::createUMLObject(Uml::ot_Class, name, m_scope[m_scopeIndex],
+ m_comment);
+ return true;
+ }
+ if (next != "is") {
+ kError() << "AdaImport::parseStmt: expecting \"is\"" << endl;
+ return false;
+ }
+ next = advance();
+ if (next == "(") {
+ // enum type
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ while ((next = advance()) != ")") {
+ Import_Utils::addEnumLiteral(enumType, next, m_comment);
+ m_comment = QString();
+ if (advance() != ",")
+ break;
+ }
+ skipStmt();
+ return true;
+ }
+ bool isTaggedType = false;
+ if (next == "abstract") {
+ m_isAbstract = true;
+ next = advance();
+ }
+ if (next == "tagged") {
+ isTaggedType = true;
+ next = advance();
+ }
+ if (next == "limited" ||
+ next == "task" ||
+ next == "protected" ||
+ next == "synchronized") {
+ next = advance(); // we can't (yet?) represent that
+ }
+ if (next == "private" ||
+ next == "interface" ||
+ next == "record" ||
+ (next == "null" &&
+ m_source[m_srcIndex+1] == "record")) {
+ Uml::Object_Type t = (next == "interface" ? Uml::ot_Interface : Uml::ot_Class);
+ UMLObject *ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
+ if (t == Uml::ot_Interface) {
+ while ((next = advance()) == "and") {
+ UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+ QString base = expand(advance());
+ UMLObject *p = Import_Utils::createUMLObject(Uml::ot_Interface, base, m_scope[m_scopeIndex]);
+ UMLClassifier *parent = static_cast<UMLClassifier*>(p);
+ Import_Utils::createGeneralization(klass, parent);
+ }
+ } else {
+ ns->setAbstract(m_isAbstract);
+ }
+ m_isAbstract = false;
+ if (isTaggedType) {
+ if (! m_classesDefinedInThisScope.contains(ns))
+ m_classesDefinedInThisScope.append(ns);
+ } else {
+ ns->setStereotype("record");
+ }
+ if (next == "record")
+ m_klass = static_cast<UMLClassifier*>(ns);
+ else
+ skipStmt();
+ return true;
+ }
+ if (next == "new") {
+ QString base = expand(advance());
+ QStringList baseInterfaces;
+ while ((next = advance()) == "and") {
+ baseInterfaces.append(expand(advance()));
+ }
+ const bool isExtension = (next == "with");
+ Uml::Object_Type t;
+ if (isExtension || m_isAbstract) {
+ t = Uml::ot_Class;
+ } else {
+ base.remove("Standard.", false);
+ UMLObject *known = umldoc->findUMLObject(base, Uml::ot_UMLObject, m_scope[m_scopeIndex]);
+ t = (known ? known->getBaseType() : Uml::ot_Datatype);
+ }
+ UMLObject *ns = Import_Utils::createUMLObject(t, base, NULL);
+ UMLClassifier *parent = static_cast<UMLClassifier*>(ns);
+ ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
+ if (isExtension) {
+ next = advance();
+ if (next == "null" || next == "record") {
+ UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+ Import_Utils::createGeneralization(klass, parent);
+ if (next == "record") {
+ // Set the m_klass for attributes.
+ m_klass = klass;
+ }
+ if (baseInterfaces.count()) {
+ t = Uml::ot_Interface;
+ QStringList::Iterator end(baseInterfaces.end());
+ for (QStringList::Iterator bi(baseInterfaces.begin()); bi != end; ++bi) {
+ ns = Import_Utils::createUMLObject(t, *bi, m_scope[m_scopeIndex]);
+ parent = static_cast<UMLClassifier*>(ns);
+ Import_Utils::createGeneralization(klass, parent);
+ }
+ }
+ }
+ }
+ skipStmt();
+ return true;
+ }
+ // Datatypes: TO BE DONE
+ return false;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "end") {
+ if (m_klass) {
+ if (advance() != "record") {
+ kError() << "end: expecting \"record\" at "
+ << m_source[m_srcIndex] << endl;
+ }
+ m_klass = NULL;
+ } else if (m_scopeIndex) {
+ if (advance() != ";") {
+ QString scopeName = m_scope[m_scopeIndex]->getFullyQualifiedName();
+ if (scopeName.lower() != m_source[m_srcIndex].lower())
+ kError() << "end: expecting " << scopeName << ", found "
+ << m_source[m_srcIndex] << endl;
+ }
+ m_scopeIndex--;
+ m_currentAccess = Uml::Visibility::Public; // @todo make a stack for this
+ } else {
+ kError() << "importAda: too many \"end\"" << endl;
+ }
+ skipStmt();
+ return true;
+ }
+ // subprogram
+ if (keyword == "not")
+ keyword = advance();
+ if (keyword == "overriding")
+ keyword = advance();
+ if (keyword == "function" || keyword == "procedure") {
+ const QString& name = advance();
+ QString returnType;
+ if (advance() != "(") {
+ // Unlike an Ada package, a UML package does not support
+ // subprograms.
+ // In order to map those, we would need to create a UML
+ // class with stereotype <<utility>> for the Ada package.
+ kDebug() << "ignoring parameterless " << keyword << " " << name << endl;
+ skipStmt();
+ return true;
+ }
+ UMLClassifier *klass = NULL;
+ UMLOperation *op = NULL;
+ const uint MAX_PARNAMES = 16;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ QString parName[MAX_PARNAMES];
+ uint parNameCount = 0;
+ do {
+ if (parNameCount >= MAX_PARNAMES) {
+ kError() << "MAX_PARNAMES is exceeded at " << name << endl;
+ break;
+ }
+ parName[parNameCount++] = advance();
+ } while (advance() == ",");
+ if (m_source[m_srcIndex] != ":") {
+ kError() << "importAda: expecting ':'" << endl;
+ skipStmt();
+ break;
+ }
+ const QString &direction = advance();
+ QString typeName;
+ Uml::Parameter_Direction dir = Uml::pd_In;
+ if (direction == "access") {
+ // Oops, we have to improvise here because there
+ // is no such thing as "access" in UML.
+ // So we use the next best thing, "inout".
+ // Better ideas, anyone?
+ dir = Uml::pd_InOut;
+ typeName = advance();
+ } else if (direction == "in") {
+ if (m_source[m_srcIndex + 1] == "out") {
+ dir = Uml::pd_InOut;
+ m_srcIndex++;
+ }
+ typeName = advance();
+ } else if (direction == "out") {
+ dir = Uml::pd_Out;
+ typeName = advance();
+ } else {
+ typeName = direction; // In Ada, the default direction is "in"
+ }
+ typeName.remove("Standard.", false);
+ typeName = expand(typeName);
+ if (op == NULL) {
+ // In Ada, the first parameter indicates the class.
+ UMLObject *type = Import_Utils::createUMLObject(Uml::ot_Class, typeName, m_scope[m_scopeIndex]);
+ Uml::Object_Type t = type->getBaseType();
+ if ((t != Uml::ot_Interface &&
+ (t != Uml::ot_Class || type->getStereotype() == "record")) ||
+ !m_classesDefinedInThisScope.contains(type)) {
+ // Not an instance bound method - we cannot represent it.
+ skipStmt(")");
+ break;
+ }
+ klass = static_cast<UMLClassifier*>(type);
+ op = Import_Utils::makeOperation(klass, name);
+ // The controlling parameter is suppressed.
+ parNameCount--;
+ if (parNameCount) {
+ for (uint i = 0; i < parNameCount; i++)
+ parName[i] = parName[i + 1];
+ }
+ }
+ for (uint i = 0; i < parNameCount; i++) {
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]);
+ att->setParmKind(dir);
+ }
+ if (advance() != ";")
+ break;
+ }
+ if (keyword == "function") {
+ if (advance() != "return") {
+ if (klass)
+ kError() << "importAda: expecting \"return\" at function "
+ << name << endl;
+ return false;
+ }
+ returnType = expand(advance());
+ returnType.remove("Standard.", false);
+ }
+ bool isAbstract = false;
+ if (advance() == "is" && advance() == "abstract")
+ isAbstract = true;
+ if (klass != NULL && op != NULL)
+ Import_Utils::insertMethod(klass, op, m_currentAccess, returnType,
+ false, isAbstract, false, false, m_comment);
+ skipStmt();
+ return true;
+ }
+ if (keyword == "task" || keyword == "protected") {
+ // Can task and protected objects/types be mapped to UML?
+ bool isType = false;
+ QString name = advance();
+ if (name == "type") {
+ isType = true;
+ name = advance();
+ }
+ QString next = advance();
+ if (next == "(") {
+ skipStmt(")"); // skip discriminant
+ next = advance();
+ }
+ if (next == "is")
+ skipStmt("end");
+ skipStmt();
+ return true;
+ }
+ if (keyword == "for") { // rep spec
+ QString typeName = advance();
+ QString next = advance();
+ if (next == "'") {
+ advance(); // skip qualifier
+ next = advance();
+ }
+ if (next == "use") {
+ if (advance() == "record")
+ skipStmt("end");
+ } else {
+ kError() << "importAda: expecting \"use\" at rep spec of "
+ << typeName << endl;
+ }
+ skipStmt();
+ return true;
+ }
+ // At this point we're only interested in attribute declarations.
+ if (m_klass == NULL || keyword == "null") {
+ skipStmt();
+ return true;
+ }
+ const QString& name = keyword;
+ if (advance() != ":") {
+ kError() << "adaImport: expecting \":\" at " << name << " "
+ << m_source[m_srcIndex] << endl;
+ skipStmt();
+ return true;
+ }
+ QString nextToken = advance();
+ if (nextToken == "aliased")
+ nextToken = advance();
+ QString typeName = expand(nextToken);
+ QString initialValue;
+ if (advance() == ":=") {
+ initialValue = advance();
+ QString token;
+ while ((token = advance()) != ";") {
+ initialValue.append(' ' + token);
+ }
+ }
+ UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ typeName, m_comment);
+ UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ attr->setInitialValue(initialValue);
+ skipStmt();
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/codeimport/adaimport.h b/umbrello/umbrello/codeimport/adaimport.h
new file mode 100644
index 00000000..14e41926
--- /dev/null
+++ b/umbrello/umbrello/codeimport/adaimport.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef ADAIMPORT_H
+#define ADAIMPORT_H
+
+#include <qmap.h>
+#include <qstringlist.h>
+
+#include "nativeimportbase.h"
+#include "../umlobjectlist.h"
+
+/**
+ * Ada code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class AdaImport : public NativeImportBase {
+public:
+ AdaImport();
+ virtual ~AdaImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Split the line so that a string is returned as a single element of the list.
+ * When not in a string then split at white space.
+ * Reimplementation of method from NativeImportBase is required because of
+ * Ada's tic which is liable to be confused with the beginning of a character
+ * constant.
+ */
+ QStringList split(const QString& line);
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+ /**
+ * Apply package renamings to the given name.
+ *
+ * @return expanded name
+ */
+ QString expand(const QString& name);
+
+ /**
+ * Parse all files that can be formed by concatenation of the given stems.
+ */
+ void parseStems(const QStringList& stems);
+
+ bool m_inGenericFormalPart; ///< auxiliary variable
+
+ /**
+ * List for keeping track of tagged objects declared in the current scope.
+ * This is required for distinguishing primitive from non primitive
+ * methods.
+ */
+ UMLObjectList m_classesDefinedInThisScope;
+
+ typedef QMap<QString, QString> StringMap;
+
+ /**
+ * Map of package renamings.
+ * Keyed by the renaming. Value returns the expanded name.
+ */
+ StringMap m_renaming;
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/classimport.cpp b/umbrello/umbrello/codeimport/classimport.cpp
new file mode 100644
index 00000000..ed675bda
--- /dev/null
+++ b/umbrello/umbrello/codeimport/classimport.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "classimport.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <klocale.h>
+// app includes
+#include "../umldoc.h"
+#include "../uml.h"
+#include "idlimport.h"
+#include "pythonimport.h"
+#include "javaimport.h"
+#include "adaimport.h"
+#include "pascalimport.h"
+#include "cppimport.h"
+
+void ClassImport::importFiles(const QStringList &fileList) {
+ initialize();
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ uint processedFilesCount = 0;
+ for (QStringList::const_iterator fileIT = fileList.begin();
+ fileIT != fileList.end(); ++fileIT) {
+ QString fileName = (*fileIT);
+ umldoc->writeToStatusBar(i18n("Importing file: %1 Progress: %2/%3").
+ arg(fileName).arg(processedFilesCount).arg(fileList.size()));
+ parseFile(fileName);
+ processedFilesCount++;
+ }
+ umldoc->writeToStatusBar(i18n("Ready."));
+}
+
+ClassImport *ClassImport::createImporterByFileExt(const QString &filename) {
+ ClassImport *classImporter;
+ if (filename.endsWith(".idl"))
+ classImporter = new IDLImport();
+ else if (filename.endsWith(".py"))
+ classImporter = new PythonImport();
+ else if (filename.endsWith(".java"))
+ classImporter = new JavaImport();
+ else if (filename.contains( QRegExp("\\.ad[sba]$") ))
+ classImporter = new AdaImport();
+ else if (filename.endsWith(".pas"))
+ classImporter = new PascalImport();
+ else
+ classImporter = new CppImport(); // the default.
+ return classImporter;
+}
+
diff --git a/umbrello/umbrello/codeimport/classimport.h b/umbrello/umbrello/codeimport/classimport.h
new file mode 100644
index 00000000..351ddec5
--- /dev/null
+++ b/umbrello/umbrello/codeimport/classimport.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CLASSIMPORT_H
+#define CLASSIMPORT_H
+
+#include <qstringlist.h>
+
+/**
+ * Interfaces classparser library to uml models
+ * Abstract base for programming language specific import classes
+ * @author Mikko Pasanen
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class ClassImport {
+public:
+ ClassImport() {}
+ virtual ~ClassImport() {}
+
+ /**
+ * Import files.
+ *
+ * @param files List of files to import.
+ */
+ void importFiles(const QStringList &files);
+
+ /**
+ * Factory method.
+ */
+ static ClassImport *createImporterByFileExt(const QString &filename);
+
+protected:
+ /**
+ * Initialize the importer.
+ * This is called by importFiles() once, before entering
+ * the loop for importing one or more files.
+ * To be implemented by inheriting classes.
+ */
+ virtual void initialize() = 0;
+
+ /**
+ * Import a single file.
+ * To be implemented by inheriting classes.
+ *
+ * @param filename The file to import.
+ */
+ virtual void parseFile(const QString& filename) = 0;
+
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/cppimport.cpp b/umbrello/umbrello/codeimport/cppimport.cpp
new file mode 100644
index 00000000..4537c038
--- /dev/null
+++ b/umbrello/umbrello/codeimport/cppimport.cpp
@@ -0,0 +1,109 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "cppimport.h"
+// qt/kde includes
+#include <qmap.h>
+#include <qregexp.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../umlobject.h"
+#include "../docwindow.h"
+#include "../package.h"
+#include "../enum.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../template.h"
+#include "../association.h"
+#include "kdevcppparser/lexer.h"
+#include "kdevcppparser/driver.h"
+#include "kdevcppparser/cpptree2uml.h"
+
+// static members
+CppDriver * CppImport::ms_driver;
+QStringList CppImport::ms_seenFiles;
+
+class CppDriver : public Driver {
+public:
+ void setupLexer(Lexer* lexer) {
+ Driver::setupLexer(lexer);
+ lexer->setRecordComments(true);
+ }
+};
+
+CppImport::CppImport() {
+ ms_driver = new CppDriver();
+}
+
+CppImport::~CppImport() {}
+
+void CppImport::feedTheModel(const QString& fileName) {
+ if (ms_seenFiles.find(fileName) != ms_seenFiles.end())
+ return;
+ ms_seenFiles.append(fileName);
+ QMap<QString, Dependence> deps = ms_driver->dependences(fileName);
+ if (! deps.empty()) {
+ QMap<QString, Dependence>::Iterator it;
+ for (it = deps.begin(); it != deps.end(); ++it) {
+ if (it.data().second == Dep_Global) // don't want these
+ continue;
+ QString includeFile = it.key();
+ if (includeFile.isEmpty()) {
+ kError() << fileName << ": " << it.data().first
+ << " not found" << endl;
+ continue;
+ }
+ kDebug() << fileName << ": " << includeFile << " => " << it.data().first << endl;
+ if (ms_seenFiles.find(includeFile) == ms_seenFiles.end())
+ feedTheModel(includeFile);
+ }
+ }
+ TranslationUnitAST *ast = ms_driver->translationUnit( fileName );
+ if (ast == NULL) {
+ kError() << "CppImport::feedTheModel: " << fileName << " not found" << endl;
+ return;
+ }
+ CppTree2Uml modelFeeder( fileName );
+ modelFeeder.parseTranslationUnit( ast );
+}
+
+void CppImport::initialize() {
+ // Reset the driver
+ ms_driver->reset();
+ // The driver shall attempt to parse included files.
+ ms_driver->setResolveDependencesEnabled( true );
+ // Add some standard include paths
+ ms_driver->addIncludePath( "/usr/include" );
+ ms_driver->addIncludePath( "/usr/include/c++" );
+ ms_driver->addIncludePath( "/usr/include/g++" );
+ ms_driver->addIncludePath( "/usr/local/include" );
+ QStringList incPathList = Import_Utils::includePathList();
+ if (incPathList.count()) {
+ QStringList::Iterator end(incPathList.end());
+ for (QStringList::Iterator i(incPathList.begin()); i != end; ++i) {
+ ms_driver->addIncludePath( *i );
+ }
+
+ }
+ ms_seenFiles.clear();
+}
+
+void CppImport::parseFile(const QString& fileName) {
+ if (ms_seenFiles.find(fileName) != ms_seenFiles.end())
+ return;
+ ms_driver->parseFile( fileName );
+ feedTheModel(fileName);
+}
+
diff --git a/umbrello/umbrello/codeimport/cppimport.h b/umbrello/umbrello/codeimport/cppimport.h
new file mode 100644
index 00000000..3d5d8195
--- /dev/null
+++ b/umbrello/umbrello/codeimport/cppimport.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CPPIMPORT_H
+#define CPPIMPORT_H
+
+#include <qstring.h>
+#include "classimport.h"
+
+class CppDriver;
+
+/**
+ * C++ code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+class CppImport : public ClassImport {
+public:
+ CppImport();
+ virtual ~CppImport();
+
+protected:
+ /**
+ * Implement abstract operation from ClassImport for C++.
+ */
+ void initialize();
+
+ /**
+ * Import a single file.
+ *
+ * @param filename The file to import.
+ */
+ void parseFile(const QString& filename);
+
+private:
+ /**
+ * Auxiliary method for recursively traversing the #include dependencies
+ * in order to feed innermost includes to the model before dependent
+ * includes. It is important that includefiles are fed to the model
+ * in proper order so that references between UML objects are created
+ * properly.
+ */
+ void feedTheModel(const QString& fileName);
+
+ static CppDriver * ms_driver;
+ static QStringList ms_seenFiles; ///< auxiliary buffer for feedTheModel()
+
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/idlimport.cpp b/umbrello/umbrello/codeimport/idlimport.cpp
new file mode 100644
index 00000000..6d228baf
--- /dev/null
+++ b/umbrello/umbrello/codeimport/idlimport.cpp
@@ -0,0 +1,356 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "idlimport.h"
+
+#include <stdio.h>
+// qt/kde includes
+// #include <qprocess.h> //should use this instead of popen()
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+IDLImport::IDLImport() : NativeImportBase("//") {
+ m_isOneway = m_isReadonly = m_isAttribute = false;
+ setMultiLineComment("/*", "*/");
+}
+
+IDLImport::~IDLImport() {
+}
+
+/// Check for split type names (e.g. unsigned long long)
+QString IDLImport::joinTypename() {
+ QString typeName = m_source[m_srcIndex];
+ if (m_source[m_srcIndex] == "unsigned")
+ typeName += ' ' + advance();
+ if (m_source[m_srcIndex] == "long" &&
+ (m_source[m_srcIndex + 1] == "long" || m_source[m_srcIndex + 1] == "double"))
+ typeName += ' ' + advance();
+ return typeName;
+}
+
+bool IDLImport::preprocess(QString& line) {
+ // Ignore C preprocessor generated lines.
+ if (line.startsWith("#"))
+ return true; // done
+ return NativeImportBase::preprocess(line);
+}
+
+void IDLImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ QChar c = word[i];
+ if (c.isLetterOrNumber() || c == '_') {
+ lexeme += c;
+ } else if (c == ':' && word[i + 1] == ':') {
+ // compress scoped name into lexeme
+ lexeme += "::";
+ i++;
+ } else if (c == '<') {
+ // compress sequence or bounded string into lexeme
+ do {
+ lexeme += word[i];
+ } while (word[i] != '>' && ++i < len);
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ m_source.append(QString(c));
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+void IDLImport::parseFile(const QString& filename) {
+ if (filename.contains('/')) {
+ QString path = filename;
+ path.remove( QRegExp("/[^/]+$") );
+ kDebug() << "IDLImport::parseFile: adding path " << path << endl;
+ Import_Utils::addIncludePath(path);
+ }
+ QStringList includePaths = Import_Utils::includePathList();
+ //QProcess command("cpp", UMLAp::app());
+ QString command("cpp -C"); // -C means "preserve comments"
+ for (QStringList::Iterator pathIt = includePaths.begin();
+ pathIt != includePaths.end(); ++pathIt) {
+ QString path = (*pathIt);
+ //command.addArgument(" -I" + path);
+ command += " -I" + path;
+ }
+ command += ' ' + filename;
+ kDebug() << "importIDL: " << command << endl;
+ FILE *fp = popen(command.ascii(), "r");
+ if (fp == NULL) {
+ kError() << "IDLImport::parseFile: cannot popen(" << command << ")" << endl;
+ return;
+ }
+ // Scan the input file into the QStringList m_source.
+ m_source.clear();
+ char buf[256];
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ int len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ buf[--len] = '\0';
+ NativeImportBase::scan( QString(buf) );
+ }
+ // Parse the QStringList m_source.
+ m_scopeIndex = 0;
+ m_scope[0] = NULL;
+ const uint srcLength = m_source.count();
+ for (m_srcIndex = 0; m_srcIndex < srcLength; m_srcIndex++) {
+ const QString& keyword = m_source[m_srcIndex];
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword.startsWith(m_singleLineCommentIntro)) {
+ m_comment = keyword.mid(m_singleLineCommentIntro.length());
+ continue;
+ }
+ if (! parseStmt())
+ skipStmt();
+ m_currentAccess = Uml::Visibility::Public;
+ m_comment = QString();
+ }
+ pclose(fp);
+}
+
+bool IDLImport::parseStmt() {
+ const QString& keyword = m_source[m_srcIndex];
+ const uint srcLength = m_source.count();
+ if (keyword == "module") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ m_scope[m_scopeIndex]->setStereotype("CORBAModule");
+ if (advance() != "{") {
+ kError() << "importIDL: unexpected: " << m_source[m_srcIndex] << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "interface") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_klass->setStereotype("CORBAInterface");
+ m_klass->setAbstract(m_isAbstract);
+ m_isAbstract = false;
+ m_comment = QString();
+ if (advance() == ";") // forward declaration
+ return true;
+ if (m_source[m_srcIndex] == ":") {
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
+ const QString& baseName = m_source[m_srcIndex];
+ Import_Utils::createGeneralization(m_klass, baseName);
+ if (advance() != ",")
+ break;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ kError() << "importIDL: ignoring excess chars at "
+ << name << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "struct" || keyword == "exception") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ if (keyword == "struct")
+ m_klass->setStereotype("CORBAStruct");
+ else
+ m_klass->setStereotype("CORBAException");
+ if (advance() != "{") {
+ kError() << "importIDL: expecting '{' at " << name << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "union") {
+ // TBD. <gulp>
+ skipStmt("}");
+ m_srcIndex++; // advance to ';'
+ return true;
+ }
+ if (keyword == "enum") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ m_srcIndex++; // skip name
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != "}") {
+ Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+ if (advance() != ",")
+ break;
+ }
+ skipStmt();
+ return true;
+ }
+ if (keyword == "typedef") {
+ const QString& existingType = advance();
+ const QString& newType = advance();
+ Import_Utils::createUMLObject(Uml::ot_Class, newType, m_scope[m_scopeIndex],
+ m_comment, "CORBATypedef" /* stereotype */);
+ // @todo How do we convey the existingType ?
+ skipStmt();
+ return true;
+ }
+ if (keyword == "const") {
+ skipStmt();
+ return true;
+ }
+ if (keyword == "custom") {
+ return true;
+ }
+ if (keyword == "abstract") {
+ m_isAbstract = true;
+ return true;
+ }
+ if (keyword == "valuetype") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_klass->setAbstract(m_isAbstract);
+ m_isAbstract = false;
+ if (advance() == ";") // forward declaration
+ return true;
+ if (m_source[m_srcIndex] == ":") {
+ if (advance() == "truncatable")
+ m_srcIndex++;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != "{") {
+ const QString& baseName = m_source[m_srcIndex];
+ Import_Utils::createGeneralization(m_klass, baseName);
+ if (advance() != ",")
+ break;
+ m_srcIndex++;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ kError() << "importIDL: ignoring excess chars at "
+ << name << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "public") {
+ return true;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "readonly") {
+ m_isReadonly = true;
+ return true;
+ }
+ if (keyword == "attribute") {
+ m_isAttribute = true;
+ return true;
+ }
+ if (keyword == "oneway") {
+ m_isOneway = true;
+ return true;
+ }
+ if (keyword == "}") {
+ if (m_scopeIndex)
+ m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+ else
+ kError() << "importIDL: too many }" << endl;
+ m_srcIndex++; // skip ';'
+ return true;
+ }
+ if (keyword == ";")
+ return true;
+ // At this point, we expect `keyword' to be a type name
+ // (of a member of struct or valuetype, or return type
+ // of an operation.) Up next is the name of the attribute
+ // or operation.
+ if (! keyword.contains( QRegExp("^\\w") )) {
+ kError() << "importIDL: ignoring " << keyword << endl;
+ return false;
+ }
+ QString typeName = joinTypename();
+ QString name = advance();
+ if (name.contains( QRegExp("\\W") )) {
+ kError() << "importIDL: expecting name in " << name << endl;
+ return false;
+ }
+ // At this point we most definitely need a class.
+ if (m_klass == NULL) {
+ kError() << "importIDL: no class set for " << name << endl;
+ return false;
+ }
+ QString nextToken = advance();
+ if (nextToken == "(") {
+ // operation
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ m_srcIndex++;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ const QString &direction = m_source[m_srcIndex++];
+ QString typeName = joinTypename();
+ const QString &parName = advance();
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName);
+ Uml::Parameter_Direction dir;
+ if (Model_Utils::stringToDirection(direction, dir))
+ att->setParmKind(dir);
+ else
+ kError() << "importIDL: expecting parameter direction at "
+ << direction << endl;
+ if (advance() != ",")
+ break;
+ m_srcIndex++;
+ }
+ Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, typeName,
+ false, false, false, false, m_comment);
+ if (m_isOneway) {
+ op->setStereotype("oneway");
+ m_isOneway = false;
+ }
+ skipStmt(); // skip possible "raises" clause
+ return true;
+ }
+ // At this point we know it's some kind of attribute declaration.
+ while (1) {
+ while (nextToken != "," && nextToken != ";") {
+ name += nextToken; // add possible array dimensions to `name'
+ nextToken = advance();
+ }
+ UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment);
+ UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ if (m_isReadonly) {
+ attr->setStereotype("readonly");
+ m_isReadonly = false;
+ }
+ if (nextToken != ",")
+ break;
+ name = advance();
+ nextToken = advance();
+ }
+ return true;
+}
+
diff --git a/umbrello/umbrello/codeimport/idlimport.h b/umbrello/umbrello/codeimport/idlimport.h
new file mode 100644
index 00000000..6945364f
--- /dev/null
+++ b/umbrello/umbrello/codeimport/idlimport.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef IDLIMPORT_H
+#define IDLIMPORT_H
+
+#include "nativeimportbase.h"
+
+/**
+ * CORBA IDL code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class IDLImport : public NativeImportBase {
+public:
+ IDLImport();
+ virtual ~IDLImport();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Reimplement operation from NativeImportBase.
+ * Need to do this because we use the external C preprocessor.
+ */
+ void parseFile(const QString& file);
+
+ /**
+ * Override operation from NativeImportBase.
+ */
+ bool preprocess(QString& line);
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+protected:
+ QString joinTypename();
+ bool m_isOneway, m_isReadonly, m_isAttribute;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/import_utils.cpp b/umbrello/umbrello/codeimport/import_utils.cpp
new file mode 100644
index 00000000..92a87867
--- /dev/null
+++ b/umbrello/umbrello/codeimport/import_utils.cpp
@@ -0,0 +1,464 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "import_utils.h"
+// qt/kde includes
+#include <qmap.h>
+#include <qregexp.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <klocale.h>
+// app includes
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umllistview.h"
+#include "../umllistviewitem.h"
+#include "../umlobject.h"
+#include "../package.h"
+#include "../folder.h"
+#include "../enum.h"
+#include "../classifier.h"
+#include "../operation.h"
+#include "../attribute.h"
+#include "../template.h"
+#include "../association.h"
+#include "../object_factory.h"
+
+#include <stdlib.h>
+
+namespace Import_Utils {
+
+/**
+ * Flag manipulated by createUMLObject().
+ * Global state is generally bad, I know.
+ * It would be cleaner to make this into a return value from
+ * createUMLObject().
+ */
+bool bNewUMLObjectWasCreated = false;
+
+/**
+ * Related classifier for creation of dependencies on template
+ * parameters in createUMLObject().
+ */
+UMLClassifier * gRelatedClassifier = NULL;
+
+/**
+ * On encountering a scoped typename string where the scopes
+ * have not yet been seen, we synthesize UML objects for the
+ * unknown scopes (using a question dialog to the user to decide
+ * whether to treat a scope as a class or as a package.)
+ * However, such an unknown scope is put at the global level.
+ * I.e. before calling createUMLObject() we set this flag to true.
+ */
+bool bPutAtGlobalScope = false;
+
+/**
+ * The include path list (see addIncludePath() and includePathList())
+ */
+QStringList incPathList;
+
+void putAtGlobalScope(bool yesno) {
+ bPutAtGlobalScope = yesno;
+}
+
+void setRelatedClassifier(UMLClassifier *c) {
+ gRelatedClassifier = c;
+}
+
+void assignUniqueIdOnCreation(bool yesno) {
+ Object_Factory::assignUniqueIdOnCreation(yesno);
+}
+
+bool newUMLObjectWasCreated() {
+ return bNewUMLObjectWasCreated;
+}
+
+QString formatComment(const QString &comment) {
+ if (comment.isEmpty())
+ return comment;
+
+ QStringList lines = QStringList::split("\n", comment);
+ QString& first = lines.first();
+ QRegExp wordex("\\w");
+ if (first.startsWith("/*")) {
+ int wordpos = wordex.search(first);
+ if (wordpos != -1)
+ first = first.mid(wordpos); // remove comment start
+ else
+ lines.pop_front(); // nothing interesting on this line
+ }
+ QString& last = lines.last();
+ int endpos = last.find("*/");
+ if (endpos != -1) {
+ if (last.contains(wordex))
+ last = last.mid(0, endpos - 1); // remove comment end
+ else
+ lines.pop_back(); // nothing interesting on this line
+ }
+ if (! lines.count())
+ return "";
+
+ QStringList::Iterator end(lines.end());
+ for (QStringList::Iterator lit(lines.begin()); lit != end; ++lit) {
+ (*lit).remove(QRegExp("^\\s+"));
+ (*lit).remove(QRegExp("^\\*+\\s?"));
+ }
+ return lines.join("\n");
+}
+
+/*
+UMLObject* findUMLObject(QString name,
+ Uml::Object_Type type) {
+ // Why an extra wrapper? See comment at addMethodParameter()
+ UMLObject * o = umldoc->findUMLObject(name, type);
+ return o;
+}
+ */
+
+UMLObject *createUMLObject(Uml::Object_Type type,
+ const QString& inName,
+ UMLPackage *parentPkg,
+ const QString& comment,
+ const QString& stereotype) {
+ QString name = inName;
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
+ const Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ if (parentPkg == NULL) {
+ // kDebug() << "Import_Utils::createUMLObject(" << name
+ // << "): parentPkg is NULL, assuming Logical View" << endl;
+ parentPkg = logicalView;
+ }
+ UMLObject * o = umldoc->findUMLObject(name, type, parentPkg);
+ bNewUMLObjectWasCreated = false;
+ if (o == NULL) {
+ // Strip possible adornments and look again.
+ int isConst = name.contains(QRegExp("^const "));
+ name.remove(QRegExp("^const\\s+"));
+ QString typeName(name);
+ const int isAdorned = typeName.contains( QRegExp("[^\\w:\\. ]") );
+ const int isPointer = typeName.contains('*');
+ const int isRef = typeName.contains('&');
+ typeName.remove(QRegExp("[^\\w:\\. ].*$"));
+ typeName = typeName.simplifyWhiteSpace();
+ UMLObject *origType = umldoc->findUMLObject(typeName, Uml::ot_UMLObject, parentPkg);
+ if (origType == NULL) {
+ // Still not found. Create the stripped down type.
+ if (bPutAtGlobalScope)
+ parentPkg = logicalView;
+ // Find, or create, the scopes.
+ QStringList components;
+ if (typeName.contains("::")) {
+ components = QStringList::split("::", typeName);
+ } else if (typeName.contains(".")) {
+ components = QStringList::split(".", typeName);
+ }
+ if (components.count() > 1) {
+ typeName = components.back();
+ components.pop_back();
+ while ( components.count() ) {
+ QString scopeName = components.front();
+ components.pop_front();
+ o = umldoc->findUMLObject(scopeName, Uml::ot_UMLObject, parentPkg);
+ if (o) {
+ parentPkg = static_cast<UMLPackage*>(o);
+ continue;
+ }
+ int wantNamespace = KMessageBox::Yes;
+ if (pl == Uml::pl_Cpp) {
+ /* We know std and Qt are namespaces */
+ if (scopeName != "std" && scopeName != "Qt") {
+ wantNamespace = KMessageBox::questionYesNo(NULL,
+ i18n("Is the scope %1 a namespace or a class?").arg(scopeName),
+ i18n("C++ Import Requests Your Help"),
+ i18n("Namespace"), i18n("Class"));
+ }
+ }
+ Uml::Object_Type ot = (wantNamespace == KMessageBox::Yes ? Uml::ot_Package : Uml::ot_Class);
+ o = Object_Factory::createUMLObject(ot, scopeName, parentPkg);
+ parentPkg = static_cast<UMLPackage*>(o);
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *lvitem = listView->findUMLObject(o);
+ listView->setCurrentItem(lvitem);
+ }
+ // All scope qualified datatypes live in the global scope.
+ bPutAtGlobalScope = true;
+ }
+ Uml::Object_Type t = type;
+ if (type == Uml::ot_UMLObject || isAdorned)
+ t = Uml::ot_Class;
+ origType = Object_Factory::createUMLObject(t, typeName, parentPkg, false);
+ bNewUMLObjectWasCreated = true;
+ bPutAtGlobalScope = false;
+ }
+ if (isConst || isAdorned) {
+ // Create the full given type (including adornments.)
+ if (isConst)
+ name.prepend("const ");
+ o = Object_Factory::createUMLObject(Uml::ot_Datatype, name,
+ umldoc->getDatatypeFolder(),
+ false); //solicitNewName
+ UMLClassifier *dt = static_cast<UMLClassifier*>(o);
+ UMLClassifier *c = dynamic_cast<UMLClassifier*>(origType);
+ if (c)
+ dt->setOriginType(c);
+ else
+ kError() << "createUMLObject(" << name << "): "
+ << "origType " << typeName << " is not a UMLClassifier"
+ << endl;
+ if (isRef || isPointer)
+ dt->setIsReference();
+ /*
+ if (isPointer) {
+ UMLObject *pointerDecl = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
+ UMLClassifier *dt = static_cast<UMLClassifier*>(pointerDecl);
+ dt->setOriginType(classifier);
+ dt->setIsReference();
+ classifier = dt;
+ } */
+ } else {
+ o = origType;
+ }
+ } else if (parentPkg && !bPutAtGlobalScope) {
+ UMLPackage *existingPkg = o->getUMLPackage();
+ if (existingPkg != umldoc->getDatatypeFolder()) {
+ if (existingPkg)
+ existingPkg->removeObject(o);
+ else
+ kError() << "createUMLObject(" << name << "): "
+ << "o->getUMLPackage() was NULL" << endl;
+ o->setUMLPackage(parentPkg);
+ parentPkg->addObject(o);
+ }
+ }
+ QString strippedComment = formatComment(comment);
+ if (! strippedComment.isEmpty()) {
+ o->setDoc(strippedComment);
+ }
+ if (!stereotype.isEmpty()) {
+ o->setStereotype(stereotype);
+ }
+ if (gRelatedClassifier == NULL || gRelatedClassifier == o)
+ return o;
+ QRegExp templateInstantiation("^[\\w:\\.]+\\s*<(.*)>");
+ int pos = templateInstantiation.search(name);
+ if (pos == -1)
+ return o;
+ // Create dependencies on template parameters.
+ QString caption = templateInstantiation.cap(1);
+ QStringList params = QStringList::split(QRegExp("[^\\w:\\.]+"), caption);
+ if (!params.count())
+ return o;
+ QStringList::Iterator end(params.end());
+ for (QStringList::Iterator it(params.begin()); it != end; ++it) {
+ UMLObject *p = umldoc->findUMLObject(*it, Uml::ot_UMLObject, parentPkg);
+ if (p == NULL || p->getBaseType() == Uml::ot_Datatype)
+ continue;
+ const Uml::Association_Type at = Uml::at_Dependency;
+ UMLAssociation *assoc = umldoc->findAssociation(at, gRelatedClassifier, p);
+ if (assoc)
+ continue;
+ assoc = new UMLAssociation(at, gRelatedClassifier, p);
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ umldoc->addAssociation(assoc);
+ }
+ return o;
+}
+
+UMLOperation* makeOperation(UMLClassifier *parent, const QString &name) {
+ UMLOperation *op = Object_Factory::createOperation(parent, name);
+ return op;
+}
+
+UMLObject* insertAttribute(UMLClassifier *owner,
+ Uml::Visibility scope,
+ const QString& name,
+ UMLClassifier *attrType,
+ const QString& comment /* ="" */,
+ bool isStatic /* =false */) {
+ Uml::Object_Type ot = owner->getBaseType();
+ Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
+ if (! (ot == Uml::ot_Class || ot == Uml::ot_Interface && pl == Uml::pl_Java)) {
+ kDebug() << "insertAttribute: Don't know what to do with "
+ << owner->getName() << " (object type " << ot << ")" << endl;
+ return NULL;
+ }
+ UMLObject *o = owner->findChildObject(name, Uml::ot_Attribute);
+ if (o) {
+ return o;
+ }
+
+ UMLAttribute *attr = owner->addAttribute(name, attrType, scope);
+ attr->setStatic(isStatic);
+ QString strippedComment = formatComment(comment);
+ if (! strippedComment.isEmpty()) {
+ attr->setDoc(strippedComment);
+ }
+
+ UMLApp::app()->getDocument()->setModified(true);
+ return attr;
+}
+
+UMLObject* insertAttribute(UMLClassifier *owner, Uml::Visibility scope,
+ const QString& name,
+ const QString& type,
+ const QString& comment /* ="" */,
+ bool isStatic /* =false */) {
+ UMLObject *attrType = owner->findTemplate(type);
+ if (attrType == NULL) {
+ bPutAtGlobalScope = true;
+ gRelatedClassifier = owner;
+ attrType = createUMLObject(Uml::ot_UMLObject, type, owner);
+ gRelatedClassifier = NULL;
+ bPutAtGlobalScope = false;
+ }
+ return insertAttribute (owner, scope, name,
+ static_cast<UMLClassifier*>(attrType),
+ comment, isStatic);
+}
+
+void insertMethod(UMLClassifier *klass, UMLOperation* &op,
+ Uml::Visibility scope, const QString& type,
+ bool isStatic, bool isAbstract,
+ bool isFriend, bool isConstructor,
+ const QString& comment) {
+ op->setVisibility(scope);
+ if (!type.isEmpty() // return type may be missing (constructor/destructor)
+ && type != "void") {
+ if (type == klass->getName()) {
+ op->setType(klass);
+ } else {
+ UMLObject *typeObj = klass->findTemplate(type);
+ if (typeObj == NULL) {
+ bPutAtGlobalScope = true;
+ gRelatedClassifier = klass;
+ typeObj = createUMLObject(Uml::ot_UMLObject, type, klass);
+ gRelatedClassifier = NULL;
+ bPutAtGlobalScope = false;
+ op->setType(typeObj);
+ }
+ }
+ }
+
+ op->setStatic(isStatic);
+ op->setAbstract(isAbstract);
+
+ // if the operation is friend, add it as a stereotype
+ if (isFriend)
+ op->setStereotype("friend");
+ // if the operation is a constructor, add it as a stereotype
+ if (isConstructor)
+ op->setStereotype("constructor");
+
+ QString strippedComment = formatComment(comment);
+ if (! strippedComment.isEmpty()) {
+ op->setDoc(strippedComment);
+ }
+
+ UMLAttributeList params = op->getParmList();
+ UMLOperation *exist = klass->checkOperationSignature(op->getName(), params);
+ if (exist) {
+ // copy contents to existing operation
+ exist->setVisibility(scope);
+ exist->setStatic(isStatic);
+ exist->setAbstract(isAbstract);
+ if (! strippedComment.isEmpty())
+ exist->setDoc(strippedComment);
+ UMLAttributeList exParams = exist->getParmList();
+ UMLAttribute *param, *exParam = exParams.first();
+ for (UMLAttributeListIt it(params); (param = it.current()) != NULL;
+ ++it, exParam = exParams.next()) {
+ exParam->setName(param->getName());
+ exParam->setVisibility(param->getVisibility());
+ exParam->setStatic(param->getStatic());
+ exParam->setAbstract(param->getAbstract());
+ exParam->setDoc(param->getDoc());
+ exParam->setInitialValue(param->getInitialValue());
+ exParam->setParmKind(param->getParmKind());
+ }
+ // delete incoming UMLOperation and pass out the existing one
+ delete op;
+ op = exist;
+ } else {
+ klass->addOperation(op);
+ }
+}
+
+UMLAttribute* addMethodParameter(UMLOperation *method,
+ const QString& type,
+ const QString& name) {
+ UMLClassifier *owner = static_cast<UMLClassifier*>(method->parent());
+ UMLObject *typeObj = owner->findTemplate(type);
+ if (typeObj == NULL) {
+ bPutAtGlobalScope = true;
+ gRelatedClassifier = owner;
+ typeObj = createUMLObject(Uml::ot_UMLObject, type, owner);
+ gRelatedClassifier = NULL;
+ bPutAtGlobalScope = false;
+ }
+ UMLAttribute *attr = Object_Factory::createAttribute(method, name, typeObj);
+ method->addParm(attr);
+ return attr;
+}
+
+void addEnumLiteral(UMLEnum *enumType, const QString &literal, const QString &comment) {
+ UMLObject *el = enumType->addEnumLiteral(literal);
+ el->setDoc(comment);
+}
+
+void createGeneralization(UMLClassifier *child, UMLClassifier *parent) {
+ // if the child is an interface, so is the parent.
+ if (child->isInterface())
+ parent->setBaseType(Uml::ot_Interface);
+ Uml::Association_Type association = Uml::at_Generalization;
+
+ if (parent->isInterface() && !child->isInterface()) {
+ // if the parent is an interface, but the child is not, then
+ // this is really realization.
+ //
+ association = Uml::at_Realization;
+ }
+ UMLAssociation *assoc = new UMLAssociation(association, child, parent);
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
+ umldoc->addAssociation(assoc);
+}
+
+void createGeneralization(UMLClassifier *child, const QString &parentName) {
+ UMLObject *parentObj = createUMLObject( Uml::ot_Class, parentName );
+ UMLClassifier *parent = static_cast<UMLClassifier*>(parentObj);
+ createGeneralization(child, parent);
+}
+
+QStringList includePathList() {
+ QStringList includePathList(incPathList);
+ char *umbrello_incpath = getenv( "UMBRELLO_INCPATH" );
+ if (umbrello_incpath) {
+ includePathList += QStringList::split( ':', umbrello_incpath );
+ }
+ return includePathList;
+}
+
+void addIncludePath(const QString& path) {
+ if (! incPathList.contains(path))
+ incPathList.append(path);
+}
+
+
+bool isDatatype(const QString& name, UMLPackage *parentPkg) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLObject * o = umldoc->findUMLObject(name, Uml::ot_Datatype, parentPkg);
+ return (o!=NULL);
+}
+
+} // end namespace Import_Utils
+
diff --git a/umbrello/umbrello/codeimport/import_utils.h b/umbrello/umbrello/codeimport/import_utils.h
new file mode 100644
index 00000000..7d36bc77
--- /dev/null
+++ b/umbrello/umbrello/codeimport/import_utils.h
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef IMPORT_UTILS_H
+#define IMPORT_UTILS_H
+
+#include <qstringlist.h>
+#include "../umlnamespace.h"
+#include "../umlattributelist.h"
+
+class UMLObject;
+class UMLClassifier;
+class UMLPackage;
+class UMLOperation;
+class UMLEnum;
+
+/**
+ * Utilities for code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+
+namespace Import_Utils {
+
+ /**
+ * Find or create a document object.
+ */
+ UMLObject* createUMLObject(Uml::Object_Type type,
+ const QString& name,
+ UMLPackage *parentPkg = NULL,
+ const QString& comment = QString::null,
+ const QString& stereotype = QString::null);
+ /**
+ * Control whether an object which is newly created by createUMLObject()
+ * is put at the global scope.
+ *
+ * @param yesno When set to false, the object is created at the scope
+ * given by the parentPkg argument of createUMLObject().
+ */
+ void putAtGlobalScope(bool yesno);
+
+ /**
+ * Set a related classifier for creation of dependencies on template
+ * parameters in createUMLObject().
+ */
+ void setRelatedClassifier(UMLClassifier *c);
+
+ /**
+ * Control whether the creation methods solicit a new unique ID for the
+ * created object.
+ * By default, unique ID generation is turned on.
+ *
+ * @param yesno False turns UID generation off, true turns it on.
+ */
+ void assignUniqueIdOnCreation(bool yesno);
+
+ /**
+ * Create a UMLAttribute and insert it into the document.
+ */
+ UMLObject* insertAttribute(UMLClassifier *klass, Uml::Visibility scope,
+ const QString& name,
+ const QString& type,
+ const QString& comment = QString::null,
+ bool isStatic = false);
+ /**
+ * Create a UMLAttribute and insert it into the document.
+ * Use the specified existing attrType.
+ */
+ UMLObject* insertAttribute(UMLClassifier *klass, Uml::Visibility scope,
+ const QString& name,
+ UMLClassifier *attrType,
+ const QString& comment /* ="" */,
+ bool isStatic /* =false */);
+ /**
+ * Create a UMLOperation.
+ * The reason for this method is to not generate any Qt signals.
+ * Instead, these are generated by insertMethod().
+ * (If we generated a creation signal prematurely, i.e. without
+ * the method parameters being known yet, then that would lead to
+ * a conflict with a pre-existing parameterless method of the same
+ * name.)
+ */
+ UMLOperation* makeOperation(UMLClassifier *parent, const QString &name);
+
+ /**
+ * Insert the UMLOperation into the given classifier.
+ *
+ * @param klass The classifier into which the operation shall be added.
+ * @param op Reference to pointer to the temporary UMLOperation
+ * for insertion. The caller relinquishes ownership of the
+ * object pointed to. If an UMLOperation of same signature
+ * already exists at the classifier then the incoming
+ * UMLOperation is deleted and the pointer is set to the
+ * existing UMLOperation.
+ * @param scope The Uml::Visibility of the method
+ * @param type The return type
+ * @param isStatic boolean switch to decide if method is static
+ * @param isAbstract boolean switch to decide if method is abstract
+ * @param isFriend true boolean switch to decide if methods is a friend function
+ * @param isConstructor boolean switch to decide if methods is a constructor
+ * @param comment The Documentation for this method
+ */
+ void insertMethod(UMLClassifier *klass, UMLOperation* &op,
+ Uml::Visibility scope, const QString& type,
+ bool isStatic, bool isAbstract,
+ bool isFriend = false, bool isConstructor = false,
+ const QString& comment = QString::null);
+
+ /**
+ * Add an argument to a UMLOperation.
+ * The parentPkg arg is only used for resolving possible scope
+ * prefixes in the `type'.
+ */
+ UMLAttribute* addMethodParameter(UMLOperation *method,
+ const QString& type,
+ const QString& name);
+
+ /**
+ * Add an enum literal to an UMLEnum.
+ */
+ void addEnumLiteral(UMLEnum *enumType, const QString &literal,
+ const QString &comment = QString());
+
+ /**
+ * Create a generalization from the given child classifier to the given
+ * parent classifier.
+ */
+ void createGeneralization(UMLClassifier *child, UMLClassifier *parent);
+
+ /**
+ * Create a generalization from the existing child UMLObject to the given
+ * parent class name.
+ */
+ void createGeneralization(UMLClassifier *child, const QString &parentName);
+
+ /**
+ * Strip comment lines of leading whitespace and stars.
+ */
+ QString formatComment(const QString &comment);
+
+ /**
+ * Return the list of paths set by previous calls to addIncludePath()
+ * and the environment variable UMBRELLO_INCPATH.
+ * This list can be used for finding #included (or Ada with'ed or...)
+ * files.
+ */
+ QStringList includePathList();
+
+ /**
+ * Add a path to the include path list.
+ */
+ void addIncludePath(const QString& path);
+
+ /**
+ * Returns whether the last createUMLObject() actually created
+ * a new object or just returned an existing one.
+ */
+ bool newUMLObjectWasCreated();
+
+ /**
+ * Returns true if a type is an actual Datatype
+ */
+ bool isDatatype(const QString& name, UMLPackage *parentPkg = NULL);
+
+} // end namespace Import_Utils
+
+#endif
diff --git a/umbrello/umbrello/codeimport/javaimport.cpp b/umbrello/umbrello/codeimport/javaimport.cpp
new file mode 100644
index 00000000..8df6e5e7
--- /dev/null
+++ b/umbrello/umbrello/codeimport/javaimport.cpp
@@ -0,0 +1,549 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "javaimport.h"
+
+// qt/kde includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+QStringList JavaImport::s_filesAlreadyParsed;
+int JavaImport::s_parseDepth = 0;
+
+JavaImport::JavaImport() : NativeImportBase("//") {
+ setMultiLineComment("/*", "*/");
+ initVars();
+}
+
+JavaImport::~JavaImport() {
+}
+
+void JavaImport::initVars() {
+ m_isStatic = false;
+}
+
+/// Catenate possible template arguments/array dimensions to the end of the type name.
+QString JavaImport::joinTypename(QString typeName) {
+ if (m_source[m_srcIndex + 1] == "<" ||
+ m_source[m_srcIndex + 1] == "[") {
+ uint start = ++m_srcIndex;
+ if (! skipToClosing(m_source[start][0]))
+ return typeName;
+ for (uint i = start; i <= m_srcIndex; i++) {
+ typeName += m_source[i];
+ }
+ }
+ // to handle multidimensional arrays, call recursively
+ if (m_source[m_srcIndex + 1] == "[") {
+ typeName = joinTypename( typeName );
+ }
+ return typeName;
+}
+
+void JavaImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ const QChar& c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ m_source.append(QString(c));
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+
+///Spawn off an import of the specified file
+void JavaImport::spawnImport( QString file ) {
+ // if the file is being parsed, don't bother
+ //
+ if (s_filesAlreadyParsed.contains( file ) ) {
+ return;
+ }
+ if (QFile::exists(file)) {
+ JavaImport importer;
+ QStringList fileList;
+ fileList.append( file );
+ s_filesAlreadyParsed.append( file );
+ importer.importFiles( fileList );
+ }
+}
+
+
+///returns the UML Object if found, or null otherwise
+UMLObject* findObject( QString name, UMLPackage *parentPkg ) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ UMLObject * o = umldoc->findUMLObject(name, Uml::ot_UMLObject , parentPkg);
+ return o;
+}
+
+
+///Resolve the specified className
+UMLObject* JavaImport::resolveClass (QString className) {
+ kDebug() << "importJava trying to resolve " << className << endl;
+ // keep track if we are dealing with an array
+ //
+ bool isArray = className.contains('[');
+ // remove any [] so that the class itself can be resolved
+ //
+ QString baseClassName = className;
+ baseClassName.remove('[');
+ baseClassName.remove(']');
+
+ // java has a few implicit imports. Most relevant for this is the
+ // current package, which is in the same directory as the current file
+ // being parsed
+ //
+ QStringList file = QStringList::split( '/', m_currentFileName);
+ // remove the filename. This leaves the full path to the containing
+ // dir which should also include the package hierarchy
+ //
+ file.pop_back();
+
+ // the file we're looking for might be in the same directory as the
+ // current class
+ //
+ QString myDir = file.join( "/" );
+ QString myFile = '/' + myDir + '/' + baseClassName + ".java";
+ if ( QFile::exists(myFile) ) {
+ spawnImport( myFile );
+ if ( isArray ) {
+ // we have imported the type. For arrays we want to return
+ // the array type
+ return Import_Utils::createUMLObject(Uml::ot_Class, className, m_scope[m_scopeIndex]);
+ }
+ return findObject(baseClassName, m_scope[m_scopeIndex]);
+ }
+
+ // the class we want is not in the same package as the one being imported.
+ // use the imports to find the one we want.
+ //
+ QStringList package = QStringList::split( '.', m_currentPackage);
+ int dirsInPackageCount = package.size();
+
+ for (int count=0; count < dirsInPackageCount; count ++ ) {
+ // pop off one by one the directories, until only the source root remains
+ //
+ file.pop_back();
+ }
+ // this is now the root of any further source imports
+ QString sourceRoot = '/' + file.join("/") + '/';
+
+ for (QStringList::Iterator pathIt = m_imports.begin();
+ pathIt != m_imports.end(); ++pathIt) {
+ QString import = (*pathIt);
+ QStringList split = QStringList::split( '.', import );
+ split.pop_back(); // remove the * or the classname
+ if ( import.endsWith( "*" ) || import.endsWith( baseClassName) ) {
+ // check if the file we want is in this imported package
+ // convert the org.test type package into a filename
+ //
+ QString aFile = sourceRoot + split.join("/") + '/' + baseClassName + ".java";
+ if ( QFile::exists(aFile) ) {
+ spawnImport( aFile );
+ // we need to set the package for the class that will be resolved
+ // start at the root package
+ UMLPackage *parent = m_scope[0];
+ UMLPackage *current = NULL;
+
+ for (QStringList::Iterator it = split.begin(); it != split.end(); ++it) {
+ QString name = (*it);
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+ name, parent);
+ current = static_cast<UMLPackage*>(ns);
+ parent = current;
+ } // for
+ if ( isArray ) {
+ // we have imported the type. For arrays we want to return
+ // the array type
+ return Import_Utils::createUMLObject(Uml::ot_Class, className, current);
+ }
+ // now that we have the right package, the class should be findable
+ return findObject(baseClassName, current);
+ } // if file exists
+ } // if import matches
+ } //foreach import
+ return NULL; // no match
+}
+
+
+/// keep track of the current file being parsed and reset the list of imports
+void JavaImport::parseFile(const QString& filename) {
+ m_currentFileName= filename;
+ m_imports.clear();
+ // default visibility is Impl, unless we are an interface, then it is
+ // public for member vars and methods
+ m_defaultCurrentAccess = Uml::Visibility::Implementation;
+ m_currentAccess = m_defaultCurrentAccess;
+ s_parseDepth++;
+ // in the case of self referencing types, we can avoid parsing the
+ // file twice by adding it to the list
+ s_filesAlreadyParsed.append(filename);
+ NativeImportBase::parseFile(filename);
+ s_parseDepth--;
+ if ( s_parseDepth <= 0 ) {
+ // if the user decides to clear things out and reparse, we need
+ // to honor the request, so reset things for next time.
+ s_filesAlreadyParsed.clear();
+ s_parseDepth = 0;
+ }
+}
+
+
+
+
+bool JavaImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ const QString& keyword = m_source[m_srcIndex];
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword == "package") {
+ m_currentPackage = advance();
+ const QString& qualifiedName = m_currentPackage;
+ QStringList names = QStringList::split(".", qualifiedName);
+ for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) {
+ QString name = (*it);
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ }
+ if (advance() != ";") {
+ kError() << "importJava: unexpected: " << m_source[m_srcIndex] << endl;
+ skipStmt();
+ }
+ return true;
+ }
+ if (keyword == "class" || keyword == "interface") {
+ const QString& name = advance();
+ const Uml::Object_Type t = (keyword == "class" ? Uml::ot_Class : Uml::ot_Interface);
+ UMLObject *ns = Import_Utils::createUMLObject(t, name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_klass->setAbstract(m_isAbstract);
+ m_klass->setStatic(m_isStatic);
+ m_klass->setVisibility(m_currentAccess);
+ // The UMLObject found by createUMLObject might originally have been created as a
+ // placeholder with a type of class but if is really an interface, then we need to
+ // change it.
+ Uml::Object_Type ot = (keyword == "interface" ? Uml::ot_Interface : Uml::ot_Class);
+ m_klass->setBaseType(ot);
+ m_isAbstract = m_isStatic = false;
+ // if no modifier is specified in an interface, then it means public
+ if ( m_klass->isInterface() ) {
+ m_defaultCurrentAccess = Uml::Visibility::Public;
+ }
+ if (advance() == ";") // forward declaration
+ return true;
+ if (m_source[m_srcIndex] == "<") {
+ // template args - preliminary, rudimentary implementation
+ // @todo implement all template arg syntax
+ uint start = m_srcIndex;
+ if (! skipToClosing('<')) {
+ kError() << "importJava(" << name << "): template syntax error" << endl;
+ return false;
+ }
+ while (1) {
+ const QString arg = m_source[++start];
+ if (! arg.contains( QRegExp("^[A-Za-z_]") )) {
+ kDebug() << "importJava(" << name << "): cannot handle template syntax ("
+ << arg << ")" << endl;
+ break;
+ }
+ /* UMLTemplate *tmpl = */ m_klass->addTemplate(arg);
+ const QString next = m_source[++start];
+ if (next == ">")
+ break;
+ if (next != ",") {
+ kDebug() << "importJava(" << name << "): can't handle template syntax ("
+ << next << ")" << endl;
+ break;
+ }
+ }
+ advance(); // skip over ">"
+ }
+ if (m_source[m_srcIndex] == "extends") {
+ const QString& baseName = advance();
+ // try to resolve the class we are extending, or if impossible
+ // create a placeholder
+ UMLObject *parent = resolveClass( baseName );
+ if ( parent ) {
+ Import_Utils::createGeneralization(m_klass, static_cast<UMLClassifier*>(parent));
+ } else {
+ kDebug() << "importJava parentClass " << baseName
+ << " is not resolveable. Creating placeholder" << endl;
+ Import_Utils::createGeneralization(m_klass, baseName);
+ }
+ advance();
+ }
+ if (m_source[m_srcIndex] == "implements") {
+ while (m_srcIndex < srcLength - 1 && advance() != "{") {
+ const QString& baseName = m_source[m_srcIndex];
+ // try to resolve the interface we are implementing, if this fails
+ // create a placeholder
+ UMLObject *interface = resolveClass( baseName );
+ if ( interface ) {
+ Import_Utils::createGeneralization(m_klass, static_cast<UMLClassifier*>(interface));
+ } else {
+ kDebug() << "importJava implementing interface "<< baseName
+ <<" is not resolvable. Creating placeholder" <<endl;
+ Import_Utils::createGeneralization(m_klass, baseName);
+ }
+ if (advance() != ",")
+ break;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ kError() << "importJava: ignoring excess chars at " << name
+ << " (" << m_source[m_srcIndex] << ")" << endl;
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "enum") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ skipStmt("{");
+ while (m_srcIndex < srcLength - 1 && advance() != "}") {
+ Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+ QString next = advance();
+ if (next == "{" || next == "(") {
+ if (! skipToClosing(next[0]))
+ return false;
+ next = advance();
+ }
+ if (next != ",") {
+ if (next == ";") {
+ // @todo handle methods in enum
+ // For now, we cheat (skip them)
+ m_source[m_srcIndex] = "{";
+ if (! skipToClosing('{'))
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+ if (keyword == "static") {
+ m_isStatic = true;
+ return true;
+ }
+ // if we detected static previously and keyword is { then this is a static block
+ if (m_isStatic && keyword == "{") {
+ // reset static flag and jump to end of static block
+ m_isStatic = false;
+ return skipToClosing('{');
+ }
+ if (keyword == "abstract") {
+ m_isAbstract = true;
+ return true;
+ }
+ if (keyword == "public") {
+ m_currentAccess = Uml::Visibility::Public;
+ return true;
+ }
+ if (keyword == "protected") {
+ m_currentAccess = Uml::Visibility::Protected;
+ return true;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "final" ||
+ keyword == "native" ||
+ keyword == "synchronized" ||
+ keyword == "transient" ||
+ keyword == "volatile") {
+ //@todo anything to do here?
+ return true;
+ }
+ if (keyword == "import") {
+ // keep track of imports so we can resolve classes we are dependent on
+ QString import = advance();
+ if ( import.endsWith(".") ) {
+ //this most likely an import that ends with a *
+ //
+ import = import + advance();
+ }
+ m_imports.append( import );
+
+ // move past ;
+ skipStmt();
+ return true;
+ }
+ if (keyword == "@") { // annotation
+ advance();
+ if (m_source[m_srcIndex + 1] == "(") {
+ advance();
+ skipToClosing('(');
+ }
+ return true;
+ }
+ if (keyword == "}") {
+ if (m_scopeIndex)
+ m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+ else
+ kError() << "importJava: too many }" << endl;
+ return true;
+ }
+ // At this point, we expect `keyword' to be a type name
+ // (of a member of class or interface, or return type
+ // of an operation.) Up next is the name of the attribute
+ // or operation.
+ if (! keyword.contains( QRegExp("^\\w") )) {
+ kError() << "importJava: ignoring " << keyword << endl;
+ return false;
+ }
+ QString typeName = m_source[m_srcIndex];
+ typeName = joinTypename(typeName);
+ // At this point we need a class.
+ if (m_klass == NULL) {
+ kError() << "importJava: no class set for " << typeName << endl;
+ return false;
+ }
+ QString name = advance();
+ QString nextToken;
+ if (typeName == m_klass->getName() && name == "(") {
+ // Constructor.
+ nextToken = name;
+ name = typeName;
+ typeName = QString();
+ } else {
+ nextToken = advance();
+ }
+ if (name.contains( QRegExp("\\W") )) {
+ kError() << "importJava: expecting name in " << name << endl;
+ return false;
+ }
+ if (nextToken == "(") {
+ // operation
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ m_srcIndex++;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ QString typeName = m_source[m_srcIndex];
+ if ( typeName == "final" || typeName.startsWith( "//") ) {
+ // ignore the "final" keyword and any comments in method args
+ typeName = advance();
+ }
+ typeName = joinTypename(typeName);
+ QString parName = advance();
+ // the Class might not be resolved yet so resolve it if necessary
+ UMLObject *obj = resolveClass(typeName);
+ if (obj) {
+ // by prepending the package, unwanted placeholder types will not get created
+ typeName = obj->getFullyQualifiedName(".");
+ }
+ /* UMLAttribute *att = */ Import_Utils::addMethodParameter(op, typeName, parName);
+ if (advance() != ",")
+ break;
+ m_srcIndex++;
+ }
+ // before adding the method, try resolving the return type
+ UMLObject *obj = resolveClass(typeName);
+ if (obj) {
+ // using the fully qualified name means that a placeholder type will not be created.
+ typeName = obj->getFullyQualifiedName(".");
+ }
+ Import_Utils::insertMethod(m_klass, op, m_currentAccess, typeName,
+ m_isStatic, m_isAbstract, false /*isFriend*/,
+ false /*isConstructor*/, m_comment);
+ m_isAbstract = m_isStatic = false;
+ // reset the default visibility
+ m_currentAccess = m_defaultCurrentAccess;
+ // At this point we do not know whether the method has a body or not.
+ do {
+ nextToken = advance();
+ } while (nextToken != "{" && nextToken != ";");
+ if (nextToken == ";") {
+ // No body (interface or abstract)
+ return true;
+ } else {
+ return skipToClosing('{');
+ }
+ }
+ // At this point we know it's some kind of attribute declaration.
+ while (1) {
+ while (nextToken != "," && nextToken != ";") {
+ if (nextToken == "=") {
+ if ((nextToken = advance()) == "new") {
+ advance();
+ if ((nextToken = advance()) == "(") {
+ skipToClosing('(');
+ if ((nextToken = advance()) == "{") {
+ skipToClosing('{');
+ } else {
+ skipStmt();
+ break;
+ }
+ } else {
+ skipStmt();
+ break;
+ }
+ } else {
+ skipStmt();
+ break;
+ }
+ } else {
+ name += nextToken; // add possible array dimensions to `name'
+ }
+ nextToken = advance();
+ }
+ // try to resolve the class type, or create a placeholder if that fails
+ UMLObject *type = resolveClass( typeName );
+ UMLObject *o;
+ if (type) {
+ o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ static_cast<UMLClassifier*>(type), m_comment, m_isStatic);
+ } else {
+ o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ typeName, m_comment, m_isStatic);
+ }
+ // UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ if (nextToken != ",") {
+ // reset the modifiers
+ m_isStatic = m_isAbstract = false;
+ break;
+ }
+ name = advance();
+ nextToken = advance();
+ }
+ // reset visibility to default
+ m_currentAccess = m_defaultCurrentAccess;
+ if (m_source[m_srcIndex] != ";") {
+ kError() << "importJava: ignoring trailing items at " << name << endl;
+ skipStmt();
+ }
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/codeimport/javaimport.h b/umbrello/umbrello/codeimport/javaimport.h
new file mode 100644
index 00000000..30fa2395
--- /dev/null
+++ b/umbrello/umbrello/codeimport/javaimport.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef JAVAIMPORT_H
+#define JAVAIMPORT_H
+
+#include "nativeimportbase.h"
+#include "../umlobject.h"
+
+/**
+ * Java code import
+ * @author Oliver Kellogg
+ * @author JP Fournier
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class JavaImport : public NativeImportBase {
+public:
+ JavaImport();
+ virtual ~JavaImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+ /**
+ * Keep track of the filename currently being parsed
+ */
+ void parseFile(const QString& filename);
+
+ /**
+ * Try to resolve the specified class the current class depends on
+ */
+ UMLObject* resolveClass (QString className);
+
+ /**
+ * spawn off an import of the specified file
+ */
+ void spawnImport(QString file);
+
+ /**
+ * figure out if the type is really an array or template of the given typeName
+ */
+ QString joinTypename(QString typeName);
+
+ /**
+ * true if the member var or method is declared static
+ */
+ bool m_isStatic;
+
+ /**
+ * The current filename being parsed
+ */
+ QString m_currentFileName;
+
+ /**
+ * the current package of the file being parsed
+ */
+ QString m_currentPackage;
+
+ /**
+ * the imports included in the current file
+ */
+ QStringList m_imports;
+
+ /**
+ * Keep track of the files we have already parsed so we don't
+ * reparse the same ones over and over again.
+ */
+ static QStringList s_filesAlreadyParsed;
+
+ /**
+ * Keep track of the parses so that the filesAlreadyParsed
+ * can be reset when we're done.
+ */
+ static int s_parseDepth;
+
+ /**
+ * The current visibility for when the visibility is absent
+ */
+ Uml::Visibility m_defaultCurrentAccess;
+
+
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am b/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am
new file mode 100644
index 00000000..b8325478
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = $(all_includes)
+
+noinst_LTLIBRARIES = libkdevcppparser.la
+libkdevcppparser_la_SOURCES = ast.cpp driver.cpp errors.cpp lexer.cpp lookup.cpp parser.cpp tree_parser.cpp urlutil.cpp ast_utils.cpp cpptree2uml.cpp
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/README b/umbrello/umbrello/codeimport/kdevcppparser/README
new file mode 100644
index 00000000..3ed39eba
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/README
@@ -0,0 +1,56 @@
+This directory contains the C++ parser from Kdevelop-3.0.
+
+Following files are copies from the directory kdevelop/lib/cppparser:
+ ast.{h,cpp} driver.{h,cpp} errors.{h,cpp} keywords.lut.h lexer.{h,cpp}
+ lookup.{h,cpp} parser.{h,cpp} tree_parser.{h,cpp}
+
+Following files are copies from the directory kdevelop/languages/cpp:
+ ast_utils.{h,cpp}
+
+Following files are copies from the directory kdevelop/lib/util:
+ urlutil.{h,cpp}
+
+The source files cpptree2uml.{h,cpp} are based on kdevelop/languages/cpp/
+store_walker.{h,cpp}. The class CppTree2Uml inherits from class TreeParser
+and overrides certain methods from that class.
+
+CppTree2Uml visits the nodes of the abstract syntax tree constructed by the
+CppParser, and constructs UML objects on the way.
+
+The import_utils.h (in the parent directory) is the interface between the
+CppTree2Uml and Umbrello.
+import_utils implements the construction of the UML objects. CppTree2Uml calls
+the create/insert methods in the import_utils while traversing the syntax
+tree.
+
+The one and only method that Umbrello uses for accessing the C++ parser,
+and any other parser for that matter, is ClassImport::importFiles().
+The class CppImport (in the parent directory) implements that operation.
+Thus we have these classes:
+
+ +-------------------+
+ | <<interface>> |
+ | ClassImport |
+ +===================+
+Umbrello ------>| importFiles() = 0 |
+ +-------------------+
+ A
+ | <<realize>>
+ |
+ +-------------------+ +-------------------+
+ | CppImport | | CppTree2Uml |
+ +===================+ <<invoke>> +===================+
+ | importFiles() |-------------->| |
+ +-------------------+ | |
+ +-------------------+
+ |
+ +-------------------+ |
+ | <<utility>> | |
+ | Import_Utils | |
+ +===================+ |
+ | createUMLObject() | <<invoke>> |
+ | insertMethod() |<-----------------------+
+ | insertAttribute() |
+ +-------------------+
+ |
+Umbrello <--------------+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp b/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp
new file mode 100644
index 00000000..6baca685
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast.cpp
@@ -0,0 +1,1183 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "ast.h"
+#include <qstringlist.h>
+#include <kdebug.h>
+
+QString nodeTypeToString( int type )
+{
+ switch( type )
+ {
+ case NodeType_Generic:
+ return "Generic";
+ case NodeType_TemplateArgumentList:
+ return "TemplateArgumentList";
+ case NodeType_ClassOrNamespaceName:
+ return "ClassOrNamespaceName";
+ case NodeType_Name:
+ return "Name";
+ case NodeType_Declaration:
+ return "Declaration";
+ case NodeType_TypeSpecifier:
+ return "TypeSpecifier";
+ case NodeType_BaseSpecifier:
+ return "BaseSpecifier";
+ case NodeType_BaseClause:
+ return "BaseClause";
+ case NodeType_ClassSpecifier:
+ return "ClassSpecifier";
+ case NodeType_Enumerator:
+ return "Enumerator";
+ case NodeType_EnumSpecifier:
+ return "EnumSpecifier";
+ case NodeType_ElaboratedTypeSpecifier:
+ return "ElaboratedTypeSpecifier";
+ case NodeType_LinkageBody:
+ return "LinkageBody";
+ case NodeType_LinkageSpecification:
+ return "LinkageSpecification";
+ case NodeType_Namespace:
+ return "Namespace";
+ case NodeType_NamespaceAlias:
+ return "NamespaceAlias";
+ case NodeType_Using:
+ return "Using";
+ case NodeType_UsingDirective:
+ return "UsingDirective";
+ case NodeType_InitDeclaratorList:
+ return "InitDeclaratorList";
+ case NodeType_Typedef:
+ return "Typedef";
+ case NodeType_Declarator:
+ return "Declarator";
+ case NodeType_InitDeclarator:
+ return "InitDeclarator";
+ case NodeType_TemplateDeclaration:
+ return "TemplateDeclaration";
+ case NodeType_SimpleDeclaration:
+ return "SimpleDeclaration";
+ case NodeType_Statement:
+ return "Statement";
+ case NodeType_IfStatement:
+ return "IfStatement";
+ case NodeType_WhileStatement:
+ return "WhileStatement";
+ case NodeType_DoStatement:
+ return "DoStatement";
+ case NodeType_ForStatement:
+ return "ForStatement";
+ case NodeType_SwitchStatement:
+ return "SwitchStatement";
+ case NodeType_DeclarationStatement:
+ return "DeclarationStatement";
+ case NodeType_StatementList:
+ return "StatementList";
+ case NodeType_TranslationUnit:
+ return "TranslationUnit";
+ case NodeType_FunctionDefinition:
+ return "FunctionDefinition";
+ case NodeType_ExpressionStatement:
+ return "ExpressionStatement";
+ case NodeType_ParameterDeclaration:
+ return "ParameterDeclaration";
+ case NodeType_ParameterDeclarationList:
+ return "ParameterDeclarationList";
+ case NodeType_ParameterDeclarationClause:
+ return "ParameterDeclarationClause";
+ case NodeType_Group:
+ return "Group";
+ case NodeType_AccessDeclaration:
+ return "AccessDeclaration";
+ case NodeType_TypeParameter:
+ return "TypeParameter";
+ case NodeType_TemplateParameter:
+ return "TemplateParameter";
+ case NodeType_TemplateParameterList:
+ return "TemplateParameterList";
+ case NodeType_Condition:
+ return "Condition";
+ case NodeType_Custom:
+ return "Custom";
+ }
+
+ return QString::null;
+}
+
+
+// ------------------------------------------------------------------------
+AST::AST()
+ : m_nodeType( NodeType_Generic ), m_parent( 0 ),
+ m_startLine( 0 ), m_startColumn( 0 ),
+ m_endLine( 0 ), m_endColumn( 0 )
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ m_children.setAutoDelete( false );
+#endif
+}
+
+AST::~AST()
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->removeChild( this );
+#endif
+}
+
+void AST::setStartPosition( int line, int col )
+{
+ m_startLine = line;
+ m_startColumn = col;
+}
+
+void AST::getStartPosition( int* line, int* col ) const
+{
+ if( line )
+ *line = m_startLine;
+
+ if( col )
+ * col = m_startColumn;
+}
+
+void AST::setEndPosition( int line, int col )
+{
+ m_endLine = line;
+ m_endColumn = col;
+}
+
+void AST::getEndPosition( int* line, int* col ) const
+{
+ if( line )
+ *line = m_endLine;
+
+ if( col )
+ * col = m_endColumn;
+}
+
+void AST::setParent( AST* parent )
+{
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->removeChild( this );
+#endif
+
+ m_parent = parent;
+
+#ifndef CPPPARSER_NO_CHILDREN
+ if( m_parent )
+ m_parent->appendChild( this );
+#endif
+}
+
+#ifndef CPPPARSER_NO_CHILDREN
+void AST::appendChild( AST* child )
+{
+ m_children.append( child );
+}
+
+void AST::removeChild( AST* child )
+{
+ m_children.remove( child );
+}
+#endif
+
+// ------------------------------------------------------------------------
+NameAST::NameAST()
+ : m_global( false )
+{
+ m_classOrNamespaceNameList.setAutoDelete( true );
+}
+
+void NameAST::setGlobal( bool b )
+{
+ m_global = b;
+}
+
+void NameAST::setUnqualifiedName( ClassOrNamespaceNameAST::Node& unqualifiedName )
+{
+ m_unqualifiedName = unqualifiedName;
+ if( m_unqualifiedName.get() ) m_unqualifiedName->setParent( this );
+}
+
+void NameAST::addClassOrNamespaceName( ClassOrNamespaceNameAST::Node& classOrNamespaceName )
+{
+ if( !classOrNamespaceName.get() )
+ return;
+
+ classOrNamespaceName->setParent( this );
+ m_classOrNamespaceNameList.append( classOrNamespaceName.release() );
+}
+
+QString NameAST::text() const
+{
+ if( !m_unqualifiedName.get() )
+ return QString::null;
+
+ QString str;
+
+ if( m_global )
+ str += "::";
+
+ QStringList l;
+ QPtrListIterator<ClassOrNamespaceNameAST> it( m_classOrNamespaceNameList );
+ while( it.current() ){
+ str += it.current()->text() + "::";
+ ++it;
+ }
+
+ if( m_unqualifiedName.get() )
+ str += m_unqualifiedName->text();
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+DeclarationAST::DeclarationAST()
+{
+}
+
+// ------------------------------------------------------------------------
+LinkageBodyAST::LinkageBodyAST()
+{
+ m_declarationList.setAutoDelete( true );
+}
+
+void LinkageBodyAST::addDeclaration( DeclarationAST::Node& ast )
+{
+ if( !ast.get() )
+ return;
+
+ ast->setParent( this );
+ m_declarationList.append( ast.release() );
+}
+
+// ------------------------------------------------------------------------
+LinkageSpecificationAST::LinkageSpecificationAST()
+{
+}
+
+void LinkageSpecificationAST::setExternType( AST::Node& externType )
+{
+ m_externType = externType;
+ if( m_externType.get() ) m_externType->setParent( this );
+}
+
+void LinkageSpecificationAST::setLinkageBody( LinkageBodyAST::Node& linkageBody )
+{
+ m_linkageBody = linkageBody;
+ if( m_linkageBody.get() ) m_linkageBody->setParent( this );
+}
+
+void LinkageSpecificationAST::setDeclaration( DeclarationAST::Node& decl )
+{
+ m_declaration = decl;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+TranslationUnitAST::TranslationUnitAST()
+{
+ //kdDebug(9007) << "++ TranslationUnitAST::TranslationUnitAST()" << endl;
+ m_declarationList.setAutoDelete( true );
+}
+
+void TranslationUnitAST::addDeclaration( DeclarationAST::Node& ast )
+{
+ if( !ast.get() )
+ return;
+
+ ast->setParent( this );
+ m_declarationList.append( ast.release() );
+}
+
+// ------------------------------------------------------------------------
+NamespaceAST::NamespaceAST()
+{
+}
+
+void NamespaceAST::setNamespaceName( AST::Node& namespaceName )
+{
+ m_namespaceName = namespaceName;
+ if( m_namespaceName.get() ) m_namespaceName->setParent( this );
+}
+
+void NamespaceAST::setLinkageBody( LinkageBodyAST::Node& linkageBody )
+{
+ m_linkageBody = linkageBody;
+ if( m_linkageBody.get() ) m_linkageBody->setParent( this );
+}
+
+
+// ------------------------------------------------------------------------
+NamespaceAliasAST::NamespaceAliasAST()
+{
+}
+
+void NamespaceAliasAST::setNamespaceName( AST::Node& namespaceName )
+{
+ m_namespaceName = namespaceName;
+ if( m_namespaceName.get() ) m_namespaceName->setParent( this );
+}
+
+void NamespaceAliasAST::setAliasName( NameAST::Node& name )
+{
+ m_aliasName = name;
+ if( m_aliasName.get() ) m_aliasName->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+UsingAST::UsingAST()
+{
+}
+
+void UsingAST::setTypeName( AST::Node& typeName )
+{
+ m_typeName = typeName;
+ if( m_typeName.get() ) m_typeName->setParent( this );
+}
+
+void UsingAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+UsingDirectiveAST::UsingDirectiveAST()
+{
+}
+
+void UsingDirectiveAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+TypedefAST::TypedefAST()
+{
+}
+
+void TypeSpecifierAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void TypedefAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void TypedefAST::setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList )
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if( m_initDeclaratorList.get() ) m_initDeclaratorList->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+TemplateArgumentListAST::TemplateArgumentListAST()
+{
+ m_argumentList.setAutoDelete( true );
+}
+
+void TemplateArgumentListAST::addArgument( AST::Node& arg )
+{
+ if( !arg.get() )
+ return;
+
+ arg->setParent( this );
+ m_argumentList.append( arg.release() );
+}
+
+QString TemplateArgumentListAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_argumentList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( ", " );
+}
+
+// ------------------------------------------------------------------------
+TemplateDeclarationAST::TemplateDeclarationAST()
+{
+}
+
+void TemplateDeclarationAST::setExported( AST::Node& exported )
+{
+ m_exported = exported;
+ if( m_exported.get() ) m_exported->setParent( this );
+}
+
+void TemplateDeclarationAST::setTemplateParameterList( TemplateParameterListAST::Node& templateParameterList )
+{
+ m_templateParameterList = templateParameterList;
+ if( m_templateParameterList.get() ) m_templateParameterList->setParent( this );
+}
+
+void TemplateDeclarationAST::setDeclaration( DeclarationAST::Node& declaration )
+{
+ m_declaration = declaration;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+ClassOrNamespaceNameAST::ClassOrNamespaceNameAST()
+{
+}
+
+void ClassOrNamespaceNameAST::setName( AST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void ClassOrNamespaceNameAST::setTemplateArgumentList( TemplateArgumentListAST::Node& templateArgumentList )
+{
+ m_templateArgumentList = templateArgumentList;
+ if( m_templateArgumentList.get() ) m_templateArgumentList->setParent( this );
+}
+
+QString ClassOrNamespaceNameAST::text() const
+{
+ if( !m_name.get() )
+ return QString::null;
+
+ QString str = m_name->text();
+ if( m_templateArgumentList.get() )
+ str += QString::fromLatin1("< ") + m_templateArgumentList->text() + QString::fromLatin1(" >");
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+TypeSpecifierAST::TypeSpecifierAST()
+{
+}
+
+void TypeSpecifierAST::setCvQualify( GroupAST::Node& cvQualify )
+{
+ m_cvQualify = cvQualify;
+ if( m_cvQualify.get() ) m_cvQualify->setParent( this );
+}
+
+void TypeSpecifierAST::setCv2Qualify( GroupAST::Node& cv2Qualify )
+{
+ m_cv2Qualify = cv2Qualify;
+ if( m_cv2Qualify.get() ) m_cv2Qualify->setParent( this );
+}
+
+QString TypeSpecifierAST::text() const
+{
+ QString str;
+
+ if( m_cvQualify.get() )
+ str += m_cvQualify->text() + ' ';
+
+ if( m_name.get() )
+ str += m_name->text();
+
+ if( m_cv2Qualify.get() )
+ str += QString(" ") + m_cv2Qualify->text();
+
+ return str;
+}
+
+// ------------------------------------------------------------------------
+ClassSpecifierAST::ClassSpecifierAST()
+{
+ m_declarationList.setAutoDelete( true );
+}
+
+void ClassSpecifierAST::setClassKey( AST::Node& classKey )
+{
+ m_classKey = classKey;
+ if( m_classKey.get() ) m_classKey->setParent( this );
+}
+
+void ClassSpecifierAST::addDeclaration( DeclarationAST::Node& declaration )
+{
+ if( !declaration.get() )
+ return;
+
+ declaration->setParent( this );
+ m_declarationList.append( declaration.release() );
+}
+
+void ClassSpecifierAST::setBaseClause( BaseClauseAST::Node& baseClause )
+{
+ m_baseClause = baseClause;
+ if( m_baseClause.get() ) m_baseClause->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+EnumSpecifierAST::EnumSpecifierAST()
+{
+ m_enumeratorList.setAutoDelete( true );
+}
+
+void EnumSpecifierAST::addEnumerator( EnumeratorAST::Node& enumerator )
+{
+ if( !enumerator.get() )
+ return;
+
+ enumerator->setParent( this );
+ m_enumeratorList.append( enumerator.release() );
+}
+
+
+// ------------------------------------------------------------------------
+ElaboratedTypeSpecifierAST::ElaboratedTypeSpecifierAST()
+{
+}
+
+void ElaboratedTypeSpecifierAST::setKind( AST::Node& kind )
+{
+ m_kind = kind;
+ if( m_kind.get() ) m_kind->setParent( this );
+}
+
+QString ElaboratedTypeSpecifierAST::text() const
+{
+ if( m_kind.get() )
+ return m_kind->text() + ' ' + TypeSpecifierAST::text();
+
+ return TypeSpecifierAST::text();
+}
+
+// ------------------------------------------------------------------------
+StatementAST::StatementAST()
+{
+}
+
+// ------------------------------------------------------------------------
+EnumeratorAST::EnumeratorAST()
+{
+}
+
+void EnumeratorAST::setId( AST::Node& id )
+{
+ m_id = id;
+ if( m_id.get() ) m_id->setParent( this );
+}
+
+void EnumeratorAST::setExpr( AST::Node& expr )
+{
+ m_expr = expr;
+ if( m_expr.get() ) m_expr->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+BaseClauseAST::BaseClauseAST()
+{
+ m_baseSpecifierList.setAutoDelete( true );
+}
+
+void BaseClauseAST::addBaseSpecifier( BaseSpecifierAST::Node& baseSpecifier )
+{
+ if( !baseSpecifier.get() )
+ return;
+
+ baseSpecifier->setParent( this );
+ m_baseSpecifierList.append( baseSpecifier.release() );
+}
+
+// ------------------------------------------------------------------------
+BaseSpecifierAST::BaseSpecifierAST()
+{
+}
+
+void BaseSpecifierAST::setIsVirtual( AST::Node& isVirtual )
+{
+ m_isVirtual = isVirtual;
+ if( m_isVirtual.get() ) m_isVirtual->setParent( this );
+}
+
+void BaseSpecifierAST::setAccess( AST::Node& access )
+{
+ m_access = access;
+ if( m_access.get() ) m_access->setParent( this );
+}
+
+void BaseSpecifierAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+// ------------------------------------------------------------------------
+SimpleDeclarationAST::SimpleDeclarationAST()
+{
+}
+
+void SimpleDeclarationAST::setFunctionSpecifier( GroupAST::Node& functionSpecifier )
+{
+ m_functionSpecifier = functionSpecifier;
+ if( m_functionSpecifier.get() ) m_functionSpecifier->setParent( this );
+}
+
+void SimpleDeclarationAST::setStorageSpecifier( GroupAST::Node& storageSpecifier )
+{
+ m_storageSpecifier = storageSpecifier;
+ if( m_storageSpecifier.get() ) m_storageSpecifier->setParent( this );
+}
+
+void SimpleDeclarationAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void SimpleDeclarationAST::setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList )
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if( m_initDeclaratorList.get() ) m_initDeclaratorList->setParent( this );
+}
+
+void SimpleDeclarationAST::setWinDeclSpec( GroupAST::Node& winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
+
+// ------------------------------------------------------------------------
+InitDeclaratorListAST::InitDeclaratorListAST()
+{
+ m_initDeclaratorList.setAutoDelete( true );
+}
+
+void InitDeclaratorListAST::addInitDeclarator( InitDeclaratorAST::Node& decl )
+{
+ if( !decl.get() )
+ return;
+
+ decl->setParent( this );
+ m_initDeclaratorList.append( decl.release() );
+}
+
+// ------------------------------------------------------------------------
+DeclaratorAST::DeclaratorAST()
+{
+ m_ptrOpList.setAutoDelete( true );
+ m_arrayDimensionList.setAutoDelete( true );
+}
+
+void DeclaratorAST::setSubDeclarator( DeclaratorAST::Node& subDeclarator )
+{
+ m_subDeclarator = subDeclarator;
+ if( m_subDeclarator.get() ) m_subDeclarator->setParent( this );
+}
+
+void DeclaratorAST::setDeclaratorId( NameAST::Node& declaratorId )
+{
+ m_declaratorId = declaratorId;
+ if( m_declaratorId.get() ) m_declaratorId->setParent( this );
+}
+
+void DeclaratorAST::setBitfieldInitialization( AST::Node& bitfieldInitialization )
+{
+ m_bitfieldInitialization = bitfieldInitialization;
+ if( m_bitfieldInitialization.get() ) m_bitfieldInitialization->setParent( this );
+}
+
+void DeclaratorAST::addArrayDimension( AST::Node& arrayDimension )
+{
+ if( !arrayDimension.get() )
+ return;
+
+ arrayDimension->setParent( this );
+ m_arrayDimensionList.append( arrayDimension.release() );
+}
+
+void DeclaratorAST::setParameterDeclarationClause( AUTO_PTR<class ParameterDeclarationClauseAST>& parameterDeclarationClause )
+{
+ m_parameterDeclarationClause = parameterDeclarationClause;
+ if( m_parameterDeclarationClause.get() ) m_parameterDeclarationClause->setParent( this );
+}
+
+void DeclaratorAST::setConstant( AST::Node& constant )
+{
+ m_constant = constant;
+ if( m_constant.get() ) m_constant->setParent( this );
+}
+
+void DeclaratorAST::setExceptionSpecification( GroupAST::Node& exceptionSpecification )
+{
+ m_exceptionSpecification = exceptionSpecification;
+ if( m_exceptionSpecification.get() ) m_exceptionSpecification->setParent( this );
+}
+
+void DeclaratorAST::addPtrOp( AST::Node& ptrOp )
+{
+ if( !ptrOp.get() )
+ return;
+
+ ptrOp->setParent( this );
+ m_ptrOpList.append( ptrOp.release() );
+}
+
+// --------------------------------------------------------------------------
+InitDeclaratorAST::InitDeclaratorAST()
+{
+}
+
+void InitDeclaratorAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void InitDeclaratorAST::setInitializer( AST::Node& initializer )
+{
+ m_initializer = initializer;
+ if( m_initializer.get() ) m_initializer->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+FunctionDefinitionAST::FunctionDefinitionAST()
+{
+}
+
+void FunctionDefinitionAST::setFunctionSpecifier( GroupAST::Node& functionSpecifier )
+{
+ m_functionSpecifier = functionSpecifier;
+ if( m_functionSpecifier.get() ) m_functionSpecifier->setParent( this );
+}
+
+void FunctionDefinitionAST::setStorageSpecifier( GroupAST::Node& storageSpecifier )
+{
+ m_storageSpecifier = storageSpecifier;
+ if( m_storageSpecifier.get() ) m_storageSpecifier->setParent( this );
+}
+
+void FunctionDefinitionAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void FunctionDefinitionAST::setInitDeclarator( InitDeclaratorAST::Node& initDeclarator )
+{
+ m_initDeclarator = initDeclarator;
+ if( m_initDeclarator.get() ) m_initDeclarator->setParent( this );
+}
+
+void FunctionDefinitionAST::setFunctionBody( StatementListAST::Node& functionBody )
+{
+ m_functionBody = functionBody;
+ if( m_functionBody.get() ) m_functionBody->setParent( this );
+}
+
+void FunctionDefinitionAST::setWinDeclSpec( GroupAST::Node& winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+StatementListAST::StatementListAST()
+{
+ m_statementList.setAutoDelete( true );
+}
+
+void StatementListAST::addStatement( StatementAST::Node& statement )
+{
+ if( !statement.get() )
+ return;
+
+ statement->setParent( this );
+ m_statementList.append( statement.release() );
+}
+
+// --------------------------------------------------------------------------
+IfStatementAST::IfStatementAST()
+{
+}
+
+void IfStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void IfStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+void IfStatementAST::setElseStatement( StatementAST::Node& elseStatement )
+{
+ m_elseStatement = elseStatement;
+ if( m_elseStatement.get() ) m_elseStatement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+WhileStatementAST::WhileStatementAST()
+{
+}
+
+void WhileStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void WhileStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+DoStatementAST::DoStatementAST()
+{
+}
+
+void DoStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void DoStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+ForStatementAST::ForStatementAST()
+{
+}
+
+void ForStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void ForStatementAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+void ForStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+void ForStatementAST::setInitStatement( StatementAST::Node& initStatement )
+{
+ m_initStatement = initStatement;
+ if( m_initStatement.get() ) m_initStatement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+SwitchStatementAST::SwitchStatementAST()
+{
+}
+
+void SwitchStatementAST::setCondition( ConditionAST::Node& condition )
+{
+ m_condition = condition;
+ if( m_condition.get() ) m_condition->setParent( this );
+}
+
+void SwitchStatementAST::setStatement( StatementAST::Node& statement )
+{
+ m_statement = statement;
+ if( m_statement.get() ) m_statement->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+DeclarationStatementAST::DeclarationStatementAST()
+{
+}
+
+void DeclarationStatementAST::setDeclaration( DeclarationAST::Node& declaration )
+{
+ m_declaration = declaration;
+ if( m_declaration.get() ) m_declaration->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+ExpressionStatementAST::ExpressionStatementAST()
+{
+}
+
+void ExpressionStatementAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationAST::ParameterDeclarationAST()
+{
+}
+
+void ParameterDeclarationAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void ParameterDeclarationAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void ParameterDeclarationAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+QString ParameterDeclarationAST::text() const
+{
+ QString str;
+ if( m_typeSpec.get() )
+ str += m_typeSpec->text() + ' ';
+
+ if( m_declarator.get() )
+ str += m_declarator->text();
+
+ if( m_expression.get() )
+ str += QString( " = " ) + m_expression->text();
+
+ return str;
+}
+
+// --------------------------------------------------------------------------
+ParameterDeclarationListAST::ParameterDeclarationListAST()
+{
+ m_parameterList.setAutoDelete( true );
+}
+
+void ParameterDeclarationListAST::addParameter( ParameterDeclarationAST::Node& parameter )
+{
+ if( !parameter.get() )
+ return;
+
+ parameter->setParent( this );
+ m_parameterList.append( parameter.release() );
+}
+
+QString ParameterDeclarationListAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<ParameterDeclarationAST> it( m_parameterList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( ", " );
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationClauseAST::ParameterDeclarationClauseAST()
+{
+}
+
+void ParameterDeclarationClauseAST::setParameterDeclarationList( ParameterDeclarationListAST::Node& parameterDeclarationList )
+{
+ m_parameterDeclarationList = parameterDeclarationList;
+ if( m_parameterDeclarationList.get() ) m_parameterDeclarationList->setParent( this );
+}
+
+void ParameterDeclarationClauseAST::setEllipsis( AST::Node& ellipsis )
+{
+ m_ellipsis = ellipsis;
+ if( m_ellipsis.get() ) m_ellipsis->setParent( this );
+}
+
+QString ParameterDeclarationClauseAST::text() const
+{
+ QString str;
+
+ if( m_parameterDeclarationList.get() )
+ str += m_parameterDeclarationList->text();
+
+ if( m_ellipsis.get() )
+ str += " ...";
+
+ return str;
+}
+
+
+// --------------------------------------------------------------------------
+GroupAST::GroupAST()
+{
+ m_nodeList.setAutoDelete( true );
+}
+
+void GroupAST::addNode( AST::Node& node )
+{
+ if( !node.get() )
+ return;
+
+ node->setParent( this );
+ m_nodeList.append( node.release() );
+}
+
+QString GroupAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_nodeList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( " " );
+}
+
+// --------------------------------------------------------------------------
+AccessDeclarationAST::AccessDeclarationAST()
+{
+ m_accessList.setAutoDelete( true );
+}
+
+void AccessDeclarationAST::addAccess( AST::Node& access )
+{
+ if( !access.get() )
+ return;
+
+ access->setParent( this );
+ m_accessList.append( access.release() );
+}
+
+QString AccessDeclarationAST::text() const
+{
+ QStringList l;
+
+ QPtrListIterator<AST> it( m_accessList );
+ while( it.current() ){
+ l.append( it.current()->text() );
+ ++it;
+ }
+
+ return l.join( " " );
+}
+
+// --------------------------------------------------------------------------
+TypeParameterAST::TypeParameterAST()
+{
+}
+
+void TypeParameterAST::setKind( AST::Node& kind )
+{
+ m_kind = kind;
+ if( m_kind.get() ) m_kind->setParent( this );
+}
+
+void TypeParameterAST::setTemplateParameterList( AUTO_PTR<class TemplateParameterListAST>& templateParameterList )
+{
+ m_templateParameterList = templateParameterList;
+ if( m_templateParameterList.get() ) m_templateParameterList->setParent( this );
+}
+
+void TypeParameterAST::setName( NameAST::Node& name )
+{
+ m_name = name;
+ if( m_name.get() ) m_name->setParent( this );
+}
+
+void TypeParameterAST::setTypeId( AST::Node& typeId )
+{
+ m_typeId = typeId;
+ if( m_typeId.get() ) m_typeId->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterAST::TemplateParameterAST()
+{
+}
+
+void TemplateParameterAST::setTypeParameter( TypeParameterAST::Node& typeParameter )
+{
+ m_typeParameter = typeParameter;
+ if( m_typeParameter.get() ) m_typeParameter->setParent( this );
+}
+
+void TemplateParameterAST::setTypeValueParameter( ParameterDeclarationAST::Node& typeValueParameter )
+{
+ m_typeValueParameter = typeValueParameter;
+ if( m_typeValueParameter.get() ) m_typeValueParameter->setParent( this );
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterListAST::TemplateParameterListAST()
+{
+ m_templateParameterList.setAutoDelete( true );
+}
+
+void TemplateParameterListAST::addTemplateParameter( TemplateParameterAST::Node& templateParameter )
+{
+ if( !templateParameter.get() )
+ return;
+
+ templateParameter->setParent( this );
+ m_templateParameterList.append( templateParameter.release() );
+}
+
+// --------------------------------------------------------------------------
+ConditionAST::ConditionAST()
+{
+}
+
+void ConditionAST::setTypeSpec( TypeSpecifierAST::Node& typeSpec )
+{
+ m_typeSpec = typeSpec;
+ if( m_typeSpec.get() ) m_typeSpec->setParent( this );
+}
+
+void ConditionAST::setDeclarator( DeclaratorAST::Node& declarator )
+{
+ m_declarator = declarator;
+ if( m_declarator.get() ) m_declarator->setParent( this );
+}
+
+void ConditionAST::setExpression( AST::Node& expression )
+{
+ m_expression = expression;
+ if( m_expression.get() ) m_expression->setParent( this );
+}
+
+void ClassSpecifierAST::setWinDeclSpec( GroupAST::Node & winDeclSpec )
+{
+ m_winDeclSpec = winDeclSpec;
+ if( m_winDeclSpec.get() ) m_winDeclSpec->setParent( this );
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast.h b/umbrello/umbrello/codeimport/kdevcppparser/ast.h
new file mode 100644
index 00000000..9b7b5aac
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast.h
@@ -0,0 +1,1449 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __ast_h
+#define __ast_h
+
+#include <memory>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#if defined( Q_OS_WIN32 ) || defined( Q_CC_SUN )
+
+#ifndef _THROW0
+# define _THROW0()
+#endif
+
+template <class _Tp> class AUTO_PTR {
+private:
+ _Tp* _M_ptr;
+
+public:
+ typedef _Tp element_type;
+
+ explicit AUTO_PTR(_Tp* __p = 0) _THROW0() : _M_ptr(__p) {}
+
+ template <class _Tp1> AUTO_PTR(AUTO_PTR<_Tp1>& __a) _THROW0()
+ : _M_ptr(__a.release()) {}
+
+ AUTO_PTR(AUTO_PTR& __a) _THROW0() : _M_ptr(__a.release()) {}
+
+
+
+ template <class _Tp1>
+ AUTO_PTR& operator=(AUTO_PTR<_Tp1>& __a) _THROW0() {
+ if (__a.get() != this->get()) {
+ delete _M_ptr;
+ _M_ptr = __a.release();
+ }
+ return *this;
+ }
+
+ AUTO_PTR& operator=(AUTO_PTR& __a) _THROW0() {
+ if (&__a != this) {
+ delete _M_ptr;
+ _M_ptr = __a.release();
+ }
+ return *this;
+ }
+
+ ~AUTO_PTR() _THROW0() { delete _M_ptr; }
+
+ _Tp& operator*() const _THROW0() {
+ return *_M_ptr;
+ }
+ _Tp* operator->() const _THROW0() {
+ return _M_ptr;
+ }
+ _Tp* get() const _THROW0() {
+ return _M_ptr;
+ }
+ _Tp* release() _THROW0() {
+ _Tp* __tmp = _M_ptr;
+ _M_ptr = 0;
+ return __tmp;
+ }
+ void reset(_Tp* __p = 0) _THROW0() {
+ delete _M_ptr;
+ _M_ptr = __p;
+ }
+
+ // According to the C++ standard, these conversions are required. Most
+ // present-day compilers, however, do not enforce that requirement---and,
+ // in fact, most present-day compilers do not support the language
+ // features that these conversions rely on.
+
+
+private:
+ template<class _Tp1> struct AUTO_PTR_ref {
+ _Tp1* _M_ptr;
+ AUTO_PTR_ref(_Tp1* __p) : _M_ptr(__p) {}
+ };
+
+public:
+ AUTO_PTR(AUTO_PTR_ref<_Tp> __ref) _THROW0()
+ : _M_ptr(__ref._M_ptr) {}
+ template <class _Tp1> operator AUTO_PTR_ref<_Tp1>() _THROW0()
+ { return AUTO_PTR_ref<_Tp>(this->release()); }
+ template <class _Tp1> operator AUTO_PTR<_Tp1>() _THROW0()
+ { return AUTO_PTR<_Tp1>(this->release()) }
+
+};
+
+#else
+#define AUTO_PTR std::auto_ptr
+#endif
+
+template <class T> typename T::Node CreateNode()
+{
+ typename T::Node node( new T );
+ node->setNodeType( T::Type );
+ return node;
+}
+
+template <class T> typename T::Node NullNode()
+{
+ typename T::Node node;
+ return node;
+}
+
+enum NodeType
+{
+ NodeType_Generic = 0,
+
+ NodeType_TemplateArgumentList = 1000,
+ NodeType_ClassOrNamespaceName,
+ NodeType_Name,
+ NodeType_Declaration,
+ NodeType_TypeSpecifier,
+ NodeType_BaseSpecifier,
+ NodeType_BaseClause,
+ NodeType_ClassSpecifier,
+ NodeType_Enumerator,
+ NodeType_EnumSpecifier,
+ NodeType_ElaboratedTypeSpecifier,
+ NodeType_LinkageBody,
+ NodeType_LinkageSpecification,
+ NodeType_Namespace,
+ NodeType_NamespaceAlias,
+ NodeType_Using,
+ NodeType_UsingDirective,
+ NodeType_InitDeclaratorList,
+ NodeType_Typedef,
+ NodeType_Declarator,
+ NodeType_InitDeclarator,
+ NodeType_TemplateDeclaration,
+ NodeType_SimpleDeclaration,
+ NodeType_Statement,
+ NodeType_StatementList,
+ NodeType_IfStatement,
+ NodeType_WhileStatement,
+ NodeType_DoStatement,
+ NodeType_ForStatement,
+ NodeType_SwitchStatement,
+ NodeType_DeclarationStatement,
+ NodeType_TranslationUnit,
+ NodeType_FunctionDefinition,
+ NodeType_ExpressionStatement,
+ NodeType_ParameterDeclaration,
+ NodeType_ParameterDeclarationList,
+ NodeType_ParameterDeclarationClause,
+ NodeType_Group,
+ NodeType_AccessDeclaration,
+ NodeType_TypeParameter,
+ NodeType_TemplateParameter,
+ NodeType_TemplateParameterList,
+ NodeType_Condition,
+
+ NodeType_Custom = 2000
+};
+
+QString nodeTypeToString( int type );
+
+
+#if defined(CPPPARSER_QUICK_ALLOCATOR)
+
+#include <quick_allocator.h>
+
+#define DECLARE_ALLOC(tp) \
+ void * operator new(std::size_t) \
+ { \
+ return quick_allocator< tp >::alloc(); \
+ } \
+ \
+ void operator delete(void * p) \
+ { \
+ quick_allocator< tp >::dealloc(p); \
+ }
+#else
+
+#define DECLARE_ALLOC(tp)
+
+#endif
+
+struct Slice
+{
+ QString source;
+ int position;
+ int length;
+
+ inline Slice()
+ : position(0), length(0) {}
+};
+
+class AST
+{
+public:
+ typedef AUTO_PTR<AST> Node;
+ enum { Type=NodeType_Generic };
+
+ DECLARE_ALLOC( AST )
+
+public:
+ AST();
+ virtual ~AST();
+
+ int nodeType() const { return m_nodeType; }
+ void setNodeType( int nodeType ) { m_nodeType = nodeType; }
+
+ AST* parent() { return m_parent; }
+ void setParent( AST* parent );
+
+ void setStartPosition( int line, int col );
+ void getStartPosition( int* line, int* col ) const;
+
+ void setEndPosition( int line, int col );
+ void getEndPosition( int* line, int* col ) const;
+
+#ifndef CPPPARSER_NO_CHILDREN
+ QPtrList<AST> children() { return m_children; }
+ void appendChild( AST* child );
+ void removeChild( AST* child );
+#endif
+
+ virtual inline QString text() const
+ { return m_slice.source.mid(m_slice.position, m_slice.length); }
+
+ QString comment() const
+ { return m_comment; }
+
+ inline void setSlice( const Slice& slice )
+ { m_slice = slice; }
+
+ inline void setSlice( const QString &text, int position, int length )
+ {
+ m_slice.source = text;
+ m_slice.position = position;
+ m_slice.length = length;
+ }
+
+ inline void setText(const QString &text)
+ { setSlice(text, 0, text.length()); }
+
+ void setComment( const QString &comment )
+ { m_comment = comment; }
+
+private:
+ int m_nodeType;
+ AST* m_parent;
+ int m_startLine, m_startColumn;
+ int m_endLine, m_endColumn;
+ Slice m_slice;
+#ifndef CPPPARSER_NO_CHILDREN
+ QPtrList<AST> m_children;
+#endif
+ QString m_comment;
+
+private:
+ AST( const AST& source );
+ void operator = ( const AST& source );
+};
+
+class GroupAST: public AST
+{
+public:
+ typedef AUTO_PTR<GroupAST> Node;
+ enum { Type = NodeType_Group };
+
+ DECLARE_ALLOC( GroupAST )
+
+public:
+ GroupAST();
+
+ QPtrList<AST> nodeList() { return m_nodeList; }
+ void addNode( AST::Node& node );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_nodeList;
+
+private:
+ GroupAST( const GroupAST& source );
+ void operator = ( const GroupAST& source );
+};
+
+
+class TemplateArgumentListAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateArgumentListAST> Node;
+ enum { Type = NodeType_TemplateArgumentList };
+
+ DECLARE_ALLOC( TemplateArgumentListAST )
+
+public:
+ TemplateArgumentListAST();
+
+ void addArgument( AST::Node& arg );
+ QPtrList<AST> argumentList() { return m_argumentList; }
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_argumentList;
+
+private:
+ TemplateArgumentListAST( const TemplateArgumentListAST& source );
+ void operator = ( const TemplateArgumentListAST& source );
+};
+
+class ClassOrNamespaceNameAST: public AST
+{
+public:
+ typedef AUTO_PTR<ClassOrNamespaceNameAST> Node;
+ enum { Type = NodeType_ClassOrNamespaceName };
+
+ DECLARE_ALLOC( ClassOrNamespaceNameAST )
+
+public:
+ ClassOrNamespaceNameAST();
+
+ AST* name() { return m_name.get(); }
+ void setName( AST::Node& name );
+
+ TemplateArgumentListAST* templateArgumentList() { return m_templateArgumentList.get(); }
+ void setTemplateArgumentList( TemplateArgumentListAST::Node& templateArgumentList );
+
+ virtual QString text() const;
+
+private:
+ AST::Node m_name;
+ TemplateArgumentListAST::Node m_templateArgumentList;
+
+private:
+ ClassOrNamespaceNameAST( const ClassOrNamespaceNameAST& source );
+ void operator = ( const ClassOrNamespaceNameAST& source );
+};
+
+class NameAST: public AST
+{
+public:
+ typedef AUTO_PTR<NameAST> Node;
+ enum { Type = NodeType_Name };
+
+ DECLARE_ALLOC( NameAST )
+
+public:
+ NameAST();
+
+ bool isGlobal() const { return m_global; }
+ void setGlobal( bool b );
+
+ void addClassOrNamespaceName( ClassOrNamespaceNameAST::Node& classOrNamespaceName );
+ QPtrList<ClassOrNamespaceNameAST> classOrNamespaceNameList() { return m_classOrNamespaceNameList; }
+
+ ClassOrNamespaceNameAST* unqualifiedName() { return m_unqualifiedName.get(); }
+ void setUnqualifiedName( ClassOrNamespaceNameAST::Node& unqualifiedName );
+
+ virtual QString text() const;
+
+private:
+ bool m_global;
+ ClassOrNamespaceNameAST::Node m_unqualifiedName;
+ QPtrList<ClassOrNamespaceNameAST> m_classOrNamespaceNameList;
+
+private:
+ NameAST( const NameAST& source );
+ void operator = ( const NameAST& source );
+};
+
+class TypeParameterAST: public AST
+{
+public:
+ typedef AUTO_PTR<TypeParameterAST> Node;
+ enum { Type = NodeType_TypeParameter };
+
+ DECLARE_ALLOC( TypeParameterAST )
+
+public:
+ TypeParameterAST();
+
+ AST* kind() { return m_kind.get(); }
+ void setKind( AST::Node& kind );
+
+ class TemplateParameterListAST* templateParameterList() { return m_templateParameterList.get(); }
+ void setTemplateParameterList( AUTO_PTR<class TemplateParameterListAST>& templateParameterList );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+ AST* typeId() { return m_typeId.get(); }
+ void setTypeId( AST::Node& typeId );
+
+private:
+ AST::Node m_kind;
+ AUTO_PTR<class TemplateParameterListAST> m_templateParameterList;
+ NameAST::Node m_name;
+ AST::Node m_typeId;
+
+private:
+ TypeParameterAST( const TypeParameterAST& source );
+ void operator = ( const TypeParameterAST& source );
+};
+
+class DeclarationAST: public AST
+{
+public:
+ typedef AUTO_PTR<DeclarationAST> Node;
+ enum { Type = NodeType_Declaration };
+
+ DECLARE_ALLOC( DeclarationAST )
+
+public:
+ DeclarationAST();
+
+private:
+ DeclarationAST( const DeclarationAST& source );
+ void operator = ( const DeclarationAST& source );
+};
+
+class AccessDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<AccessDeclarationAST> Node;
+ enum { Type = NodeType_AccessDeclaration };
+
+ DECLARE_ALLOC( AccessDeclarationAST )
+
+public:
+ AccessDeclarationAST();
+
+ QPtrList<AST> accessList() { return m_accessList; }
+ void addAccess( AST::Node& access );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<AST> m_accessList;
+
+private:
+ AccessDeclarationAST( const AccessDeclarationAST& source );
+ void operator = ( const AccessDeclarationAST& source );
+};
+
+class TypeSpecifierAST: public AST
+{
+public:
+ typedef AUTO_PTR<TypeSpecifierAST> Node;
+ enum { Type = NodeType_TypeSpecifier };
+
+ DECLARE_ALLOC( TypeSpecifierAST )
+
+public:
+ TypeSpecifierAST();
+
+ virtual NameAST* name() { return m_name.get(); }
+ virtual void setName( NameAST::Node& name );
+
+ GroupAST* cvQualify() { return m_cvQualify.get(); }
+ void setCvQualify( GroupAST::Node& cvQualify );
+
+ GroupAST* cv2Qualify() { return m_cv2Qualify.get(); }
+ void setCv2Qualify( GroupAST::Node& cv2Qualify );
+
+ virtual QString text() const;
+
+private:
+ NameAST::Node m_name;
+ GroupAST::Node m_cvQualify;
+ GroupAST::Node m_cv2Qualify;
+
+private:
+ TypeSpecifierAST( const TypeSpecifierAST& source );
+ void operator = ( const TypeSpecifierAST& source );
+};
+
+class BaseSpecifierAST: public AST
+{
+public:
+ typedef AUTO_PTR<BaseSpecifierAST> Node;
+ enum { Type = NodeType_BaseSpecifier };
+
+ DECLARE_ALLOC( BaseSpecifierAST )
+
+public:
+ BaseSpecifierAST();
+
+ AST* isVirtual() { return m_isVirtual.get(); }
+ void setIsVirtual( AST::Node& isVirtual );
+
+ AST* access() { return m_access.get(); }
+ void setAccess( AST::Node& access );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ AST::Node m_isVirtual;
+ AST::Node m_access;
+ NameAST::Node m_name;
+
+private:
+ BaseSpecifierAST( const BaseSpecifierAST& source );
+ void operator = ( const BaseSpecifierAST& source );
+};
+
+class BaseClauseAST: public AST
+{
+public:
+ typedef AUTO_PTR<BaseClauseAST> Node;
+ enum { Type = NodeType_BaseClause };
+
+ DECLARE_ALLOC( BaseClauseAST )
+
+public:
+ BaseClauseAST();
+
+ void addBaseSpecifier( BaseSpecifierAST::Node& baseSpecifier );
+ QPtrList<BaseSpecifierAST> baseSpecifierList() { return m_baseSpecifierList; }
+
+private:
+ QPtrList<BaseSpecifierAST> m_baseSpecifierList;
+
+private:
+ BaseClauseAST( const BaseClauseAST& source );
+ void operator = ( const BaseClauseAST& source );
+};
+
+class ClassSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<ClassSpecifierAST> Node;
+ enum { Type = NodeType_ClassSpecifier };
+
+ DECLARE_ALLOC( ClassSpecifierAST )
+
+public:
+ ClassSpecifierAST();
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+ AST* classKey() { return m_classKey.get(); }
+ void setClassKey( AST::Node& classKey );
+
+ BaseClauseAST* baseClause() { return m_baseClause.get(); }
+ void setBaseClause( BaseClauseAST::Node& baseClause );
+
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+ void addDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ GroupAST::Node m_winDeclSpec;
+ AST::Node m_classKey;
+ BaseClauseAST::Node m_baseClause;
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ ClassSpecifierAST( const ClassSpecifierAST& source );
+ void operator = ( const ClassSpecifierAST& source );
+};
+
+class EnumeratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<EnumeratorAST> Node;
+ enum { Type = NodeType_Enumerator };
+
+ DECLARE_ALLOC( EnumeratorAST )
+
+public:
+ EnumeratorAST();
+
+ AST* id() { return m_id.get(); }
+ void setId( AST::Node& id );
+
+ AST* expr() { return m_expr.get(); }
+ void setExpr( AST::Node& expr );
+
+private:
+ AST::Node m_id;
+ AST::Node m_expr;
+
+private:
+ EnumeratorAST( const EnumeratorAST& source );
+ void operator = ( const EnumeratorAST& source );
+};
+
+class EnumSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<EnumSpecifierAST> Node;
+ enum { Type = NodeType_EnumSpecifier };
+
+ DECLARE_ALLOC( EnumSpecifierAST )
+
+public:
+ EnumSpecifierAST();
+
+ void addEnumerator( EnumeratorAST::Node& enumerator );
+ QPtrList<EnumeratorAST> enumeratorList() { return m_enumeratorList; }
+
+private:
+ QPtrList<EnumeratorAST> m_enumeratorList;
+
+private:
+ EnumSpecifierAST( const EnumSpecifierAST& source );
+ void operator = ( const EnumSpecifierAST& source );
+};
+
+class ElaboratedTypeSpecifierAST: public TypeSpecifierAST
+{
+public:
+ typedef AUTO_PTR<ElaboratedTypeSpecifierAST> Node;
+ enum { Type = NodeType_ElaboratedTypeSpecifier };
+
+ DECLARE_ALLOC( ElaboratedTypeSpecifierAST )
+
+public:
+ ElaboratedTypeSpecifierAST();
+
+ AST* kind() { return m_kind.get(); }
+ void setKind( AST::Node& kind );
+
+ virtual QString text() const;
+
+private:
+ AST::Node m_kind;
+
+private:
+ ElaboratedTypeSpecifierAST( const ElaboratedTypeSpecifierAST& source );
+ void operator = ( const ElaboratedTypeSpecifierAST& source );
+};
+
+
+class LinkageBodyAST: public AST
+{
+public:
+ typedef AUTO_PTR<LinkageBodyAST> Node;
+ enum { Type = NodeType_LinkageBody };
+
+ DECLARE_ALLOC( LinkageBodyAST )
+
+public:
+ LinkageBodyAST();
+
+ void addDeclaration( DeclarationAST::Node& ast );
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+
+private:
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ LinkageBodyAST( const LinkageBodyAST& source );
+ void operator = ( const LinkageBodyAST& source );
+};
+
+class LinkageSpecificationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<LinkageSpecificationAST> Node;
+ enum { Type = NodeType_LinkageSpecification };
+
+ DECLARE_ALLOC( LinkageSpecificationAST )
+
+public:
+ LinkageSpecificationAST();
+
+ AST* externType() { return m_externType.get(); }
+ void setExternType( AST::Node& externType );
+
+ LinkageBodyAST* linkageBody() { return m_linkageBody.get(); }
+ void setLinkageBody( LinkageBodyAST::Node& linkageBody );
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& decl );
+
+private:
+ AST::Node m_externType;
+ LinkageBodyAST::Node m_linkageBody;
+ DeclarationAST::Node m_declaration;
+
+private:
+ LinkageSpecificationAST( const LinkageSpecificationAST& source );
+ void operator = ( const LinkageSpecificationAST& source );
+};
+
+class NamespaceAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<NamespaceAST> Node;
+ enum { Type = NodeType_Namespace };
+
+ DECLARE_ALLOC( NamespaceAST )
+
+public:
+ NamespaceAST();
+
+ AST* namespaceName() { return m_namespaceName.get(); }
+ void setNamespaceName( AST::Node& namespaceName );
+
+ LinkageBodyAST* linkageBody() { return m_linkageBody.get(); }
+ void setLinkageBody( LinkageBodyAST::Node& linkageBody );
+
+private:
+ AST::Node m_namespaceName;
+ LinkageBodyAST::Node m_linkageBody;
+
+private:
+ NamespaceAST( const NamespaceAST& source );
+ void operator = ( const NamespaceAST& source );
+};
+
+class NamespaceAliasAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<NamespaceAliasAST> Node;
+ enum { Type = NodeType_NamespaceAlias };
+
+ DECLARE_ALLOC( NamespaceAliasAST )
+
+public:
+ NamespaceAliasAST();
+
+ AST* namespaceName() { return m_namespaceName.get(); }
+ void setNamespaceName( AST::Node& name );
+
+ NameAST* aliasName() { return m_aliasName.get(); }
+ void setAliasName( NameAST::Node& name );
+
+private:
+ AST::Node m_namespaceName;
+ NameAST::Node m_aliasName;
+
+private:
+ NamespaceAliasAST( const NamespaceAliasAST& source );
+ void operator = ( const NamespaceAliasAST& source );
+};
+
+class UsingAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<UsingAST> Node;
+ enum { Type = NodeType_Using };
+
+ DECLARE_ALLOC( UsingAST )
+
+public:
+ UsingAST();
+
+ AST* typeName() { return m_typeName.get(); }
+ void setTypeName( AST::Node& typeName );
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ AST::Node m_typeName;
+ NameAST::Node m_name;
+
+private:
+ UsingAST( const UsingAST& source );
+ void operator = ( const UsingAST& source );
+};
+
+class UsingDirectiveAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<UsingDirectiveAST> Node;
+ enum { Type = NodeType_UsingDirective };
+
+ DECLARE_ALLOC( UsingDirectiveAST )
+
+public:
+ UsingDirectiveAST();
+
+ NameAST* name() { return m_name.get(); }
+ void setName( NameAST::Node& name );
+
+private:
+ NameAST::Node m_name;
+
+private:
+ UsingDirectiveAST( const UsingDirectiveAST& source );
+ void operator = ( const UsingDirectiveAST& source );
+};
+
+class DeclaratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<DeclaratorAST> Node;
+ enum { Type = NodeType_Declarator };
+
+ DECLARE_ALLOC( DeclaratorAST )
+
+public:
+ DeclaratorAST();
+
+ QPtrList<AST> ptrOpList() { return m_ptrOpList; }
+ void addPtrOp( AST::Node& ptrOp );
+
+ DeclaratorAST* subDeclarator() { return m_subDeclarator.get(); }
+ void setSubDeclarator( Node& subDeclarator );
+
+ NameAST* declaratorId() { return m_declaratorId.get(); }
+ void setDeclaratorId( NameAST::Node& declaratorId );
+
+ AST* bitfieldInitialization() { return m_bitfieldInitialization.get(); }
+ void setBitfieldInitialization( AST::Node& bitfieldInitialization );
+
+ QPtrList<AST> arrayDimensionList() { return m_arrayDimensionList; }
+ void addArrayDimension( AST::Node& arrayDimension );
+
+ class ParameterDeclarationClauseAST* parameterDeclarationClause() { return m_parameterDeclarationClause.get(); }
+ void setParameterDeclarationClause( AUTO_PTR<class ParameterDeclarationClauseAST>& parameterDeclarationClause );
+
+ // ### replace 'constant' with cvQualify
+ AST* constant() { return m_constant.get(); }
+ void setConstant( AST::Node& constant );
+
+ GroupAST* exceptionSpecification() { return m_exceptionSpecification.get(); }
+ void setExceptionSpecification( GroupAST::Node& exceptionSpecification );
+
+private:
+ QPtrList<AST> m_ptrOpList;
+ Node m_subDeclarator;
+ NameAST::Node m_declaratorId;
+ AST::Node m_bitfieldInitialization;
+ QPtrList<AST> m_arrayDimensionList;
+ AUTO_PTR<class ParameterDeclarationClauseAST> m_parameterDeclarationClause;
+ AST::Node m_constant;
+ GroupAST::Node m_exceptionSpecification;
+
+private:
+ DeclaratorAST( const DeclaratorAST& source );
+ void operator = ( const DeclaratorAST& source );
+};
+
+class ParameterDeclarationAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationAST> Node;
+ enum { Type = NodeType_ParameterDeclaration };
+
+ DECLARE_ALLOC( ParameterDeclarationAST )
+
+public:
+ ParameterDeclarationAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+ virtual QString text() const;
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_expression;
+
+private:
+ ParameterDeclarationAST( const ParameterDeclarationAST& source );
+ void operator = ( const ParameterDeclarationAST& source );
+};
+
+class ParameterDeclarationListAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationListAST> Node;
+ enum { Type = NodeType_ParameterDeclarationList };
+
+ DECLARE_ALLOC( ParameterDeclarationListAST )
+
+public:
+ ParameterDeclarationListAST();
+
+ QPtrList<ParameterDeclarationAST> parameterList() { return m_parameterList; }
+ void addParameter( ParameterDeclarationAST::Node& parameter );
+
+ virtual QString text() const;
+
+private:
+ QPtrList<ParameterDeclarationAST> m_parameterList;
+
+private:
+ ParameterDeclarationListAST( const ParameterDeclarationListAST& source );
+ void operator = ( const ParameterDeclarationListAST& source );
+};
+
+class ParameterDeclarationClauseAST: public AST
+{
+public:
+ typedef AUTO_PTR<ParameterDeclarationClauseAST> Node;
+ enum { Type = NodeType_ParameterDeclarationClause };
+
+ DECLARE_ALLOC( ParameterDeclarationClauseAST )
+
+public:
+ ParameterDeclarationClauseAST();
+
+ ParameterDeclarationListAST* parameterDeclarationList() { return m_parameterDeclarationList.get(); }
+ void setParameterDeclarationList( ParameterDeclarationListAST::Node& parameterDeclarationList );
+
+ AST* ellipsis() { return m_ellipsis.get(); }
+ void setEllipsis( AST::Node& ellipsis );
+
+ virtual QString text() const;
+
+private:
+ ParameterDeclarationListAST::Node m_parameterDeclarationList;
+ AST::Node m_ellipsis;
+
+private:
+ ParameterDeclarationClauseAST( const ParameterDeclarationClauseAST& source );
+ void operator = ( const ParameterDeclarationClauseAST& source );
+};
+
+
+class InitDeclaratorAST: public AST
+{
+public:
+ typedef AUTO_PTR<InitDeclaratorAST> Node;
+ enum { Type = NodeType_InitDeclarator };
+
+ DECLARE_ALLOC( InitDeclaratorAST )
+
+public:
+ InitDeclaratorAST();
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* initializer() { return m_initializer.get(); }
+ void setInitializer( AST::Node& initializer );
+
+private:
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_initializer;
+
+private:
+ InitDeclaratorAST( const InitDeclaratorAST& source );
+ void operator = ( const InitDeclaratorAST& source );
+};
+
+class InitDeclaratorListAST: public AST
+{
+public:
+ typedef AUTO_PTR<InitDeclaratorListAST> Node;
+ enum { Type = NodeType_InitDeclaratorList };
+
+ DECLARE_ALLOC( InitDeclaratorListAST )
+
+public:
+ InitDeclaratorListAST();
+
+ QPtrList<InitDeclaratorAST> initDeclaratorList() { return m_initDeclaratorList; }
+ void addInitDeclarator( InitDeclaratorAST::Node& decl );
+
+private:
+ QPtrList<InitDeclaratorAST> m_initDeclaratorList;
+
+private:
+ InitDeclaratorListAST( const InitDeclaratorListAST& source );
+ void operator = ( const InitDeclaratorListAST& source );
+};
+
+class TypedefAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<TypedefAST> Node;
+ enum { Type = NodeType_Typedef };
+
+ DECLARE_ALLOC( TypedefAST )
+
+public:
+ TypedefAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorListAST* initDeclaratorList() { return m_initDeclaratorList.get(); }
+ void setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList );
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorListAST::Node m_initDeclaratorList;
+
+private:
+ TypedefAST( const TypedefAST& source );
+ void operator = ( const TypedefAST& source );
+};
+
+class TemplateParameterAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateParameterAST> Node;
+ enum { Type = NodeType_TemplateParameter };
+
+ DECLARE_ALLOC( TemplateParameterAST )
+
+public:
+ TemplateParameterAST();
+
+ TypeParameterAST* typeParameter() { return m_typeParameter.get(); }
+ void setTypeParameter( TypeParameterAST::Node& typeParameter );
+
+ ParameterDeclarationAST* typeValueParameter() { return m_typeValueParameter.get(); }
+ void setTypeValueParameter( ParameterDeclarationAST::Node& typeValueParameter );
+
+private:
+ TypeParameterAST::Node m_typeParameter;
+ ParameterDeclarationAST::Node m_typeValueParameter;
+
+private:
+ TemplateParameterAST( const TemplateParameterAST& source );
+ void operator = ( const TemplateParameterAST& source );
+};
+
+class TemplateParameterListAST: public AST
+{
+public:
+ typedef AUTO_PTR<TemplateParameterListAST> Node;
+ enum { Type = NodeType_TemplateParameterList };
+
+ DECLARE_ALLOC( TemplateParameterListAST )
+
+public:
+ TemplateParameterListAST();
+
+ QPtrList<TemplateParameterAST> templateParameterList() { return m_templateParameterList; }
+ void addTemplateParameter( TemplateParameterAST::Node& templateParameter );
+
+private:
+ QPtrList<TemplateParameterAST> m_templateParameterList;
+
+private:
+ TemplateParameterListAST( const TemplateParameterListAST& source );
+ void operator = ( const TemplateParameterListAST& source );
+};
+
+class TemplateDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<TemplateDeclarationAST> Node;
+ enum { Type = NodeType_TemplateDeclaration };
+
+ DECLARE_ALLOC( TemplateDeclarationAST )
+
+public:
+ TemplateDeclarationAST();
+
+ AST* exported() { return m_exported.get(); }
+ void setExported( AST::Node& exported );
+
+ TemplateParameterListAST* templateParameterList() { return m_templateParameterList.get(); }
+ void setTemplateParameterList( TemplateParameterListAST::Node& templateParameterList );
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ AST::Node m_exported;
+ TemplateParameterListAST::Node m_templateParameterList;
+ DeclarationAST::Node m_declaration;
+
+private:
+ TemplateDeclarationAST( const TemplateDeclarationAST& source );
+ void operator = ( const TemplateDeclarationAST& source );
+};
+
+class SimpleDeclarationAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<SimpleDeclarationAST> Node;
+ enum { Type = NodeType_SimpleDeclaration };
+
+ DECLARE_ALLOC( SimpleDeclarationAST )
+
+public:
+ SimpleDeclarationAST();
+
+ GroupAST* functionSpecifier() { return m_functionSpecifier.get(); }
+ void setFunctionSpecifier( GroupAST::Node& functionSpecifier );
+
+ GroupAST* storageSpecifier() { return m_storageSpecifier.get(); }
+ void setStorageSpecifier( GroupAST::Node& storageSpecifier );
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorListAST* initDeclaratorList() { return m_initDeclaratorList.get(); }
+ void setInitDeclaratorList( InitDeclaratorListAST::Node& initDeclaratorList );
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+private:
+ GroupAST::Node m_functionSpecifier;
+ GroupAST::Node m_storageSpecifier;
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorListAST::Node m_initDeclaratorList;
+ GroupAST::Node m_winDeclSpec;
+
+private:
+ SimpleDeclarationAST( const SimpleDeclarationAST& source );
+ void operator = ( const SimpleDeclarationAST& source );
+};
+
+class StatementAST: public AST
+{
+public:
+ typedef AUTO_PTR<StatementAST> Node;
+ enum { Type = NodeType_Statement };
+
+ DECLARE_ALLOC( StatementAST )
+
+public:
+ StatementAST();
+
+private:
+ StatementAST( const StatementAST& source );
+ void operator = ( const StatementAST& source );
+};
+
+class ExpressionStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<ExpressionStatementAST> Node;
+ enum { Type = NodeType_ExpressionStatement };
+
+ DECLARE_ALLOC( ExpressionStatementAST )
+
+public:
+ ExpressionStatementAST();
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+private:
+ AST::Node m_expression;
+
+private:
+ ExpressionStatementAST( const ExpressionStatementAST& source );
+ void operator = ( const ExpressionStatementAST& source );
+};
+
+class ConditionAST: public AST
+{
+public:
+ typedef AUTO_PTR<ConditionAST> Node;
+ enum { Type = NodeType_Condition };
+
+ DECLARE_ALLOC( ConditionAST )
+
+public:
+ ConditionAST();
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ DeclaratorAST* declarator() { return m_declarator.get(); }
+ void setDeclarator( DeclaratorAST::Node& declarator );
+
+ AST* expression() { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+private:
+ TypeSpecifierAST::Node m_typeSpec;
+ DeclaratorAST::Node m_declarator;
+ AST::Node m_expression;
+
+private:
+ ConditionAST( const ConditionAST& source );
+ void operator = ( const ConditionAST& source );
+};
+
+class IfStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<IfStatementAST> Node;
+ enum { Type = NodeType_IfStatement };
+
+ DECLARE_ALLOC( IfStatementAST )
+
+public:
+ IfStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+ StatementAST* elseStatement() { return m_elseStatement.get(); }
+ void setElseStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+ StatementAST::Node m_elseStatement;
+
+private:
+ IfStatementAST( const IfStatementAST& source );
+ void operator = ( const IfStatementAST& source );
+};
+
+class WhileStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<WhileStatementAST> Node;
+ enum { Type = NodeType_WhileStatement };
+
+ DECLARE_ALLOC( WhileStatementAST )
+
+public:
+ WhileStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ WhileStatementAST( const WhileStatementAST& source );
+ void operator = ( const WhileStatementAST& source );
+};
+
+class DoStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<DoStatementAST> Node;
+ enum { Type = NodeType_DoStatement };
+
+ DECLARE_ALLOC( DoStatementAST )
+
+public:
+ DoStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ DoStatementAST( const DoStatementAST& source );
+ void operator = ( const DoStatementAST& source );
+};
+
+class ForStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<ForStatementAST> Node;
+ enum { Type = NodeType_ForStatement };
+
+ DECLARE_ALLOC( ForStatementAST )
+
+public:
+ ForStatementAST();
+
+ StatementAST* initStatement() { return m_initStatement.get(); }
+ void setInitStatement( StatementAST::Node& statement );
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ AST* expression() const { return m_expression.get(); }
+ void setExpression( AST::Node& expression );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_initStatement;
+ StatementAST::Node m_statement;
+ AST::Node m_expression;
+
+private:
+ ForStatementAST( const ForStatementAST& source );
+ void operator = ( const ForStatementAST& source );
+};
+
+class SwitchStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<SwitchStatementAST> Node;
+ enum { Type = NodeType_SwitchStatement };
+
+ DECLARE_ALLOC( SwitchStatementAST )
+
+public:
+ SwitchStatementAST();
+
+ ConditionAST* condition() const { return m_condition.get(); }
+ void setCondition( ConditionAST::Node& condition );
+
+ StatementAST* statement() { return m_statement.get(); }
+ void setStatement( StatementAST::Node& statement );
+
+private:
+ ConditionAST::Node m_condition;
+ StatementAST::Node m_statement;
+
+private:
+ SwitchStatementAST( const SwitchStatementAST& source );
+ void operator = ( const SwitchStatementAST& source );
+};
+
+class StatementListAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<StatementListAST> Node;
+ enum { Type = NodeType_StatementList };
+
+ DECLARE_ALLOC( StatementListAST )
+
+public:
+ StatementListAST();
+
+ QPtrList<StatementAST> statementList() { return m_statementList; }
+ void addStatement( StatementAST::Node& statement );
+
+private:
+ QPtrList<StatementAST> m_statementList;
+
+private:
+ StatementListAST( const StatementListAST& source );
+ void operator = ( const StatementListAST& source );
+};
+
+class DeclarationStatementAST: public StatementAST
+{
+public:
+ typedef AUTO_PTR<DeclarationStatementAST> Node;
+ enum { Type = NodeType_DeclarationStatement };
+
+ DECLARE_ALLOC( DeclarationStatementAST )
+
+public:
+ DeclarationStatementAST();
+
+ DeclarationAST* declaration() { return m_declaration.get(); }
+ void setDeclaration( DeclarationAST::Node& declaration );
+
+private:
+ DeclarationAST::Node m_declaration;
+
+private:
+ DeclarationStatementAST( const DeclarationStatementAST& source );
+ void operator = ( const DeclarationStatementAST& source );
+};
+
+class FunctionDefinitionAST: public DeclarationAST
+{
+public:
+ typedef AUTO_PTR<FunctionDefinitionAST> Node;
+ enum { Type = NodeType_FunctionDefinition };
+
+ DECLARE_ALLOC( FunctionDefinitionAST )
+
+public:
+ FunctionDefinitionAST();
+
+ GroupAST* functionSpecifier() { return m_functionSpecifier.get(); }
+ void setFunctionSpecifier( GroupAST::Node& functionSpecifier );
+
+ GroupAST* storageSpecifier() { return m_storageSpecifier.get(); }
+ void setStorageSpecifier( GroupAST::Node& storageSpecifier );
+
+ TypeSpecifierAST* typeSpec() { return m_typeSpec.get(); }
+ void setTypeSpec( TypeSpecifierAST::Node& typeSpec );
+
+ InitDeclaratorAST* initDeclarator() { return m_initDeclarator.get(); }
+ void setInitDeclarator( InitDeclaratorAST::Node& initDeclarator );
+
+ StatementListAST* functionBody() { return m_functionBody.get(); }
+ void setFunctionBody( StatementListAST::Node& functionBody );
+
+ GroupAST* winDeclSpec() { return m_winDeclSpec.get(); }
+ void setWinDeclSpec( GroupAST::Node& winDeclSpec );
+
+private:
+ GroupAST::Node m_functionSpecifier;
+ GroupAST::Node m_storageSpecifier;
+ TypeSpecifierAST::Node m_typeSpec;
+ InitDeclaratorAST::Node m_initDeclarator;
+ StatementListAST::Node m_functionBody;
+ GroupAST::Node m_winDeclSpec;
+
+private:
+ FunctionDefinitionAST( const FunctionDefinitionAST& source );
+ void operator = ( const FunctionDefinitionAST& source );
+};
+
+
+class TranslationUnitAST: public AST
+{
+public:
+ typedef AUTO_PTR<TranslationUnitAST> Node;
+ enum { Type = NodeType_TranslationUnit };
+
+ DECLARE_ALLOC( TranslationUnitAST )
+
+public:
+ TranslationUnitAST();
+
+ void addDeclaration( DeclarationAST::Node& ast );
+ QPtrList<DeclarationAST> declarationList() { return m_declarationList; }
+
+private:
+ QPtrList<DeclarationAST> m_declarationList;
+
+private:
+ TranslationUnitAST( const TranslationUnitAST& source );
+ void operator = ( const TranslationUnitAST& source );
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp
new file mode 100644
index 00000000..e30f0c1e
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.cpp
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Roberto Raggi *
+ * roberto@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "ast_utils.h"
+#include "ast.h"
+
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+AST* findNodeAt( AST* node, int line, int column )
+{
+ // kdDebug(9007) << "findNodeAt(" << node << ")" << endl;
+
+ if( !node )
+ return 0;
+
+ int startLine, startColumn;
+ int endLine, endColumn;
+
+ node->getStartPosition( &startLine, &startColumn );
+ node->getEndPosition( &endLine, &endColumn );
+
+ if( (line > startLine || (line == startLine && column >= startColumn)) &&
+ (line < endLine || (line == endLine && column < endColumn)) ){
+
+ QPtrList<AST> children = node->children();
+ QPtrListIterator<AST> it( children );
+ while( it.current() ){
+ AST* a = it.current();
+ ++it;
+
+ AST* r = findNodeAt( a, line, column );
+ if( r )
+ return r;
+ }
+
+ return node;
+ }
+
+ return 0;
+}
+
+void scopeOfNode( AST* ast, QStringList& scope )
+{
+ if( !ast )
+ return;
+
+ if( ast->parent() )
+ scopeOfNode( ast->parent(), scope );
+
+ QString s;
+ switch( ast->nodeType() )
+ {
+ case NodeType_ClassSpecifier:
+ if( ((ClassSpecifierAST*)ast)->name() ){
+ s = ((ClassSpecifierAST*)ast)->name()->text();
+ s = s.isEmpty() ? QString::fromLatin1("<unnamed>") : s;
+ scope.push_back( s );
+ }
+ break;
+
+ case NodeType_Namespace:
+ {
+ AST* namespaceName = ((NamespaceAST*)ast)->namespaceName();
+ s = namespaceName ? namespaceName->text() : QString::fromLatin1("<unnamed>");
+ scope.push_back( s );
+ }
+ break;
+
+ case NodeType_FunctionDefinition:
+ {
+ FunctionDefinitionAST* funDef = static_cast<FunctionDefinitionAST*>( ast );
+ DeclaratorAST* d = funDef->initDeclarator()->declarator();
+
+ // hotfix for bug #68726
+ if ( !d->declaratorId() )
+ break;
+
+ QPtrList<ClassOrNamespaceNameAST> l = d->declaratorId()->classOrNamespaceNameList();
+ QPtrListIterator<ClassOrNamespaceNameAST> nameIt( l );
+ while( nameIt.current() ){
+ AST* name = nameIt.current()->name();
+ scope.push_back( name->text() );
+
+ ++nameIt;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+QString typeSpecToString( TypeSpecifierAST* typeSpec ) /// @todo remove
+{
+ if( !typeSpec )
+ return QString::null;
+
+ return typeSpec->text().replace( QRegExp(" :: "), "::" );
+}
+
+QString declaratorToString( DeclaratorAST* declarator, const QString& scope, bool skipPtrOp )
+{
+ if( !declarator )
+ return QString::null;
+
+ QString text;
+
+ if( !skipPtrOp ){
+ QPtrList<AST> ptrOpList = declarator->ptrOpList();
+ for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
+ text += it.current()->text();
+ }
+ text += ' ';
+ }
+
+ text += scope;
+
+ if( declarator->subDeclarator() )
+ text += QString::fromLatin1("(") + declaratorToString(declarator->subDeclarator()) + QString::fromLatin1(")");
+
+ if( declarator->declaratorId() )
+ text += declarator->declaratorId()->text();
+
+ QPtrList<AST> arrays = declarator->arrayDimensionList();
+ QPtrListIterator<AST> it( arrays );
+ while( it.current() ){
+ text += "[]";
+ ++it;
+ }
+
+ if( declarator->parameterDeclarationClause() ){
+ text += "( ";
+
+ ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
+ if( l != 0 ){
+ QPtrList<ParameterDeclarationAST> params = l->parameterList();
+ QPtrListIterator<ParameterDeclarationAST> it( params );
+
+ while( it.current() ){
+ QString type = typeSpecToString( it.current()->typeSpec() );
+ text += type;
+ if( !type.isEmpty() )
+ text += ' ';
+ text += declaratorToString( it.current()->declarator() );
+
+ ++it;
+
+ if( it.current() )
+ text += ", ";
+ }
+ }
+
+ text += " )";
+
+ if( declarator->constant() != 0 )
+ text += " const";
+ }
+
+ return text.replace( QRegExp(" :: "), "::" ).simplifyWhiteSpace();
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h
new file mode 100644
index 00000000..187647b7
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/ast_utils.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * Copyright (C) 2002 by Roberto Raggi *
+ * roberto@kdevelop.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __ast_utils_h
+#define __ast_utils_h
+
+#include <qstring.h>
+
+class AST;
+class DeclaratorAST;
+class TypeSpecifierAST;
+class QStringList;
+
+namespace KTextEditor{ class EditInterface; }
+
+AST* findNodeAt( AST* unit, int line, int column );
+void scopeOfNode( AST* ast, QStringList& );
+QString typeSpecToString( TypeSpecifierAST* typeSpec );
+QString declaratorToString( DeclaratorAST* declarator, const QString& scope = QString::null, bool skipPtrOp=false );
+
+#endif // __ast_utils_h
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp
new file mode 100644
index 00000000..e7d0b848
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.cpp
@@ -0,0 +1,640 @@
+/***************************************************************************
+ * Based on kdevelop-3.0 languages/cpp/store_walker.cpp by Roberto Raggi *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2004-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "cpptree2uml.h"
+// qt/kde includes
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "ast_utils.h"
+#include "urlutil.h"
+#include "../import_utils.h"
+// FIXME: The sole reason for the next 2 includes is parseTypedef().
+// Make capsule methods in ClassImport, and remove these includes.
+#include "../../classifier.h"
+// FIXME The next include is motivated by template params
+#include "../../template.h"
+
+CppTree2Uml::CppTree2Uml( const QString& fileName)
+ : m_anon( 0 ), m_nsCnt( 0 ), m_clsCnt( 0 )
+{
+ m_fileName = URLUtil::canonicalPath(fileName);
+}
+
+CppTree2Uml::~CppTree2Uml()
+{
+}
+
+void CppTree2Uml::parseTranslationUnit( TranslationUnitAST* ast )
+{
+ m_currentScope.clear();
+ m_currentNamespace[0] = NULL; // index 0 is reserved (always NULL)
+ m_currentClass[0] = NULL; // index 0 is reserved (always NULL)
+ m_nsCnt = 0;
+ m_clsCnt = 0;
+
+ m_currentAccess = Uml::Visibility::Public;
+ m_inSlots = false;
+ m_inSignals = false;
+ m_inStorageSpec = false;
+ m_inTypedef = false;
+ m_currentDeclarator = 0;
+ m_anon = 0;
+
+ TreeParser::parseTranslationUnit( ast );
+}
+
+void CppTree2Uml::parseNamespace( NamespaceAST* ast )
+{
+ if (m_clsCnt > 0) {
+ kDebug() << "CppTree2Uml::parseNamespace: error - cannot nest namespace inside class"
+ << endl;
+ return;
+ }
+
+ QString nsName;
+ if( !ast->namespaceName() || ast->namespaceName()->text().isEmpty() ){
+ QFileInfo fileInfo( m_fileName );
+ QString shortFileName = fileInfo.baseName();
+
+ nsName.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ );
+ } else {
+ nsName = ast->namespaceName()->text();
+ }
+
+#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseNamespace: " << nsName << endl;
+#endif
+ UMLObject * o = Import_Utils::createUMLObject( Uml::ot_Package, nsName,
+ m_currentNamespace[m_nsCnt],
+ ast->comment());
+ UMLPackage *ns = (UMLPackage *)o;
+ m_currentScope.push_back( nsName );
+ if (++m_nsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive namespace nesting" << endl;
+ m_nsCnt = STACKSIZE;
+ }
+ m_currentNamespace[m_nsCnt] = ns;
+
+ TreeParser::parseNamespace( ast );
+
+ --m_nsCnt;
+ m_currentScope.pop_back();
+}
+
+void CppTree2Uml::parseTypedef( TypedefAST* ast )
+{
+#if 0
+ DeclaratorAST* oldDeclarator = m_currentDeclarator;
+
+ if( ast && ast->initDeclaratorList() && ast->initDeclaratorList()->initDeclaratorList().count() > 0 ) {
+ QPtrList<InitDeclaratorAST> lst( ast->initDeclaratorList()->initDeclaratorList() );
+ m_currentDeclarator = lst.at( 0 )->declarator();
+ }
+
+ m_inTypedef = true;
+
+ TreeParser::parseTypedef( ast );
+
+ m_inTypedef = false;
+ m_currentDeclarator = oldDeclarator;
+#else
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ InitDeclaratorListAST* declarators = ast->initDeclaratorList();
+
+ if( typeSpec && declarators ){
+ QString typeId;
+
+ if( typeSpec->name() )
+ typeId = typeSpec->name()->text();
+
+ QPtrList<InitDeclaratorAST> l( declarators->initDeclaratorList() );
+ QPtrListIterator<InitDeclaratorAST> it( l );
+
+ InitDeclaratorAST* initDecl = 0;
+ while( 0 != (initDecl = it.current()) ){
+
+ QString type, id;
+ if( initDecl->declarator() ){
+ type = typeOfDeclaration( typeSpec, initDecl->declarator() );
+
+ DeclaratorAST* d = initDecl->declarator();
+ while( d->subDeclarator() ){
+ d = d->subDeclarator();
+ }
+
+ if( d->declaratorId() )
+ id = d->declaratorId()->text();
+ }
+//#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseTypedef: name=" << id << ", type=" << type << endl;
+//#endif
+ /* @todo Trace typedefs back to their root type for deciding
+ whether to build a Datatype (for pointers.) */
+ /* check out if the ID type is a Datatype
+ ex: typedef unsigned int uint;
+ where unsigned int is a known datatype
+ I'm not sure if setIsReference() should be run
+ */
+ bool isDatatype = Import_Utils::isDatatype(typeId, m_currentNamespace[m_nsCnt]);
+
+ if (type.contains('*') || isDatatype) {
+ UMLObject *inner =
+ Import_Utils::createUMLObject( Uml::ot_Class, typeId,
+ m_currentNamespace[m_nsCnt] );
+ UMLObject *typedefObj =
+ Import_Utils::createUMLObject( Uml::ot_Datatype, id,
+ m_currentNamespace[m_nsCnt] );
+ UMLClassifier *dt = static_cast<UMLClassifier*>(typedefObj);
+ dt->setIsReference();
+ dt->setOriginType(static_cast<UMLClassifier*>(inner));
+ } else {
+ Import_Utils::createUMLObject( Uml::ot_Class, id,
+ m_currentNamespace[m_nsCnt],
+ "" /* doc */,
+ "typedef" /* stereotype */);
+ }
+ ++it;
+ }
+
+ }
+#endif
+}
+
+void CppTree2Uml::parseTemplateDeclaration( TemplateDeclarationAST* ast )
+{
+ TemplateParameterListAST* parmListAST = ast->templateParameterList();
+ if (parmListAST == NULL)
+ return;
+ QPtrList<TemplateParameterAST> parmList = parmListAST->templateParameterList();
+ for (QPtrListIterator<TemplateParameterAST> it(parmList); it.current(); ++it) {
+ // The template is either a typeParameter or a typeValueParameter.
+
+ TemplateParameterAST* tmplParmNode = it.current();
+ TypeParameterAST* typeParmNode = tmplParmNode->typeParameter();
+ if (typeParmNode) {
+ NameAST* nameNode = typeParmNode->name();
+ if (nameNode) {
+ QString typeName = nameNode->unqualifiedName()->text();
+ Model_Utils::NameAndType nt(typeName, NULL);
+ m_templateParams.append(nt);
+ } else {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(type):"
+ << " nameNode is NULL" << endl;
+ }
+ }
+
+ ParameterDeclarationAST* valueNode = tmplParmNode->typeValueParameter();
+ if (valueNode) {
+ TypeSpecifierAST* typeSpec = valueNode->typeSpec();
+ if (typeSpec == NULL) {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(value):"
+ << " typeSpec is NULL" << endl;
+ continue;
+ }
+ QString typeName = typeSpec->name()->text();
+ UMLObject *t = Import_Utils::createUMLObject( Uml::ot_UMLObject, typeName,
+ m_currentNamespace[m_nsCnt] );
+ DeclaratorAST* declNode = valueNode->declarator();
+ NameAST* nameNode = declNode->declaratorId();
+ if (nameNode == NULL) {
+ kdError() << "CppTree2Uml::parseTemplateDeclaration(value):"
+ << " nameNode is NULL" << endl;
+ continue;
+ }
+ QString paramName = nameNode->unqualifiedName()->text();
+ Model_Utils::NameAndType nt(paramName, t);
+ m_templateParams.append(nt);
+ }
+ }
+
+ if( ast->declaration() )
+ TreeParser::parseDeclaration( ast->declaration() );
+}
+
+void CppTree2Uml::parseSimpleDeclaration( SimpleDeclarationAST* ast )
+{
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ InitDeclaratorListAST* declarators = ast->initDeclaratorList();
+
+ m_comment = ast->comment();
+
+ if( typeSpec )
+ parseTypeSpecifier( typeSpec );
+
+ if( declarators ){
+ QPtrList<InitDeclaratorAST> l = declarators->initDeclaratorList();
+
+ QPtrListIterator<InitDeclaratorAST> it( l );
+ while( it.current() ){
+ parseDeclaration( ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, it.current() );
+ ++it;
+ }
+ }
+}
+
+void CppTree2Uml::parseFunctionDefinition( FunctionDefinitionAST* ast )
+{
+ TypeSpecifierAST* typeSpec = ast->typeSpec();
+ GroupAST* funSpec = ast->functionSpecifier();
+ GroupAST* storageSpec = ast->storageSpecifier();
+
+ if( !ast->initDeclarator() )
+ return;
+
+ DeclaratorAST* d = ast->initDeclarator()->declarator();
+
+ if( !d->declaratorId() )
+ return;
+
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isConstructor = false;
+
+ if( funSpec ){
+ QPtrList<AST> l = funSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "virtual" ) isVirtual = true;
+ else if( text == "inline" ) isInline = true;
+ ++it;
+ }
+ }
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ QString id = d->declaratorId()->unqualifiedName()->text().stripWhiteSpace();
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseFunctionDefinition (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString returnType = typeOfDeclaration( typeSpec, d );
+ UMLOperation *m = Import_Utils::makeOperation(c, id);
+ // if a class has no return type, it could be a constructor or
+ // a destructor
+ if (d && returnType.isEmpty() && id.find("~") == -1)
+ isConstructor = true;
+
+ parseFunctionArguments( d, m );
+ Import_Utils::insertMethod( c, m, m_currentAccess, returnType,
+ isStatic, false /*isAbstract*/, isFriend, isConstructor, m_comment);
+ m_comment = "";
+
+/* For reference, Kdevelop does some more:
+ method->setFileName( m_fileName );
+ if( m_inSignals )
+ method->setSignal( true );
+ if( m_inSlots )
+ method->setSlot( true );
+ */
+}
+
+void CppTree2Uml::parseClassSpecifier( ClassSpecifierAST* ast )
+{
+ Uml::Visibility oldAccess = m_currentAccess;
+ bool oldInSlots = m_inSlots;
+ bool oldInSignals = m_inSignals;
+
+ QString kind = ast->classKey()->text();
+ m_currentAccess=Uml::Visibility::fromString(kind);
+ m_inSlots = false;
+ m_inSignals = false;
+
+ QString className;
+ if( !ast->name() && m_currentDeclarator && m_currentDeclarator->declaratorId() ) {
+ className = m_currentDeclarator->declaratorId()->text().stripWhiteSpace();
+ } else if( !ast->name() ){
+ QFileInfo fileInfo( m_fileName );
+ QString shortFileName = fileInfo.baseName();
+ className.sprintf( "(%s_%d)", shortFileName.local8Bit().data(), m_anon++ );
+ } else {
+ className = ast->name()->unqualifiedName()->text().stripWhiteSpace();
+ }
+//#ifdef DEBUG_CPPTREE2UML
+ kDebug() << "CppTree2Uml::parseClassSpecifier: name=" << className << endl;
+//#endif
+ if( !scopeOfName( ast->name(), QStringList() ).isEmpty() ){
+ kDebug() << "skip private class declarations" << endl;
+ return;
+ }
+
+ if (className.isEmpty()) {
+ className = "anon_" + QString::number(m_anon);
+ m_anon++;
+ }
+ UMLObject * o = Import_Utils::createUMLObject( Uml::ot_Class, className,
+ m_currentNamespace[m_nsCnt],
+ ast->comment() );
+ UMLClassifier *klass = static_cast<UMLClassifier*>(o);
+ flushTemplateParams(klass);
+ if ( ast->baseClause() )
+ parseBaseClause( ast->baseClause(), klass );
+
+ m_currentScope.push_back( className );
+ if (++m_clsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive class nesting" << endl;
+ m_clsCnt = STACKSIZE;
+ }
+ m_currentClass[m_clsCnt] = klass;
+ if (++m_nsCnt > STACKSIZE) {
+ kdError() << "CppTree2Uml::parseNamespace: excessive namespace nesting" << endl;
+ m_nsCnt = STACKSIZE;
+ }
+ m_currentNamespace[m_nsCnt] = (UMLPackage*)klass;
+
+ TreeParser::parseClassSpecifier( ast );
+
+ --m_nsCnt;
+ --m_clsCnt;
+
+ m_currentScope.pop_back();
+
+ m_currentAccess = oldAccess;
+ m_inSlots = oldInSlots;
+ m_inSignals = oldInSignals;
+}
+
+void CppTree2Uml::parseEnumSpecifier( EnumSpecifierAST* ast )
+{
+ NameAST *nameNode = ast->name();
+ if (nameNode == NULL)
+ return; // skip constants
+ QString typeName = nameNode->unqualifiedName()->text().stripWhiteSpace();
+ if (typeName.isEmpty())
+ return; // skip constants
+ UMLObject *o = Import_Utils::createUMLObject( Uml::ot_Enum, typeName,
+ m_currentNamespace[m_nsCnt],
+ ast->comment() );
+
+ QPtrList<EnumeratorAST> l = ast->enumeratorList();
+ QPtrListIterator<EnumeratorAST> it( l );
+ while ( it.current() ) {
+ QString enumLiteral = it.current()->id()->text();
+ Import_Utils::addEnumLiteral( (UMLEnum*)o, enumLiteral );
+ ++it;
+ }
+}
+
+void CppTree2Uml::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* typeSpec )
+{
+ // This is invoked for forward declarations.
+ /// @todo Refine - Currently only handles class forward declarations.
+ /// - Using typeSpec->text() is probably not good, decode
+ /// the kind() instead.
+ QString text = typeSpec->text();
+ kDebug() << "CppTree2Uml::parseElaboratedTypeSpecifier: text is " << text << endl;
+ text.remove(QRegExp("^class\\s+"));
+ UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Class, text, m_currentNamespace[m_nsCnt]);
+ flushTemplateParams( static_cast<UMLClassifier*>(o) );
+}
+
+void CppTree2Uml::parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
+ TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl )
+{
+ if( m_inStorageSpec )
+ return;
+
+ DeclaratorAST* d = decl->declarator();
+
+ if( !d )
+ return;
+
+ if( !d->subDeclarator() && d->parameterDeclarationClause() )
+ return parseFunctionDeclaration( funSpec, storageSpec, typeSpec, decl );
+
+ DeclaratorAST* t = d;
+ while( t && t->subDeclarator() )
+ t = t->subDeclarator();
+
+ QString id;
+ if( t && t->declaratorId() && t->declaratorId()->unqualifiedName() )
+ id = t->declaratorId()->unqualifiedName()->text();
+
+ if( !scopeOfDeclarator(d, QStringList()).isEmpty() ){
+ kDebug() << "CppTree2Uml::parseDeclaration (" << id << "): skipping."
+ << endl;
+ return;
+ }
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseDeclaration (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString typeName = typeOfDeclaration( typeSpec, d );
+ bool isFriend = false;
+ bool isStatic = false;
+ //bool isInitialized = decl->initializer() != 0;
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ Import_Utils::insertAttribute( c, m_currentAccess, id, typeName,
+ m_comment, isStatic);
+ m_comment = "";
+}
+
+void CppTree2Uml::parseAccessDeclaration( AccessDeclarationAST * access )
+{
+ QPtrList<AST> l = access->accessList();
+
+ QString accessStr = l.at( 0 )->text();
+
+ m_currentAccess=Uml::Visibility::fromString(accessStr);
+
+ m_inSlots = l.count() > 1 ? l.at( 1 )->text() == "slots" : false;
+ m_inSignals = l.count() >= 1 ? l.at( 0 )->text() == "signals" : false;
+}
+
+void CppTree2Uml::parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec,
+ TypeSpecifierAST * typeSpec, InitDeclaratorAST * decl )
+{
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isPure = decl->initializer() != 0;
+ bool isConstructor = false;
+
+ if( funSpec ){
+ QPtrList<AST> l = funSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "virtual" ) isVirtual = true;
+ else if( text == "inline" ) isInline = true;
+ ++it;
+ }
+ }
+
+ if( storageSpec ){
+ QPtrList<AST> l = storageSpec->nodeList();
+ QPtrListIterator<AST> it( l );
+ while( it.current() ){
+ QString text = it.current()->text();
+ if( text == "friend" ) isFriend = true;
+ else if( text == "static" ) isStatic = true;
+ ++it;
+ }
+ }
+
+ DeclaratorAST* d = decl->declarator();
+ QString id = d->declaratorId()->unqualifiedName()->text();
+
+ UMLClassifier *c = m_currentClass[m_clsCnt];
+ if (c == NULL) {
+ kDebug() << "CppTree2Uml::parseFunctionDeclaration (" << id
+ << "): need a surrounding class." << endl;
+ return;
+ }
+
+ QString returnType = typeOfDeclaration( typeSpec, d );
+ UMLOperation *m = Import_Utils::makeOperation(c, id);
+ // if a class has no return type, it could be a constructor or
+ // a destructor
+ if (d && returnType.isEmpty() && id.find("~") == -1)
+ isConstructor = true;
+
+ parseFunctionArguments( d, m );
+ Import_Utils::insertMethod( c, m, m_currentAccess, returnType,
+ isStatic, isPure, isFriend, isConstructor, m_comment);
+ m_comment = "";
+}
+
+void CppTree2Uml::parseFunctionArguments(DeclaratorAST* declarator,
+ UMLOperation* method)
+{
+ ParameterDeclarationClauseAST* clause = declarator->parameterDeclarationClause();
+
+ if( clause && clause->parameterDeclarationList() ){
+ ParameterDeclarationListAST* params = clause->parameterDeclarationList();
+ QPtrList<ParameterDeclarationAST> l( params->parameterList() );
+ QPtrListIterator<ParameterDeclarationAST> it( l );
+ while( it.current() ){
+ ParameterDeclarationAST* param = it.current();
+ ++it;
+
+ QString name;
+ if (param->declarator())
+ name = declaratorToString(param->declarator(), QString::null, true );
+
+ QString tp = typeOfDeclaration( param->typeSpec(), param->declarator() );
+
+ if (tp != "void")
+ Import_Utils::addMethodParameter( method, tp, name );
+ }
+ }
+}
+
+QString CppTree2Uml::typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator )
+{
+ if( !typeSpec || !declarator )
+ return QString::null;
+
+ QString text;
+
+ text += typeSpec->text();
+
+ QPtrList<AST> ptrOpList = declarator->ptrOpList();
+ for( QPtrListIterator<AST> it(ptrOpList); it.current(); ++it ){
+ text += it.current()->text();
+ }
+
+ return text;
+}
+
+void CppTree2Uml::parseBaseClause( BaseClauseAST * baseClause, UMLClassifier* klass )
+{
+ QPtrList<BaseSpecifierAST> l = baseClause->baseSpecifierList();
+ QPtrListIterator<BaseSpecifierAST> it( l );
+ while( it.current() ){
+ BaseSpecifierAST* baseSpecifier = it.current();
+ ++it;
+
+ if (baseSpecifier->name() == NULL) {
+ kDebug() << "CppTree2Uml::parseBaseClause: baseSpecifier->name() is NULL"
+ << endl;
+ continue;
+ }
+
+ QString baseName = baseSpecifier->name()->text();
+ Import_Utils::createGeneralization( klass, baseName );
+ }
+}
+
+QStringList CppTree2Uml::scopeOfName( NameAST* id, const QStringList& startScope )
+{
+ QStringList scope = startScope;
+ if( id && id->classOrNamespaceNameList().count() ){
+ if( id->isGlobal() )
+ scope.clear();
+ QPtrList<ClassOrNamespaceNameAST> l = id->classOrNamespaceNameList();
+ QPtrListIterator<ClassOrNamespaceNameAST> it( l );
+ while( it.current() ){
+ if( it.current()->name() ){
+ scope << it.current()->name()->text();
+ }
+ ++it;
+ }
+ }
+
+ return scope;
+}
+
+QStringList CppTree2Uml::scopeOfDeclarator( DeclaratorAST* d, const QStringList& startScope )
+{
+ return scopeOfName( d->declaratorId(), startScope );
+}
+
+void CppTree2Uml::flushTemplateParams(UMLClassifier *klass) {
+ if (m_templateParams.count()) {
+ Model_Utils::NameAndType_ListIt it;
+ for (it = m_templateParams.begin(); it != m_templateParams.end(); ++it) {
+ const Model_Utils::NameAndType &nt = *it;
+ kDebug() << "CppTree2Uml::parseClassSpecifier: adding template param: "
+ << nt.m_name << endl;
+ UMLTemplate *tmpl = klass->addTemplate(nt.m_name);
+ tmpl->setType(nt.m_type);
+ }
+ m_templateParams.clear();
+ }
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h
new file mode 100644
index 00000000..b9791372
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/cpptree2uml.h
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef CPPTREE2UML_H
+#define CPPTREE2UML_H
+
+#include "tree_parser.h"
+#include <qstringlist.h>
+#include "../../model_utils.h"
+
+// fwd decls
+class UMLClassifier;
+class UMLOperation;
+class UMLPackage;
+
+class CppTree2Uml: public TreeParser
+{
+public:
+ CppTree2Uml( const QString& fileName);
+ virtual ~CppTree2Uml();
+
+ //FileDom file() { return m_file; }
+
+ // translation-unit
+ virtual void parseTranslationUnit( TranslationUnitAST* );
+
+ // declarations
+ //virtual void parseDeclaration( DeclarationAST* ); // use parent method
+ //virtual void parseLinkageSpecification( LinkageSpecificationAST* ); // use parent method
+ virtual void parseNamespace( NamespaceAST* );
+ //virtual void parseNamespaceAlias( NamespaceAliasAST* ); // use parent method
+ //virtual void parseUsing( UsingAST* ); // use parent method
+ //virtual void parseUsingDirective( UsingDirectiveAST* ); // use parent method
+ virtual void parseTypedef( TypedefAST* );
+ virtual void parseTemplateDeclaration( TemplateDeclarationAST* );
+ virtual void parseSimpleDeclaration( SimpleDeclarationAST* );
+ virtual void parseFunctionDefinition( FunctionDefinitionAST* );
+ //virtual void parseLinkageBody( LinkageBodyAST* ); // use parent method
+ virtual void parseAccessDeclaration( AccessDeclarationAST* );
+
+ // type-specifier
+ //virtual void parseTypeSpecifier( TypeSpecifierAST* ); // use parent method
+ virtual void parseClassSpecifier( ClassSpecifierAST* );
+ virtual void parseEnumSpecifier( EnumSpecifierAST* );
+ virtual void parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* );
+
+ // non-overriding (locally added) methods
+
+ virtual void parseDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl );
+ virtual void parseFunctionDeclaration( GroupAST* funSpec, GroupAST* storageSpec, TypeSpecifierAST* typeSpec, InitDeclaratorAST* decl );
+ void parseFunctionArguments( DeclaratorAST* declarator, UMLOperation* method);
+ virtual void parseBaseClause( BaseClauseAST* baseClause, UMLClassifier* klass );
+
+private:
+ //NamespaceDom findOrInsertNamespace( NamespaceAST* ast, const QString& name );
+
+ QString typeOfDeclaration( TypeSpecifierAST* typeSpec, DeclaratorAST* declarator );
+ QStringList scopeOfName( NameAST* id, const QStringList& scope );
+ QStringList scopeOfDeclarator( DeclaratorAST* d, const QStringList& scope );
+ /**
+ * Flush template parameters pending in m_templateParams to the klass.
+ */
+ void flushTemplateParams(UMLClassifier *klass);
+
+private:
+ //FileDom m_file;
+ QString m_fileName;
+ QStringList m_currentScope;
+ Uml::Visibility m_currentAccess;
+ bool m_inSlots;
+ bool m_inSignals;
+ int m_anon;
+ bool m_inStorageSpec;
+ bool m_inTypedef;
+ QString m_comment;
+ Model_Utils::NameAndType_List m_templateParams;
+
+ DeclaratorAST* m_currentDeclarator;
+# define STACKSIZE 30
+ UMLPackage* m_currentNamespace[STACKSIZE+1]; ///< stack
+ UMLClassifier* m_currentClass[STACKSIZE+1]; ///< stack
+ int m_nsCnt; ///< stack top for m_currentNamespace
+ int m_clsCnt; ///< stack top for m_currentClass
+
+private:
+ CppTree2Uml( const CppTree2Uml& source );
+ void operator = ( const CppTree2Uml& source );
+};
+
+#endif // CPPTREE2UML
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp b/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp
new file mode 100644
index 00000000..84941025
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/driver.cpp
@@ -0,0 +1,435 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "driver.h"
+#include "lexer.h"
+#include "parser.h"
+#include <kdebug.h>
+#include <stdlib.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+
+class DefaultSourceProvider: public SourceProvider
+{
+public:
+ DefaultSourceProvider() {}
+
+ virtual QString contents( const QString& fileName )
+ {
+ QString source;
+
+ QFile f( fileName );
+ if( f.open(IO_ReadOnly) ){
+ QTextStream s( &f );
+ source = s.read();
+ f.close();
+ }
+ return source;
+ }
+
+ virtual bool isModified( const QString& fileName )
+ {
+ Q_UNUSED( fileName );
+ return true;
+ }
+
+private:
+ DefaultSourceProvider( const DefaultSourceProvider& source );
+ void operator = ( const DefaultSourceProvider& source );
+};
+
+
+Driver::Driver()
+ : depresolv( false ), lexer( 0 )
+{
+ m_sourceProvider = new DefaultSourceProvider();
+}
+
+Driver::~Driver()
+{
+ reset();
+ delete( m_sourceProvider );
+}
+
+SourceProvider* Driver::sourceProvider()
+{
+ return m_sourceProvider;
+}
+
+void Driver::setSourceProvider( SourceProvider* sourceProvider )
+{
+ if( m_sourceProvider )
+ delete( m_sourceProvider );
+ m_sourceProvider = sourceProvider;
+}
+
+void Driver::reset( )
+{
+ m_dependences.clear();
+ m_macros.clear();
+ m_problems.clear();
+ m_includePaths.clear();
+
+ while( m_parsedUnits.size() ){
+ TranslationUnitAST* unit = *m_parsedUnits.begin();
+ m_parsedUnits.remove( m_parsedUnits.begin() );
+ delete( unit );
+ }
+}
+
+void Driver::remove( const QString & fileName )
+{
+ m_dependences.remove( fileName );
+ m_problems.remove( fileName );
+ removeAllMacrosInFile( fileName );
+
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
+ if( it != m_parsedUnits.end() ){
+ TranslationUnitAST* unit = *it;
+ m_parsedUnits.remove( it );
+ delete( unit );
+ }
+}
+
+void Driver::removeAllMacrosInFile( const QString& fileName )
+{
+ QMap<QString, Macro>::Iterator it = m_macros.begin();
+ while( it != m_macros.end() ){
+ Macro m = *it++;
+ if( m.fileName() == fileName )
+ removeMacro( m.name() );
+ }
+}
+
+TranslationUnitAST::Node Driver::takeTranslationUnit( const QString& fileName )
+{
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
+ TranslationUnitAST::Node unit( *it );
+ //m_parsedUnits.remove( it );
+ m_parsedUnits[ fileName] = 0;
+ return unit;
+}
+
+TranslationUnitAST* Driver::translationUnit( const QString& fileName ) const
+{
+ QMap<QString, TranslationUnitAST*>::ConstIterator it = m_parsedUnits.find( fileName );
+ return it != m_parsedUnits.end() ? *it : 0;
+}
+
+void Driver::addDependence( const QString & fileName, const Dependence & dep )
+{
+ QFileInfo fileInfo( dep.first );
+ QString fn = fileInfo.absFilePath();
+
+ if ( !depresolv ){
+ findOrInsertDependenceList( fileName ).insert( fn, dep );
+ return;
+ }
+
+ QString file = findIncludeFile( dep );
+ findOrInsertDependenceList( fileName ).insert( file, dep );
+
+ if ( m_parsedUnits.find(file) != m_parsedUnits.end() )
+ return;
+
+ if ( !QFile::exists( file ) ) {
+ Problem p( "Couldn't find include file " + dep.first,
+ lexer ? lexer->currentLine() : -1,
+ lexer ? lexer->currentColumn() : -1 );
+ addProblem( fileName, p );
+ return;
+ }
+
+ QString cfn = m_currentFileName;
+ Lexer *l = lexer;
+ parseFile( file );
+ m_currentFileName = cfn;
+ lexer = l;
+}
+
+void Driver::addMacro( const Macro & macro )
+{
+ m_macros.insert( macro.name(), macro );
+}
+
+void Driver::addProblem( const QString & fileName, const Problem & problem )
+{
+ findOrInsertProblemList( fileName ).append( problem );
+}
+
+QMap< QString, Dependence >& Driver::findOrInsertDependenceList( const QString & fileName )
+{
+ QMap<QString, QMap<QString, Dependence> >::Iterator it = m_dependences.find( fileName );
+ if( it != m_dependences.end() )
+ return it.data();
+
+ QMap<QString, Dependence> l;
+ m_dependences.insert( fileName, l );
+ return m_dependences[ fileName ];
+}
+
+QValueList < Problem >& Driver::findOrInsertProblemList( const QString & fileName )
+{
+ QMap<QString, QValueList<Problem> >::Iterator it = m_problems.find( fileName );
+ if( it != m_problems.end() )
+ return it.data();
+
+ QValueList<Problem> l;
+ m_problems.insert( fileName, l );
+ return m_problems[ fileName ];
+}
+
+QMap< QString, Dependence > Driver::dependences( const QString & fileName ) const
+{
+ QMap<QString, QMap<QString, Dependence> >::ConstIterator it = m_dependences.find( fileName );
+ if( it != m_dependences.end() )
+ return it.data();
+ return QMap<QString, Dependence>();
+}
+
+QMap< QString, Macro > Driver::macros() const
+{
+ return m_macros;
+}
+
+QValueList < Problem > Driver::problems( const QString & fileName ) const
+{
+ QMap<QString, QValueList<Problem> >::ConstIterator it = m_problems.find( fileName );
+ if( it != m_problems.end() )
+ return it.data();
+ return QValueList<Problem>();
+}
+
+void Driver::parseFile( const QString& fileName, bool onlyPreProcess, bool force )
+{
+ QFileInfo fileInfo( fileName );
+ QString absFilePath = fileInfo.absFilePath();
+
+ QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( absFilePath );
+
+ if( force && it != m_parsedUnits.end() ){
+ takeTranslationUnit( absFilePath );
+ } else if( it != m_parsedUnits.end() && *it != 0 ){
+ // file already processed
+ return;
+ }
+
+ m_dependences.remove( fileName );
+ m_problems.remove( fileName );
+
+ m_currentFileName = fileName;
+
+ Lexer lex( this );
+ lexer = &lex;
+ setupLexer( &lex );
+
+ lex.setSource( sourceProvider()->contents(fileName) );
+
+ if( !onlyPreProcess ){
+ Parser parser( this, &lex );
+ setupParser( &parser );
+
+ TranslationUnitAST :: Node translationUnit;
+ parser.parseTranslationUnit( translationUnit );
+ m_parsedUnits.insert( fileName, translationUnit.release() );
+ fileParsed( fileName );
+ }
+
+ m_currentFileName = QString::null;
+ lexer = 0;
+}
+
+void Driver::setupLexer( Lexer * lexer )
+{
+ // stl
+ lexer->addSkipWord( "__STL_BEGIN_NAMESPACE" );
+ lexer->addSkipWord( "__STL_END_NAMESPACE" );
+ lexer->addSkipWord( "__STL_BEGIN_RELOPS_NAMESPACE" );
+ lexer->addSkipWord( "__STL_END_RELOPS_NAMESPACE" );
+ lexer->addSkipWord( "__STL_TEMPLATE_NULL" );
+ lexer->addSkipWord( "__STL_TRY" );
+ lexer->addSkipWord( "__STL_UNWIND" );
+ lexer->addSkipWord( "__STL_NOTHROW" );
+ lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
+ lexer->addSkipWord( "__STL_UNWIND", SkipWordAndArguments );
+ lexer->addSkipWord( "__GC_CONST" );
+ lexer->addSkipWord( "__HASH_ALLOC_INIT", SkipWordAndArguments );
+ lexer->addSkipWord( "__STL_DEFAULT_ALLOCATOR", SkipWordAndArguments, "T" );
+ lexer->addSkipWord( "__STL_MUTEX_INITIALIZER" );
+ lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
+
+ // antlr
+ lexer->addSkipWord( "ANTLR_BEGIN_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_USE_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_USING_NAMESPACE", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_END_NAMESPACE" );
+ lexer->addSkipWord( "ANTLR_C_USING", SkipWordAndArguments );
+ lexer->addSkipWord( "ANTLR_API" );
+
+ // gnu
+ lexer->addSkipWord( "__extension__", SkipWordAndArguments );
+ lexer->addSkipWord( "__attribute__", SkipWordAndArguments );
+ lexer->addSkipWord( "__BEGIN_DECLS" );
+ lexer->addSkipWord( "__END_DECLS" );
+ lexer->addSkipWord( "__THROW" );
+ lexer->addSkipWord( "__restrict" );
+ lexer->addSkipWord( "__restrict__" );
+ lexer->addSkipWord( "__attribute_pure__" );
+ lexer->addSkipWord( "__attribute_malloc__" );
+ lexer->addSkipWord( "__attribute_format_strfmon__" );
+ lexer->addSkipWord( "__asm__", SkipWordAndArguments );
+ lexer->addSkipWord( "__devinit" );
+ lexer->addSkipWord( "__devinit__" );
+ lexer->addSkipWord( "__init" );
+ lexer->addSkipWord( "__init__" );
+ lexer->addSkipWord( "__signed" );
+ lexer->addSkipWord( "__signed__" );
+ lexer->addSkipWord( "__unsigned" );
+ lexer->addSkipWord( "__unsigned__" );
+ lexer->addSkipWord( "asmlinkage" );
+ lexer->addSkipWord( "____cacheline_aligned" );
+ lexer->addSkipWord( "__glibcpp_class_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_class2_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_class4_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "__glibcpp_function_requires", SkipWordAndArguments );
+ lexer->addSkipWord( "restrict" );
+
+ lexer->addSkipWord( "__BEGIN_NAMESPACE_STD" );
+ lexer->addSkipWord( "__END_NAMESPACE_STD" );
+ lexer->addSkipWord( "__BEGIN_NAMESPACE_C99" );
+ lexer->addSkipWord( "__END_NAMESPACE_C99" );
+ lexer->addSkipWord( "__USING_NAMESPACE_STD", SkipWordAndArguments );
+
+ // kde
+ lexer->addSkipWord( "K_SYCOCATYPE", SkipWordAndArguments );
+ lexer->addSkipWord( "EXPORT_DOCKCLASS" );
+ lexer->addSkipWord( "K_EXPORT_COMPONENT_FACTORY", SkipWordAndArguments );
+ lexer->addSkipWord( "K_SYCOCAFACTORY", SkipWordAndArguments );
+ lexer->addSkipWord( "KDE_DEPRECATED" );
+
+ // qt
+ lexer->addSkipWord( "Q_OVERRIDE", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_ENUMS", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_PROPERTY", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_CLASSINFO", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_SETS", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_UNUSED", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_CREATE_INSTANCE", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_DUMMY_COMPARISON_OPERATOR", SkipWordAndArguments );
+ lexer->addSkipWord( "ACTIVATE_SIGNAL_WITH_PARAM", SkipWordAndArguments );
+ lexer->addSkipWord( "Q_INLINE_TEMPLATES" );
+ lexer->addSkipWord( "Q_TEMPLATE_EXTERN" );
+ lexer->addSkipWord( "Q_TYPENAME" );
+ lexer->addSkipWord( "Q_REFCOUNT" );
+ lexer->addSkipWord( "Q_EXPLICIT" );
+ lexer->addSkipWord( "QMAC_PASCAL" );
+ lexer->addSkipWord( "QT_STATIC_CONST" );
+ lexer->addSkipWord( "QT_STATIC_CONST_IMPL" );
+ lexer->addSkipWord( "QT_WIN_PAINTER_MEMBERS" );
+ lexer->addSkipWord( "QT_NC_MSGBOX" );
+ lexer->addSkipWord( "Q_VARIANT_AS", SkipWordAndArguments );
+ lexer->addSkipWord( "CALLBACK_CALL_TYPE" );
+
+ // flex
+ lexer->addSkipWord( "yyconst" );
+ lexer->addSkipWord( "YY_RULE_SETUP" );
+ lexer->addSkipWord( "YY_BREAK" );
+ lexer->addSkipWord( "YY_RESTORE_YY_MORE_OFFSET" );
+
+ // gtk
+ lexer->addSkipWord( "G_BEGIN_DECLS" );
+ lexer->addSkipWord( "G_END_DECLS" );
+ lexer->addSkipWord( "G_GNUC_CONST" );
+ lexer->addSkipWord( "G_CONST_RETURN" );
+ lexer->addSkipWord( "GTKMAIN_C_VAR" );
+ lexer->addSkipWord( "GTKVAR" );
+ lexer->addSkipWord( "GDKVAR" );
+ lexer->addSkipWord( "G_GNUC_PRINTF", SkipWordAndArguments );
+
+ // windows
+ lexer->addSkipWord( "WINAPI" );
+ lexer->addSkipWord( "__stdcall" );
+ lexer->addSkipWord( "__cdecl" );
+ lexer->addSkipWord( "_cdecl" );
+ lexer->addSkipWord( "CALLBACK" );
+
+ // gcc extensions
+ addMacro( Macro("__asm__", "asm") );
+ addMacro( Macro("__inline", "inline") );
+ addMacro( Macro("__inline__", "inline") );
+ addMacro( Macro("__const", "const") );
+ addMacro( Macro("__const__", "const") );
+ addMacro( Macro("__volatile__", "volatile") );
+ addMacro( Macro("__complex__", "") );
+}
+
+void Driver::setupParser( Parser * parser )
+{
+ Q_UNUSED( parser );
+}
+
+void Driver::removeMacro( const QString& macroName )
+{
+ m_macros.remove( macroName );
+}
+
+void Driver::addIncludePath( const QString &path )
+{
+ if( !path.stripWhiteSpace().isEmpty() )
+ m_includePaths << path;
+}
+
+QString Driver::findIncludeFile( const Dependence& dep ) const
+{
+ QString fileName = dep.first;
+
+ if( dep.second == Dep_Local ){
+ QString path = QFileInfo( currentFileName() ).dirPath( true );
+ QFileInfo fileInfo( QFileInfo(path, fileName) );
+ if ( fileInfo.exists() && fileInfo.isFile() )
+ return fileInfo.absFilePath();
+
+ }
+
+ QStringList::ConstIterator end(m_includePaths.end());
+ for ( QStringList::ConstIterator it(m_includePaths.begin()); it != end; ++it ) {
+ QFileInfo fileInfo( *it, fileName );
+ if ( fileInfo.exists() && fileInfo.isFile() )
+ return fileInfo.absFilePath();
+ }
+
+ return QString::null;
+}
+
+void Driver::setResolveDependencesEnabled( bool enabled )
+{
+ depresolv = enabled;
+ if ( depresolv )
+ setupPreProcessor();
+}
+
+void Driver::setupPreProcessor()
+{
+}
+
+void Driver::fileParsed( const QString & fileName )
+{
+ Q_UNUSED( fileName );
+}
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/driver.h b/umbrello/umbrello/codeimport/kdevcppparser/driver.h
new file mode 100644
index 00000000..ecb603ab
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/driver.h
@@ -0,0 +1,230 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef DRIVER_H
+#define DRIVER_H
+
+#include "ast.h"
+
+#include <qpair.h>
+#include <qvaluestack.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+class Lexer;
+class Parser;
+
+class Problem
+{
+public:
+ enum
+ {
+ Level_Error = 0,
+ Level_Warning,
+ Level_Todo,
+ Level_Fixme
+ };
+
+public:
+ Problem() {}
+ Problem( const Problem& source )
+ : m_text( source.m_text ), m_line( source.m_line ),
+ m_column( source.m_column ), m_level( source.m_level ) {}
+ Problem( const QString& text, int line, int column, int level=Level_Error )
+ : m_text( text ), m_line( line ), m_column( column ), m_level(level) {}
+
+ Problem& operator = ( const Problem& source )
+ {
+ m_text = source.m_text;
+ m_line = source.m_line;
+ m_column = source.m_column;
+ m_level = source.m_level;
+ return( *this );
+ }
+
+ bool operator == ( const Problem& p ) const
+ {
+ return m_text == p.m_text && m_line == p.m_line && m_column == p.m_column && m_level == p.m_level;
+ }
+
+ QString text() const { return m_text; }
+ int line() const { return m_line; }
+ int column() const { return m_column; }
+ int level() const { return m_level; }
+
+private:
+ QString m_text;
+ int m_line;
+ int m_column;
+ int m_level;
+};
+
+enum
+{
+ Dep_Global,
+ Dep_Local
+};
+
+typedef QPair<QString, int> Dependence;
+
+class Macro
+{
+public:
+ typedef QString Argument;
+
+public:
+ Macro( bool hasArguments = false ): m_hasArguments( hasArguments ) {}
+ Macro( const QString &n, const QString &b ) : m_name( n ), m_body( b ), m_hasArguments( false ) {}
+
+ Macro( const Macro& source )
+ : m_name( source.m_name),
+ m_fileName( source.m_fileName ),
+ m_body( source.m_body ),
+ m_hasArguments( source.m_hasArguments ),
+ m_argumentList( source.m_argumentList ) {}
+
+ Macro& operator = ( const Macro& source )
+ {
+ m_name = source.m_name;
+ m_body = source.m_body;
+ m_fileName = source.m_fileName;
+ m_hasArguments = source.m_hasArguments;
+ m_argumentList = source.m_argumentList;
+ return *this;
+ }
+
+ bool operator == ( const Macro& source ) const
+ {
+ return
+ m_name == source.m_name &&
+ m_fileName == source.m_fileName &&
+ m_body == source.m_body &&
+ m_hasArguments == source.m_hasArguments &&
+ m_argumentList == source.m_argumentList;
+ }
+
+ QString name() const { return m_name; }
+ void setName( const QString& name ) { m_name = name; }
+
+ QString fileName() const { return m_fileName; }
+ void setFileName( const QString& fileName ) { m_fileName = fileName; }
+
+ QString body() const { return m_body; }
+ void setBody( const QString& body ) { m_body = body; }
+
+ bool hasArguments() const { return m_hasArguments; }
+ void setHasArguments( bool hasArguments ) { m_hasArguments = hasArguments; }
+ QValueList<Argument> argumentList() const { return m_argumentList; }
+
+ void clearArgumentList() { m_argumentList.clear(); m_hasArguments = false; }
+ void addArgument( const Argument& argument ) { m_argumentList << argument; }
+ void addArgumentList( const QValueList<Argument>& arguments ) { m_argumentList += arguments; }
+
+private:
+ QString m_name;
+ QString m_fileName;
+ QString m_body;
+ bool m_hasArguments;
+ QValueList<Argument> m_argumentList;
+};
+
+class SourceProvider
+{
+public:
+ SourceProvider() {}
+ virtual ~SourceProvider() {}
+
+ virtual QString contents( const QString& fileName ) = 0;
+ virtual bool isModified( const QString& fileName ) = 0;
+
+private:
+ SourceProvider( const SourceProvider& source );
+ void operator = ( const SourceProvider& source );
+};
+
+class Driver
+{
+public:
+ Driver();
+ virtual ~Driver();
+
+ SourceProvider* sourceProvider();
+ void setSourceProvider( SourceProvider* sourceProvider );
+
+ virtual void reset();
+
+ virtual void parseFile( const QString& fileName, bool onlyPreProcesss=false, bool force=false );
+ virtual void fileParsed( const QString& fileName );
+ virtual void remove( const QString& fileName );
+
+ virtual void addDependence( const QString& fileName, const Dependence& dep );
+ virtual void addMacro( const Macro& macro );
+ virtual void addProblem( const QString& fileName, const Problem& problem );
+
+
+ QString currentFileName() const { return m_currentFileName; }
+ TranslationUnitAST::Node takeTranslationUnit( const QString& fileName );
+ TranslationUnitAST* translationUnit( const QString& fileName ) const;
+ QMap<QString, Dependence> dependences( const QString& fileName ) const;
+ QMap<QString, Macro> macros() const;
+ QValueList<Problem> problems( const QString& fileName ) const;
+
+ bool hasMacro( const QString& name ) const { return m_macros.contains( name ); }
+ const Macro& macro( const QString& name ) const { return m_macros[ name ]; }
+ Macro& macro( const QString& name ) { return m_macros[ name ]; }
+
+ virtual void removeMacro( const QString& macroName );
+ virtual void removeAllMacrosInFile( const QString& fileName );
+
+ QStringList includePaths() const { return m_includePaths; }
+ virtual void addIncludePath( const QString &path );
+
+ /// @todo remove
+ const QMap<QString, TranslationUnitAST*> &parsedUnits() const { return m_parsedUnits; }
+
+ virtual void setResolveDependencesEnabled( bool enabled );
+ bool isResolveDependencesEnabled() const { return depresolv; }
+
+protected:
+ virtual void setupLexer( Lexer* lexer );
+ virtual void setupParser( Parser* parser );
+ virtual void setupPreProcessor();
+
+private:
+ QMap<QString, Dependence>& findOrInsertDependenceList( const QString& fileName );
+ QValueList<Problem>& findOrInsertProblemList( const QString& fileName );
+ QString findIncludeFile( const Dependence& dep ) const;
+
+private:
+ QString m_currentFileName;
+ QMap< QString, QMap<QString, Dependence> > m_dependences;
+ QMap<QString, Macro> m_macros;
+ QMap< QString, QValueList<Problem> > m_problems;
+ QMap<QString, TranslationUnitAST*> m_parsedUnits;
+ QStringList m_includePaths;
+ uint depresolv : 1;
+ Lexer *lexer;
+ SourceProvider* m_sourceProvider;
+
+private:
+ Driver( const Driver& source );
+ void operator = ( const Driver& source );
+};
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp b/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp
new file mode 100644
index 00000000..154301c6
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/errors.cpp
@@ -0,0 +1,25 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "errors.h"
+#include <klocale.h>
+
+QT_STATIC_CONST_IMPL Error& Errors::InternalError = Error( 1, -1, i18n("Internal Error") );
+QT_STATIC_CONST_IMPL Error& Errors::SyntaxError = Error( 2, -1, i18n("Syntax Error before '%1'") );
+QT_STATIC_CONST_IMPL Error& Errors::ParseError = Error( 3, -1, i18n("Parse Error before '%1'") );
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/errors.h b/umbrello/umbrello/codeimport/kdevcppparser/errors.h
new file mode 100644
index 00000000..f846533d
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/errors.h
@@ -0,0 +1,45 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+#include <qstring.h>
+
+
+struct Error{
+ int code;
+ int level;
+ QString text;
+
+ Error( int c, int l, const QString& s )
+ : code( c ), level( l ), text( s )
+ {}
+};
+
+class Errors{
+public:
+ QT_STATIC_CONST Error& InternalError;
+ QT_STATIC_CONST Error& SyntaxError;
+ QT_STATIC_CONST Error& ParseError;
+};
+
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h b/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h
new file mode 100644
index 00000000..5c276953
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/keywords.lut.h
@@ -0,0 +1,123 @@
+/* Automatically generated from keywords.table using /home/roberto/src/kdelibs/kjs/create_hash_table. DO NOT EDIT ! */
+
+
+static const struct HashEntry keywordEntries[] = {
+ { "template", Token_template, 0, 0, 0 },
+ { "emit", Token_emit, 0, 0, &keywordEntries[88] },
+ { "long", Token_long, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "void", Token_void, 0, 0, &keywordEntries[113] },
+ { 0, 0, 0, 0, 0 },
+ { "explicit", Token_explicit, 0, 0, &keywordEntries[100] },
+ { "enum", Token_enum, 0, 0, &keywordEntries[105] },
+ { 0, 0, 0, 0, 0 },
+ { "continue", Token_continue, 0, 0, &keywordEntries[99] },
+ { "k_dcop_signals", Token_k_dcop_signals, 0, 0, &keywordEntries[104] },
+ { "auto", Token_auto, 0, 0, &keywordEntries[91] },
+ { 0, 0, 0, 0, 0 },
+ { "Q_OBJECT", Token_Q_OBJECT, 0, 0, &keywordEntries[86] },
+ { "and_eq", Token_and_eq, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "operator", Token_operator, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "class", Token_class, 0, 0, &keywordEntries[90] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "while", Token_while, 0, 0, 0 },
+ { "k_dcop", Token_k_dcop, 0, 0, 0 },
+ { "compl", Token_compl, 0, 0, 0 },
+ { "bitand", Token_bitand, 0, 0, &keywordEntries[97] },
+ { "__int64", Token_int, 0, 0, &keywordEntries[89] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "bitor", Token_bitor, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "friend", Token_friend, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "signed", Token_signed, 0, 0, 0 },
+ { "double", Token_double, 0, 0, 0 },
+ { "K_DCOP", Token_K_DCOP, 0, 0, &keywordEntries[111] },
+ { "const", Token_const, 0, 0, &keywordEntries[92] },
+ { 0, 0, 0, 0, 0 },
+ { "inline", Token_inline, 0, 0, &keywordEntries[98] },
+ { 0, 0, 0, 0, 0 },
+ { "do", Token_do, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "const_cast", Token_const_cast, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "not_eq", Token_not_eq, 0, 0, &keywordEntries[102] },
+ { 0, 0, 0, 0, 0 },
+ { "static", Token_static, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "throw", Token_throw, 0, 0, 0 },
+ { "slots", Token_slots, 0, 0, &keywordEntries[87] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "static_cast", Token_static_cast, 0, 0, &keywordEntries[115] },
+ { "default", Token_default, 0, 0, &keywordEntries[95] },
+ { "sizeof", Token_sizeof, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "switch", Token_switch, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "mutable", Token_mutable, 0, 0, 0 },
+ { "dynamic_cast", Token_dynamic_cast, 0, 0, 0 },
+ { "extern", Token_extern, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "asm", Token_asm, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "signals", Token_signals, 0, 0, &keywordEntries[106] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "case", Token_case, 0, 0, 0 },
+ { "for", Token_for, 0, 0, 0 },
+ { "char", Token_char, 0, 0, &keywordEntries[101] },
+ { 0, 0, 0, 0, 0 },
+ { "export", Token_export, 0, 0, &keywordEntries[94] },
+ { "int", Token_int, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "private", Token_private, 0, 0, &keywordEntries[103] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "not", Token_not, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "else", Token_else, 0, 0, &keywordEntries[93] },
+ { 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0 },
+ { "bool", Token_bool, 0, 0, 0 },
+ { "catch", Token_catch, 0, 0, 0 },
+ { "__asm__", Token_asm, 0, 0, 0 },
+ { "and", Token_and, 0, 0, 0 },
+ { "break", Token_break, 0, 0, &keywordEntries[110] },
+ { "delete", Token_delete, 0, 0, 0 },
+ { "float", Token_float, 0, 0, &keywordEntries[96] },
+ { "goto", Token_goto, 0, 0, 0 },
+ { "if", Token_if, 0, 0, 0 },
+ { "namespace", Token_namespace, 0, 0, 0 },
+ { "new", Token_new, 0, 0, 0 },
+ { "or", Token_or, 0, 0, &keywordEntries[107] },
+ { "or_eq", Token_or_eq, 0, 0, 0 },
+ { "protected", Token_protected, 0, 0, 0 },
+ { "public", Token_public, 0, 0, &keywordEntries[109] },
+ { "register", Token_register, 0, 0, 0 },
+ { "reinterpret_cast", Token_reinterpret_cast, 0, 0, 0 },
+ { "return", Token_return, 0, 0, 0 },
+ { "short", Token_short, 0, 0, 0 },
+ { "struct", Token_struct, 0, 0, 0 },
+ { "this", Token_this, 0, 0, 0 },
+ { "try", Token_try, 0, 0, &keywordEntries[108] },
+ { "typedef", Token_typedef, 0, 0, 0 },
+ { "typeid", Token_typeid, 0, 0, 0 },
+ { "typename", Token_typename, 0, 0, 0 },
+ { "union", Token_union, 0, 0, 0 },
+ { "unsigned", Token_unsigned, 0, 0, &keywordEntries[112] },
+ { "using", Token_using, 0, 0, 0 },
+ { "virtual", Token_virtual, 0, 0, &keywordEntries[114] },
+ { "volatile", Token_volatile, 0, 0, 0 },
+ { "xor", Token_xor, 0, 0, 0 },
+ { "xor_eq", Token_xor_eq, 0, 0, 0 }
+};
+
+static const struct HashTable keyword = { 2, 116, keywordEntries, 86 };
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp b/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp
new file mode 100644
index 00000000..2748688f
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lexer.cpp
@@ -0,0 +1,1002 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "lexer.h"
+#include "lookup.h"
+#include "keywords.lut.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qregexp.h>
+#include <qmap.h>
+#include <qvaluelist.h>
+
+#if defined( KDEVELOP_BGPARSER )
+#include <qthread.h>
+
+class KDevTread: public QThread
+{
+public:
+ static void yield()
+ {
+ msleep( 0 );
+ }
+};
+
+inline void qthread_yield()
+{
+ KDevTread::yield();
+}
+
+#endif
+
+#define CREATE_TOKEN(type, start, len) Token( (type), (start), (len), m_source )
+#define ADD_TOKEN(tk) m_tokens.insert( m_size++, new Token(tk) );
+
+using namespace std;
+
+struct LexerData
+{
+ typedef QMap<QString, QString> Scope;
+ typedef QValueList<Scope> StaticChain;
+
+ StaticChain staticChain;
+
+ void beginScope()
+ {
+ Scope scope;
+ staticChain.push_front( scope );
+ }
+
+ void endScope()
+ {
+ staticChain.pop_front();
+ }
+
+ void bind( const QString& name, const QString& value )
+ {
+ Q_ASSERT( staticChain.size() > 0 );
+ staticChain.front().insert( name, value );
+ }
+
+ bool hasBind( const QString& name ) const
+ {
+ StaticChain::ConstIterator it = staticChain.begin();
+ while( it != staticChain.end() ){
+ const Scope& scope = *it;
+ ++it;
+
+ if( scope.contains(name) )
+ return true;
+ }
+
+ return false;
+ }
+
+ QString apply( const QString& name ) const
+ {
+ StaticChain::ConstIterator it = staticChain.begin();
+ while( it != staticChain.end() ){
+ const Scope& scope = *it;
+ ++it;
+
+ if( scope.contains(name) )
+ return scope[ name ];
+ }
+
+ return QString::null;
+ }
+
+};
+
+Lexer::Lexer( Driver* driver )
+ : d( new LexerData),
+ m_driver( driver ),
+ m_recordComments( false ),
+ m_recordWhiteSpaces( false ),
+ m_skipWordsEnabled( true ),
+ m_preprocessorEnabled( true ),
+ m_reportWarnings( false ),
+ m_reportMessages( false )
+{
+ m_tokens.setAutoDelete( true );
+ reset();
+ d->beginScope();
+}
+
+Lexer::~Lexer()
+{
+ d->endScope();
+ delete( d );
+}
+
+void Lexer::setSource( const QString& source )
+{
+ reset();
+ m_source = source;
+ m_ptr = 0;
+ m_endPtr = m_source.length();
+ m_inPreproc = false;
+
+ tokenize();
+}
+
+void Lexer::reset()
+{
+ m_index = 0;
+ m_size = 0;
+ m_tokens.clear();
+ m_source = QString::null;
+ m_ptr = 0;
+ m_endPtr = 0;
+ m_startLine = false;
+ m_ifLevel = 0;
+ m_skipping.resize( 200 );
+ m_skipping.fill( 0 );
+ m_trueTest.resize( 200 );
+ m_trueTest.fill( 0 );
+
+ m_currentLine = 0;
+ m_currentColumn = 0;
+}
+
+// ### should all be done with a "long" type IMO
+int Lexer::toInt( const Token& token )
+{
+ QString s = token.text();
+ if( token.type() == Token_number_literal ){
+ // hex literal ?
+ if( s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ return s.mid( 2 ).toInt( 0, 16 );
+ QString n;
+ int i = 0;
+ while( i < int(s.length()) && s[i].isDigit() )
+ n += s[i++];
+ // ### respect more prefixes and suffixes ?
+ return n.toInt();
+ } else if( token.type() == Token_char_literal ){
+ int i = s[0] == 'L' ? 2 : 1; // wide char ?
+ if( s[i] == '\\' ){
+ // escaped char
+ int c = s[i+1].unicode();
+ switch( c ) {
+ case '0':
+ return 0;
+ case 'n':
+ return '\n';
+ // ### more
+ default:
+ return c;
+ }
+ } else {
+ return s[i].unicode();
+ }
+ } else {
+ return 0;
+ }
+}
+
+void Lexer::getTokenPosition( const Token& token, int* line, int* col )
+{
+ token.getStartPosition( line, col );
+}
+
+void Lexer::nextToken( Token& tk, bool stopOnNewline )
+{
+ int op = 0;
+
+ if( m_size == (int)m_tokens.size() ){
+ m_tokens.resize( m_tokens.size() + 5000 );
+ }
+
+ readWhiteSpaces( !stopOnNewline );
+
+ int startLine = m_currentLine;
+ int startColumn = m_currentColumn;
+
+ QChar ch = currentChar();
+ QChar ch1 = peekChar();
+
+ if( ch.isNull() || ch.isSpace() ){
+ /* skip */
+ } else if( m_startLine && ch == '#' ){
+
+ nextChar(); // skip #
+ readWhiteSpaces( false ); // skip white spaces
+ m_startLine = false;
+
+ int start = currentPosition();
+ readIdentifier(); // read the directive
+ QString directive = m_source.mid( start, currentPosition() - start );
+
+ handleDirective( directive );
+ } else if( m_startLine && m_skipping[ m_ifLevel ] ){
+ // skip line and continue
+ m_startLine = false;
+ int ppe = preprocessorEnabled();
+ setPreprocessorEnabled( false );
+ while( currentChar() && currentChar() != '\n' ){
+ Token tok;
+ nextToken( tok, true );
+ }
+ m_startLine = true;
+ setPreprocessorEnabled( ppe );
+ return;
+ } else if( ch == '/' && ch1 == '/' ){
+ int start = currentPosition();
+ readLineComment();
+ if( recordComments() ){
+ tk = CREATE_TOKEN( Token_comment, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch == '/' && ch1 == '*' ){
+ int start = currentPosition();
+ nextChar( 2 );
+ readMultiLineComment();
+
+ if( recordComments() ){
+ tk = CREATE_TOKEN( Token_comment, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch == '\'' || (ch == 'L' && ch1 == '\'') ){
+ int start = currentPosition();
+ readCharLiteral();
+ tk = CREATE_TOKEN( Token_char_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( ch == '"' ){
+ int start = currentPosition();
+ readStringLiteral();
+ tk = CREATE_TOKEN( Token_string_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( ch.isLetter() || ch == '_' ){
+ int start = currentPosition();
+ readIdentifier();
+ QString ide = m_source.mid( start, currentPosition() - start );
+ int k = Lookup::find( &keyword, ide );
+ if( m_preprocessorEnabled && m_driver->hasMacro(ide) &&
+ (k == -1 || !m_driver->macro(ide).body().isEmpty()) ){
+
+
+ bool preproc = m_preprocessorEnabled;
+ m_preprocessorEnabled = false;
+
+ d->beginScope();
+
+ int svLine = currentLine();
+ int svColumn = currentColumn();
+
+// Macro& m = m_driver->macro( ide );
+ Macro m = m_driver->macro( ide );
+ //m_driver->removeMacro( m.name() );
+
+ QString ellipsisArg;
+
+ if( m.hasArguments() ){
+ int endIde = currentPosition();
+
+ readWhiteSpaces();
+ if( currentChar() == '(' ){
+ nextChar();
+ int argIdx = 0;
+ int argCount = m.argumentList().size();
+ while( currentChar() && argIdx<argCount ){
+ readWhiteSpaces();
+
+ QString argName = m.argumentList()[ argIdx ];
+
+ bool ellipsis = argName == "...";
+
+ QString arg = readArgument();
+
+ if( !ellipsis )
+ d->bind( argName, arg );
+ else
+ ellipsisArg += arg;
+
+ if( currentChar() == ',' ){
+ nextChar();
+ if( !ellipsis ){
+ ++argIdx;
+ } else {
+ ellipsisArg += ", ";
+ }
+ } else if( currentChar() == ')' ){
+ break;
+ }
+ }
+ if( currentChar() == ')' ){
+ // valid macro
+ nextChar();
+ }
+ } else {
+ tk = CREATE_TOKEN( Token_identifier, start, endIde - start );
+ tk.setStartPosition( svLine, svColumn );
+ tk.setEndPosition( svLine, svColumn + (endIde - start) );
+
+ m_startLine = false;
+
+ d->endScope(); // OPS!!
+ m_preprocessorEnabled = preproc;
+ return;
+ }
+ }
+
+ int argsEndAtLine = currentLine();
+ int argsEndAtColumn = currentColumn();
+
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), m.body() );
+
+ // tokenize the macro body
+
+ QString textToInsert;
+
+ m_endPtr = currentPosition() + m.body().length();
+ while( currentChar() ){
+
+ readWhiteSpaces();
+
+ Token tok;
+ nextToken( tok );
+
+ bool stringify = !m_inPreproc && tok == '#';
+ bool merge = !m_inPreproc && tok == Token_concat;
+
+ if( stringify || merge )
+ nextToken( tok );
+
+ if( tok == Token_eof )
+ break;
+
+ QString tokText = tok.text();
+ QString str = (tok == Token_identifier && d->hasBind(tokText)) ? d->apply( tokText ) : tokText;
+ if( str == ide ){
+ //Problem p( i18n("unsafe use of macro '%1'").arg(ide), m_currentLine, m_currentColumn );
+ //m_driver->addProblem( m_driver->currentFileName(), p );
+ m_driver->removeMacro( ide );
+ // str = QString::null;
+ }
+
+ if( stringify ) {
+ textToInsert.append( QString::fromLatin1("\"") + str + QString::fromLatin1("\" ") );
+ } else if( merge ){
+ textToInsert.truncate( textToInsert.length() - 1 );
+ textToInsert.append( str );
+ } else if( tok == Token_ellipsis && d->hasBind("...") ){
+ textToInsert.append( ellipsisArg );
+ } else {
+ textToInsert.append( str + QString::fromLatin1(" ") );
+ }
+ }
+
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), textToInsert );
+
+ d->endScope();
+ m_preprocessorEnabled = preproc;
+ //m_driver->addMacro( m );
+ m_currentLine = argsEndAtLine;
+ m_currentColumn = argsEndAtColumn;
+ m_endPtr = m_source.length();
+ } else if( k != -1 ){
+ tk = CREATE_TOKEN( k, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( m_skipWordsEnabled ){
+ QMap< QString, QPair<SkipType, QString> >::Iterator pos = m_words.find( ide );
+ if( pos != m_words.end() ){
+ if( (*pos).first == SkipWordAndArguments ){
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ }
+ if( !(*pos).second.isEmpty() ){
+#if defined( KDEVELOP_BGPARSER )
+ qthread_yield();
+#endif
+ m_source.insert( currentPosition(), QString(" ") + (*pos).second + QString(" ") );
+ m_endPtr = m_source.length();
+ }
+ } else if( /*qt_rx.exactMatch(ide) ||*/
+ ide.endsWith("EXPORT") ||
+ (ide.startsWith("Q_EXPORT") && ide != "Q_EXPORT_INTERFACE") ||
+ ide.startsWith("QM_EXPORT") ||
+ ide.startsWith("QM_TEMPLATE")){
+
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ } else if( ide.startsWith("K_TYPELIST_") || ide.startsWith("TYPELIST_") ){
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ readWhiteSpaces();
+ if( currentChar() == '(' )
+ skip( '(', ')' );
+ } else{
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else {
+ tk = CREATE_TOKEN( Token_identifier, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+ } else if( ch.isNumber() ){
+ int start = currentPosition();
+ readNumberLiteral();
+ tk = CREATE_TOKEN( Token_number_literal, start, currentPosition() - start );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( -1 != (op = findOperator3()) ){
+ tk = CREATE_TOKEN( op, currentPosition(), 3 );
+ nextChar( 3 );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else if( -1 != (op = findOperator2()) ){
+ tk = CREATE_TOKEN( op, currentPosition(), 2 );
+ nextChar( 2 );
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ } else {
+ tk = CREATE_TOKEN( ch.unicode(), currentPosition(), 1 );
+ nextChar();
+ tk.setStartPosition( startLine, startColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ }
+
+ m_startLine = false;
+}
+
+
+void Lexer::tokenize()
+{
+ m_startLine = true;
+ m_size = 0;
+
+ for( ;; ) {
+ Token tk;
+ nextToken( tk );
+
+ if( tk.type() != -1 )
+ ADD_TOKEN( tk );
+
+ if( currentChar().isNull() )
+ break;
+ }
+
+ Token tk = CREATE_TOKEN( Token_eof, currentPosition(), 0 );
+ tk.setStartPosition( m_currentLine, m_currentColumn );
+ tk.setEndPosition( m_currentLine, m_currentColumn );
+ ADD_TOKEN( tk );
+}
+
+void Lexer::resetSkipWords()
+{
+ m_words.clear();
+}
+
+void Lexer::addSkipWord( const QString& word, SkipType skipType, const QString& str )
+{
+ m_words[ word ] = qMakePair( skipType, str );
+}
+
+void Lexer::skip( int l, int r )
+{
+ int svCurrentLine = m_currentLine;
+ int svCurrentColumn = m_currentColumn;
+
+ int count = 0;
+
+ while( !eof() ){
+ Token tk;
+ nextToken( tk );
+
+ if( (int)tk == l )
+ ++count;
+ else if( (int)tk == r )
+ --count;
+
+ if( count == 0 )
+ break;
+ }
+
+ m_currentLine = svCurrentLine;
+ m_currentColumn = svCurrentColumn;
+}
+
+QString Lexer::readArgument()
+{
+ int count = 0;
+
+ QString arg;
+
+ readWhiteSpaces();
+ while( currentChar() ){
+
+ readWhiteSpaces();
+ QChar ch = currentChar();
+
+ if( ch.isNull() || (!count && (ch == ',' || ch == ')')) )
+ break;
+
+ Token tk;
+ nextToken( tk );
+
+ if( tk == '(' ){
+ ++count;
+ } else if( tk == ')' ){
+ --count;
+ }
+
+ if( tk != -1 )
+ arg += tk.text() + ' ';
+ }
+
+ return arg.stripWhiteSpace();
+}
+
+void Lexer::handleDirective( const QString& directive )
+{
+ m_inPreproc = true;
+
+ bool skip = skipWordsEnabled();
+ bool preproc = preprocessorEnabled();
+
+ setSkipWordsEnabled( false );
+ setPreprocessorEnabled( false );
+
+ if( directive == "define" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ Macro m;
+ processDefine( m );
+ }
+ } else if( directive == "else" ){
+ processElse();
+ } else if( directive == "elif" ){
+ processElif();
+ } else if( directive == "endif" ){
+ processEndif();
+ } else if( directive == "if" ){
+ processIf();
+ } else if( directive == "ifdef" ){
+ processIfdef();
+ } else if( directive == "ifndef" ){
+ processIfndef();
+ } else if( directive == "include" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ processInclude();
+ }
+ } else if( directive == "undef" ){
+ if( !m_skipping[ m_ifLevel ] ){
+ processUndef();
+ }
+ }
+
+ // skip line
+ while( currentChar() && currentChar() != '\n' ){
+ Token tk;
+ nextToken( tk, true );
+ }
+
+ setSkipWordsEnabled( skip );
+ setPreprocessorEnabled( preproc );
+
+ m_inPreproc = false;
+}
+
+int Lexer::testIfLevel()
+{
+ int rtn = !m_skipping[ m_ifLevel++ ];
+ m_skipping[ m_ifLevel ] = m_skipping[ m_ifLevel - 1 ];
+ return rtn;
+}
+
+int Lexer::macroDefined()
+{
+ readWhiteSpaces( false );
+ int startWord = currentPosition();
+ readIdentifier();
+ QString word = m_source.mid( startWord, currentPosition() - startWord );
+ bool r = m_driver->hasMacro( word );
+
+ return r;
+}
+
+void Lexer::processDefine( Macro& m )
+{
+ m.setFileName( m_driver->currentFileName() );
+ readWhiteSpaces( false );
+
+ int startMacroName = currentPosition();
+ readIdentifier();
+ QString macroName = m_source.mid( startMacroName, int(currentPosition()-startMacroName) );
+ m_driver->removeMacro( macroName );
+ m.setName( macroName );
+
+ if( currentChar() == '(' ){
+ m.setHasArguments( true );
+ nextChar();
+
+ readWhiteSpaces( false );
+
+ while( currentChar() && currentChar() != ')' ){
+ readWhiteSpaces( false );
+
+ int startArg = currentPosition();
+
+ if( currentChar() == '.' && peekChar() == '.' && peekChar(2) == '.' )
+ nextChar( 3 );
+ else
+ readIdentifier();
+
+ QString arg = m_source.mid( startArg, int(currentPosition()-startArg) );
+
+ m.addArgument( Macro::Argument(arg) );
+
+ readWhiteSpaces( false );
+ if( currentChar() != ',' )
+ break;
+
+ nextChar(); // skip ','
+ }
+
+ if( currentChar() == ')' )
+ nextChar(); // skip ')'
+ }
+
+ setPreprocessorEnabled( true );
+
+ QString body;
+ while( currentChar() && currentChar() != '\n' ){
+
+ if( currentChar().isSpace() ){
+ readWhiteSpaces( false );
+ body += ' ';
+ } else {
+
+ Token tk;
+ nextToken( tk, true );
+
+ if( tk.type() != -1 ){
+ QString s = tk.text();
+ body += s;
+ }
+ }
+ }
+
+ m.setBody( body );
+ m_driver->addMacro( m );
+}
+
+void Lexer::processElse()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ if( m_ifLevel > 0 && m_skipping[m_ifLevel-1] )
+ m_skipping[ m_ifLevel ] = m_skipping[ m_ifLevel - 1 ];
+ else
+ m_skipping[ m_ifLevel ] = m_trueTest[ m_ifLevel ];
+}
+
+void Lexer::processElif()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ if( !m_trueTest[m_ifLevel] ){
+ /// @todo implement the correct semantic for elif!!
+ bool inSkip = m_ifLevel > 0 && m_skipping[ m_ifLevel-1 ];
+ m_trueTest[ m_ifLevel ] = macroExpression() != 0;
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+ else
+ m_skipping[ m_ifLevel ] = true;
+}
+
+void Lexer::processEndif()
+{
+ if( m_ifLevel == 0 )
+ /// @todo report error
+ return;
+
+ m_skipping[ m_ifLevel ] = 0;
+ m_trueTest[ m_ifLevel-- ] = 0;
+}
+
+void Lexer::processIf()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ) {
+#if 0
+ int n;
+ if( (n = testDefined()) != 0 ) {
+ int isdef = macroDefined();
+ m_trueTest[ m_ifLevel ] = (n == 1 && isdef) || (n == -1 && !isdef);
+ } else
+#endif
+ m_trueTest[ m_ifLevel ] = macroExpression() != 0;
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processIfdef()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ){
+ m_trueTest[ m_ifLevel ] = macroDefined();
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processIfndef()
+{
+ bool inSkip = m_skipping[ m_ifLevel ];
+
+ if( testIfLevel() ){
+ m_trueTest[ m_ifLevel ] = !macroDefined();
+ m_skipping[ m_ifLevel ] = inSkip ? inSkip : !m_trueTest[ m_ifLevel ];
+ }
+}
+
+void Lexer::processInclude()
+{
+ if( m_skipping[m_ifLevel] )
+ return;
+
+ readWhiteSpaces( false );
+ if( currentChar() ){
+ QChar ch = currentChar();
+ if( ch == '"' || ch == '<' ){
+ nextChar();
+ QChar ch2 = ch == QChar('"') ? QChar('"') : QChar('>');
+
+ int startWord = currentPosition();
+ while( currentChar() && currentChar() != ch2 )
+ nextChar();
+ if( currentChar() ){
+ QString word = m_source.mid( startWord, int(currentPosition()-startWord) );
+ m_driver->addDependence( m_driver->currentFileName(),
+ Dependence(word, ch == '"' ? Dep_Local : Dep_Global) );
+ nextChar();
+ }
+ }
+ }
+}
+
+void Lexer::processUndef()
+{
+ readWhiteSpaces();
+ int startWord = currentPosition();
+ readIdentifier();
+ QString word = m_source.mid( startWord, currentPosition() - startWord );
+ m_driver->removeMacro( word );
+}
+
+int Lexer::macroPrimary()
+{
+ readWhiteSpaces( false );
+ int result = 0;
+ switch( currentChar().unicode() ) {
+ case '(':
+ nextChar();
+ result = macroExpression();
+ if( currentChar() != ')' ){
+ /// @todo report error
+ return 0;
+ }
+ nextChar();
+ return result;
+
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ QChar tk = currentChar();
+ nextChar();
+ int result = macroPrimary();
+ if( tk == '-' ) return -result;
+ else if( tk == '!' ) return !result;
+ else if( tk == '~' ) return ~result;
+ }
+ break;
+
+ default:
+ {
+ Token tk;
+ nextToken( tk, false );
+ switch( tk.type() ){
+ case Token_identifier:
+ if( tk.text() == "defined" ){
+ return macroPrimary();
+ }
+ /// @todo implement
+ return m_driver->hasMacro( tk.text() );
+ case Token_number_literal:
+ case Token_char_literal:
+ return toInt( tk );
+ default:
+ break;
+ } // end switch
+
+ } // end default
+
+ } // end switch
+
+ return 0;
+}
+
+int Lexer::macroMultiplyDivide()
+{
+ int result = macroPrimary();
+ int iresult, op;
+ for (;;) {
+ readWhiteSpaces( false );
+ if( currentChar() == '*' )
+ op = 0;
+ else if( currentChar() == '/' && !(peekChar() == '*' || peekChar() == '/') )
+ op = 1;
+ else if( currentChar() == '%' )
+ op = 2;
+ else
+ break;
+ nextChar();
+ iresult = macroPrimary();
+ result = op == 0 ? (result * iresult) :
+ op == 1 ? (iresult == 0 ? 0 : (result / iresult)) :
+ (iresult == 0 ? 0 : (result % iresult)) ;
+ }
+ return result;
+}
+
+int Lexer::macroAddSubtract()
+{
+ int result = macroMultiplyDivide();
+ int iresult, ad;
+ readWhiteSpaces( false );
+ while( currentChar() == '+' || currentChar() == '-') {
+ ad = currentChar() == '+';
+ nextChar();
+ iresult = macroMultiplyDivide();
+ result = ad ? (result+iresult) : (result-iresult);
+ }
+ return result;
+}
+
+int Lexer::macroRelational()
+{
+ int result = macroAddSubtract();
+ int iresult;
+ readWhiteSpaces( false );
+ while( currentChar() == '<' || currentChar() == '>') {
+ int lt = currentChar() == '<';
+ nextChar();
+ if( currentChar() == '=') {
+ nextChar();
+
+ iresult = macroAddSubtract();
+ result = lt ? (result <= iresult) : (result >= iresult);
+ }
+ else {
+ iresult = macroAddSubtract();
+ result = lt ? (result < iresult) : (result > iresult);
+ }
+ }
+
+ return result;
+}
+
+int Lexer::macroEquality()
+{
+ int result = macroRelational();
+ int iresult, eq;
+ readWhiteSpaces( false );
+ while ((currentChar() == '=' || currentChar() == '!') && peekChar() == '=') {
+ eq = currentChar() == '=';
+ nextChar( 2 );
+ iresult = macroRelational();
+ result = eq ? (result==iresult) : (result!=iresult);
+ }
+ return result;
+}
+
+int Lexer::macroBoolAnd()
+{
+ int result = macroEquality();
+ readWhiteSpaces( false );
+ while( currentChar() == '&' && peekChar() != '&') {
+ nextChar();
+ result &= macroEquality();
+ }
+ return result;
+}
+
+int Lexer::macroBoolXor()
+{
+ int result = macroBoolAnd();
+ readWhiteSpaces( false );
+ while( currentChar() == '^') {
+ nextChar();
+ result ^= macroBoolAnd();
+ }
+ return result;
+}
+
+int Lexer::macroBoolOr()
+{
+ int result = macroBoolXor();
+ readWhiteSpaces( false );
+ while( currentChar() == '|' && peekChar() != '|') {
+ nextChar();
+ result |= macroBoolXor();
+ }
+ return result;
+}
+
+int Lexer::macroLogicalAnd()
+{
+ int result = macroBoolOr();
+ readWhiteSpaces( false );
+ while( currentChar() == '&' && peekChar() == '&') {
+ nextChar( 2 );
+ int start = currentPosition();
+ result = macroBoolOr() && result;
+ QString s = m_source.mid( start, currentPosition() - start );
+ }
+ return result;
+}
+
+int Lexer::macroLogicalOr()
+{
+ int result = macroLogicalAnd();
+ readWhiteSpaces( false );
+ while( currentChar() == '|' && peekChar() == '|') {
+ nextChar( 2 );
+ result = macroLogicalAnd() || result;
+ }
+ return result;
+}
+
+int Lexer::macroExpression()
+{
+ readWhiteSpaces( false );
+ return macroLogicalOr();
+}
+
+// *IMPORTANT*
+// please, don't include lexer.moc here, because Lexer isn't a QObject class!!
+// if you have problem while recompiling try to remove cppsupport/.deps,
+// cppsupport/Makefile.in and rerun automake/autoconf
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lexer.h b/umbrello/umbrello/codeimport/kdevcppparser/lexer.h
new file mode 100644
index 00000000..cce951d4
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lexer.h
@@ -0,0 +1,791 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include "driver.h"
+
+#include <qstring.h>
+#include <qmap.h>
+#include <qvaluestack.h>
+#include <qpair.h>
+#include <qptrvector.h>
+
+enum Type {
+ Token_eof = 0,
+ Token_identifier = 1000,
+ Token_number_literal,
+ Token_char_literal,
+ Token_string_literal,
+ Token_whitespaces,
+ Token_comment,
+ Token_preproc,
+
+ Token_assign = 2000,
+ Token_ptrmem,
+ Token_ellipsis,
+ Token_scope,
+ Token_shift,
+ Token_eq,
+ Token_leq,
+ Token_geq,
+ Token_incr,
+ Token_decr,
+ Token_arrow,
+
+ Token_concat,
+
+ Token_K_DCOP,
+ Token_k_dcop,
+ Token_k_dcop_signals,
+
+ Token_Q_OBJECT,
+ Token_signals,
+ Token_slots,
+ Token_emit,
+
+ Token_and,
+ Token_and_eq,
+ Token_asm,
+ Token_auto,
+ Token_bitand,
+ Token_bitor,
+ Token_bool,
+ Token_break,
+ Token_case,
+ Token_catch,
+ Token_char,
+ Token_class,
+ Token_compl,
+ Token_const,
+ Token_const_cast,
+ Token_continue,
+ Token_default,
+ Token_delete,
+ Token_do,
+ Token_double,
+ Token_dynamic_cast,
+ Token_else,
+ Token_enum,
+ Token_explicit,
+ Token_export,
+ Token_extern,
+ Token_false,
+ Token_float,
+ Token_for,
+ Token_friend,
+ Token_goto,
+ Token_if,
+ Token_inline,
+ Token_int,
+ Token_long,
+ Token_mutable,
+ Token_namespace,
+ Token_new,
+ Token_not,
+ Token_not_eq,
+ Token_operator,
+ Token_or,
+ Token_or_eq,
+ Token_private,
+ Token_protected,
+ Token_public,
+ Token_register,
+ Token_reinterpret_cast,
+ Token_return,
+ Token_short,
+ Token_signed,
+ Token_sizeof,
+ Token_static,
+ Token_static_cast,
+ Token_struct,
+ Token_switch,
+ Token_template,
+ Token_this,
+ Token_throw,
+ Token_true,
+ Token_try,
+ Token_typedef,
+ Token_typeid,
+ Token_typename,
+ Token_union,
+ Token_unsigned,
+ Token_using,
+ Token_virtual,
+ Token_void,
+ Token_volatile,
+ Token_wchar_t,
+ Token_while,
+ Token_xor,
+ Token_xor_eq
+};
+
+enum SkipType {
+ SkipWord,
+ SkipWordAndArguments
+};
+
+struct LexerData;
+
+class Token
+{
+public:
+ Token();
+ Token( int type, int position, int length, const QString& text );
+ Token( const Token& source );
+
+ Token& operator = ( const Token& source );
+ bool operator == ( const Token& token ) const;
+ operator int () const;
+
+ bool isNull() const;
+
+ int type() const;
+ void setType( int type );
+
+ void getStartPosition( int* line, int* column ) const;
+ void setStartPosition( int line, int column );
+ void getEndPosition( int* line, int* column ) const;
+ void setEndPosition( int line, int column );
+
+ unsigned int length() const;
+ void setLength( unsigned int length );
+
+ int position() const;
+ void setPosition( int position );
+
+ QString text() const;
+
+private:
+ int m_type;
+ int m_position;
+ int m_length;
+ int m_startLine;
+ int m_startColumn;
+ int m_endLine;
+ int m_endColumn;
+ QString m_text;
+
+ friend class Lexer;
+ friend class Parser;
+}; // class Token
+
+class Lexer
+{
+public:
+ Lexer( Driver* driver );
+ ~Lexer();
+
+ bool recordComments() const;
+ void setRecordComments( bool record );
+
+ bool recordWhiteSpaces() const;
+ void setRecordWhiteSpaces( bool record );
+
+ bool reportWarnings() const;
+ void setReportWarnings( bool enable );
+
+ bool reportMessages() const;
+ void setReportMessages( bool enable );
+
+ bool skipWordsEnabled() const;
+ void setSkipWordsEnabled( bool enabled );
+
+ bool preprocessorEnabled() const;
+ void setPreprocessorEnabled( bool enabled );
+
+ void resetSkipWords();
+ void addSkipWord( const QString& word, SkipType skipType=SkipWord, const QString& str = QString::null );
+
+ QString source() const;
+ void setSource( const QString& source );
+
+ int index() const;
+ void setIndex( int index );
+
+ void reset();
+
+ const Token& tokenAt( int position ) const;
+ const Token& nextToken();
+ const Token& lookAhead( int n ) const;
+
+ static int toInt( const Token& token );
+
+ int tokenPosition( const Token& token ) const;
+ void getTokenPosition( const Token& token, int* line, int* col );
+
+ int currentLine() const { return m_currentLine; }
+ int currentColumn() const { return m_currentColumn; }
+
+private:
+ QChar currentChar() const;
+ QChar peekChar( int n=1 ) const;
+ int currentPosition() const;
+
+ void tokenize();
+ void nextToken( Token& token, bool stopOnNewline=false );
+ void nextChar();
+ void nextChar( int n );
+ void skip( int l, int r );
+ void readIdentifier();
+ void readWhiteSpaces( bool skipNewLine=true );
+ void readLineComment();
+ void readMultiLineComment();
+ void readCharLiteral();
+ void readStringLiteral();
+ void readNumberLiteral();
+
+ int findOperator3() const;
+ int findOperator2() const;
+ bool eof() const;
+
+ // preprocessor (based on an article of Al Stevens on Dr.Dobb's journal)
+ int testIfLevel();
+ int macroDefined();
+ QString readArgument();
+
+ int macroPrimary();
+ int macroMultiplyDivide();
+ int macroAddSubtract();
+ int macroRelational();
+ int macroEquality();
+ int macroBoolAnd();
+ int macroBoolXor();
+ int macroBoolOr();
+ int macroLogicalAnd();
+ int macroLogicalOr();
+ int macroExpression();
+
+ void handleDirective( const QString& directive );
+ void processDefine( Macro& macro );
+ void processElse();
+ void processElif();
+ void processEndif();
+ void processIf();
+ void processIfdef();
+ void processIfndef();
+ void processInclude();
+ void processUndef();
+
+private:
+ LexerData* d;
+ Driver* m_driver;
+ QPtrVector< Token > m_tokens;
+ int m_size;
+ int m_index;
+ QString m_source;
+ int m_ptr;
+ int m_endPtr;
+ bool m_recordComments;
+ bool m_recordWhiteSpaces;
+ bool m_startLine;
+ QMap< QString, QPair<SkipType, QString> > m_words;
+
+ int m_currentLine;
+ int m_currentColumn;
+ bool m_skipWordsEnabled;
+
+ // preprocessor
+ QMemArray<bool> m_skipping;
+ QMemArray<bool> m_trueTest;
+ int m_ifLevel;
+ bool m_preprocessorEnabled;
+ bool m_inPreproc;
+
+ bool m_reportWarnings;
+ bool m_reportMessages;
+
+private:
+ Lexer( const Lexer& source );
+ void operator = ( const Lexer& source );
+};
+
+
+inline Token::Token()
+ : m_type( -1 ),
+ m_position( 0 ),
+ m_length( 0 ),
+ m_text( 0 )
+{
+}
+
+inline Token::Token( int type, int position, int length, const QString& text )
+ : m_type( type ),
+ m_position( position ),
+ m_length( length ),
+ m_text( text )
+{
+}
+
+inline Token::Token( const Token& source )
+ : m_type( source.m_type ),
+ m_position( source.m_position ),
+ m_length( source.m_length ),
+ m_startLine( source.m_startLine ),
+ m_startColumn( source.m_startColumn ),
+ m_endLine( source.m_endLine ),
+ m_endColumn( source.m_endColumn ),
+ m_text( source.m_text )
+{
+}
+
+inline Token& Token::operator = ( const Token& source )
+{
+ m_type = source.m_type;
+ m_position = source.m_position;
+ m_length = source.m_length;
+ m_startLine = source.m_startLine;
+ m_startColumn = source.m_startColumn;
+ m_endLine = source.m_endLine;
+ m_endColumn = source.m_endColumn;
+ m_text = source.m_text;
+ return( *this );
+}
+
+inline Token::operator int () const
+{
+ return m_type;
+}
+
+inline bool Token::operator == ( const Token& token ) const
+{
+ return m_type == token.m_type &&
+ m_position == token.m_position &&
+ m_length == token.m_length &&
+ m_startLine == token.m_startLine &&
+ m_startColumn == token.m_startColumn &&
+ m_endLine == token.m_endLine &&
+ m_endColumn == token.m_endColumn &&
+ m_text == token.m_text;
+}
+
+inline bool Token::isNull() const
+{
+ return m_type == Token_eof || m_length == 0;
+}
+
+inline int Token::type() const
+{
+ return m_type;
+}
+
+inline void Token::setType( int type )
+{
+ m_type = type;
+}
+
+inline int Token::position() const
+{
+ return m_position;
+}
+
+inline QString Token::text() const
+{
+ return m_text.mid(m_position, m_length);
+}
+
+inline void Token::setStartPosition( int line, int column )
+{
+ m_startLine = line;
+ m_startColumn = column;
+}
+
+inline void Token::setEndPosition( int line, int column )
+{
+ m_endLine = line;
+ m_endColumn = column;
+}
+
+inline void Token::getStartPosition( int* line, int* column ) const
+{
+ if( line ) *line = m_startLine;
+ if( column ) *column = m_startColumn;
+}
+
+inline void Token::getEndPosition( int* line, int* column ) const
+{
+ if( line ) *line = m_endLine;
+ if( column ) *column = m_endColumn;
+}
+
+inline void Token::setPosition( int position )
+{
+ m_position = position;
+}
+
+inline unsigned int Token::length() const
+{
+ return m_length;
+}
+
+inline void Token::setLength( unsigned int length )
+{
+ m_length = length;
+}
+
+inline bool Lexer::recordComments() const
+{
+ return m_recordComments;
+}
+
+inline void Lexer::setRecordComments( bool record )
+{
+ m_recordComments = record;
+}
+
+inline bool Lexer::recordWhiteSpaces() const
+{
+ return m_recordWhiteSpaces;
+}
+
+inline void Lexer::setRecordWhiteSpaces( bool record )
+{
+ m_recordWhiteSpaces = record;
+}
+
+inline QString Lexer::source() const
+{
+ return m_source;
+}
+
+inline int Lexer::index() const
+{
+ return m_index;
+}
+
+inline void Lexer::setIndex( int index )
+{
+ m_index = index;
+}
+
+inline const Token& Lexer::nextToken()
+{
+ if( m_index < m_size )
+ return *m_tokens[ m_index++ ];
+
+ return *m_tokens[ m_index ];
+}
+
+inline const Token& Lexer::tokenAt( int n ) const
+{
+ return *m_tokens[ QMIN(n, m_size-1) ];
+}
+
+inline const Token& Lexer::lookAhead( int n ) const
+{
+ return *m_tokens[ QMIN(m_index + n, m_size-1) ];
+}
+
+inline int Lexer::tokenPosition( const Token& token ) const
+{
+ return token.position();
+}
+
+inline void Lexer::nextChar()
+{
+ if(m_source[m_ptr++] == '\n') {
+ ++m_currentLine;
+ m_currentColumn = 0;
+ m_startLine = true;
+ } else {
+ ++m_currentColumn;
+ }
+}
+
+inline void Lexer::nextChar( int n )
+{
+ m_currentColumn += n;
+ m_ptr += n;
+}
+
+inline void Lexer::readIdentifier()
+{
+ while( currentChar().isLetterOrNumber() || currentChar() == '_' )
+ nextChar();
+}
+
+inline void Lexer::readWhiteSpaces( bool skipNewLine )
+{
+ while( !currentChar().isNull() ){
+ QChar ch = currentChar();
+
+ if( ch == '\n' && !skipNewLine ){
+ break;
+ } else if( ch.isSpace() ){
+ nextChar();
+ } else if( m_inPreproc && currentChar() == '\\' ){
+ nextChar();
+ readWhiteSpaces( true );
+ } else {
+ break;
+ }
+ }
+}
+
+inline void Lexer::readLineComment()
+{
+ while( !currentChar().isNull() && currentChar() != '\n' ){
+ if( m_reportMessages && currentChar() == '@' && m_source.mid(currentPosition()+1, 4).lower() == "todo" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Todo) );
+ } else
+ if( m_reportMessages && m_source.mid(currentPosition(), 5).lower() == "fixme" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Fixme) );
+ } else
+ nextChar();
+ }
+}
+
+inline void Lexer::readMultiLineComment()
+{
+ while( !currentChar().isNull() ){
+ if( currentChar() == '*' && peekChar() == '/' ){
+ nextChar( 2 );
+ return;
+ } else if( m_reportMessages && currentChar() == '@' && m_source.mid(currentPosition()+1, 4).lower() == "todo" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Todo) );
+ } else
+ if( m_reportMessages && m_source.mid(currentPosition(), 5).lower() == "fixme" ){
+ nextChar( 5 );
+ QString msg;
+ int line = m_currentLine;
+ int col = m_currentColumn;
+
+ while( currentChar() ){
+ if( currentChar() == '*' && peekChar() == '/' )
+ break;
+ else if( currentChar() == '\n' )
+ break;
+
+ msg += currentChar();
+ nextChar();
+ }
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col, Problem::Level_Fixme) );
+ } else
+ nextChar();
+ }
+}
+
+inline void Lexer::readCharLiteral()
+{
+ if( currentChar() == '\'' )
+ nextChar(); // skip '
+ else if( currentChar() == 'L' && peekChar() == '\'' )
+ nextChar( 2 ); // slip L'
+ else
+ return;
+
+ while( !currentChar().isNull() ){
+ int len = m_endPtr - currentPosition();
+
+ if( len>=2 && (currentChar() == '\\' && peekChar() == '\'') ){
+ nextChar( 2 );
+ } else if( len>=2 && (currentChar() == '\\' && peekChar() == '\\') ){
+ nextChar( 2 );
+ } else if( currentChar() == '\'' ){
+ nextChar();
+ break;
+ } else {
+ nextChar();
+ }
+ }
+}
+
+inline void Lexer::readStringLiteral()
+{
+ if( currentChar() != '"' )
+ return;
+
+ nextChar(); // skip "
+
+ while( !currentChar().isNull() ){
+ int len = m_endPtr - m_ptr;
+
+ if( len>=2 && currentChar() == '\\' && peekChar() == '"' ){
+ nextChar( 2 );
+ } else if( len>=2 && currentChar() == '\\' && peekChar() == '\\' ){
+ nextChar( 2 );
+ } else if( currentChar() == '"' ){
+ nextChar();
+ break;
+ } else {
+ nextChar();
+ }
+ }
+}
+
+inline void Lexer::readNumberLiteral()
+{
+ while( currentChar().isLetterOrNumber() || currentChar() == '.' )
+ nextChar();
+}
+
+inline int Lexer::findOperator3() const
+{
+ int n = int(m_endPtr - m_ptr);
+
+ if( n >= 3){
+ QChar ch = currentChar(), ch1=peekChar(), ch2=peekChar(2);
+
+ if( ch == '<' && ch1 == '<' && ch2 == '=' ) return Token_assign;
+ else if( ch == '>' && ch1 == '>' && ch2 == '=' ) return Token_assign;
+ else if( ch == '-' && ch1 == '>' && ch2 == '*' ) return Token_ptrmem;
+ else if( ch == '.' && ch1 == '.' && ch2 == '.' ) return Token_ellipsis;
+ }
+
+ return -1;
+}
+
+inline int Lexer::findOperator2() const
+{
+ int n = int(m_endPtr - m_ptr);
+
+ if( n>=2 ){
+ QChar ch = currentChar(), ch1=peekChar();
+
+ if( ch == ':' && ch1 == ':' ) return Token_scope;
+ else if( ch == '.' && ch1 == '*' ) return Token_ptrmem;
+ else if( ch == '+' && ch1 == '=' ) return Token_assign;
+ else if( ch == '-' && ch1 == '=' ) return Token_assign;
+ else if( ch == '*' && ch1 == '=' ) return Token_assign;
+ else if( ch == '/' && ch1 == '=' ) return Token_assign;
+ else if( ch == '%' && ch1 == '=' ) return Token_assign;
+ else if( ch == '^' && ch1 == '=' ) return Token_assign;
+ else if( ch == '&' && ch1 == '=' ) return Token_assign;
+ else if( ch == '|' && ch1 == '=' ) return Token_assign;
+ else if( ch == '<' && ch1 == '<' ) return Token_shift;
+ else if( ch == '>' && ch1 == '>' ) return Token_shift;
+ else if( ch == '=' && ch1 == '=' ) return Token_eq;
+ else if( ch == '!' && ch1 == '=' ) return Token_eq;
+ else if( ch == '<' && ch1 == '=' ) return Token_leq;
+ else if( ch == '>' && ch1 == '=' ) return Token_geq;
+ else if( ch == '&' && ch1 == '&' ) return Token_and;
+ else if( ch == '|' && ch1 == '|' ) return Token_or;
+ else if( ch == '+' && ch1 == '+' ) return Token_incr;
+ else if( ch == '-' && ch1 == '-' ) return Token_decr;
+ else if( ch == '-' && ch1 == '>' ) return Token_arrow;
+ else if( ch == '#' && ch1 == '#' ) return Token_concat;
+ }
+
+ return -1;
+}
+
+inline bool Lexer::skipWordsEnabled() const
+{
+ return m_skipWordsEnabled;
+}
+
+inline void Lexer::setSkipWordsEnabled( bool enabled )
+{
+ m_skipWordsEnabled = enabled;
+}
+
+inline bool Lexer::preprocessorEnabled() const
+{
+ return m_preprocessorEnabled;
+}
+
+inline void Lexer::setPreprocessorEnabled( bool enabled )
+{
+ m_preprocessorEnabled = enabled;
+}
+
+inline int Lexer::currentPosition() const
+{
+ return m_ptr;
+}
+
+inline QChar Lexer::currentChar() const
+{
+ return m_ptr < m_endPtr ? m_source[m_ptr] : QChar::null;
+}
+
+inline QChar Lexer::peekChar( int n ) const
+{
+ return m_ptr+n < m_endPtr ? m_source[m_ptr + n] : QChar::null;
+}
+
+inline bool Lexer::eof() const
+{
+ return m_ptr >= m_endPtr;
+}
+
+inline bool Lexer::reportWarnings() const
+{
+ return m_reportWarnings;
+}
+
+inline void Lexer::setReportWarnings( bool enable )
+{
+ m_reportWarnings = enable;
+}
+
+inline bool Lexer::reportMessages() const
+{
+ return m_reportMessages;
+}
+
+inline void Lexer::setReportMessages( bool enable )
+{
+ m_reportMessages = enable;
+}
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp b/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp
new file mode 100644
index 00000000..86299304
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lookup.cpp
@@ -0,0 +1,113 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+// adapted to kdevelop by Roberto Raggi <roberto@kdevelop.org>
+
+#include "lookup.h"
+
+#include <kdebug.h>
+
+#include <stdio.h>
+#include <string.h>
+
+const HashEntry* Lookup::findEntry( const struct HashTable *table,
+ const QChar *c, unsigned int len )
+{
+ if (table->type != 2) {
+ kdDebug() << "KJS: Unknown hash table version" << endl;
+ return 0;
+ }
+ char *ascii = new char[len+1];
+ unsigned int i;
+ for(i = 0; i < len; i++, c++) {
+ if (!c->row())
+ ascii[i] = c->cell();
+ else
+ break;
+ }
+ ascii[i] = '\0';
+
+ int h = hash(ascii) % table->hashSize;
+ const HashEntry *e = &table->entries[h];
+
+ // empty bucket ?
+ if (!e->s) {
+ delete [] ascii;
+ return 0;
+ }
+
+ do {
+ // compare strings
+ if (strcmp(ascii, e->s) == 0) {
+ delete [] ascii;
+ return e;
+ }
+ // try next bucket
+ e = e->next;
+ } while (e);
+
+ delete [] ascii;
+ return 0;
+}
+
+const HashEntry* Lookup::findEntry( const struct HashTable *table,
+ const QString &s )
+{
+ return findEntry( table, s.unicode(), s.length() );
+}
+
+int Lookup::find(const struct HashTable *table,
+ const QChar *c, unsigned int len)
+{
+ const HashEntry *entry = findEntry( table, c, len );
+ if (entry)
+ return entry->value;
+ return -1;
+}
+
+int Lookup::find(const struct HashTable *table, const QString &s)
+{
+ return find(table, s.unicode(), s.length());
+}
+
+unsigned int Lookup::hash(const QChar *c, unsigned int len)
+{
+ unsigned int val = 0;
+ // ignoring rower byte
+ for (unsigned int i = 0; i < len; i++, c++)
+ val += c->cell();
+
+ return val;
+}
+
+unsigned int Lookup::hash(const QString &key)
+{
+ return hash(key.unicode(), key.length());
+}
+
+unsigned int Lookup::hash(const char *s)
+{
+ unsigned int val = 0;
+ while (*s)
+ val += *s++;
+
+ return val;
+}
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/lookup.h b/umbrello/umbrello/codeimport/kdevcppparser/lookup.h
new file mode 100644
index 00000000..3e9c713c
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/lookup.h
@@ -0,0 +1,119 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+// adapted to kdevelop by Roberto Raggi <roberto@kdevelop.org>
+
+#ifndef _KJSLOOKUP_H_
+#define _KJSLOOKUP_H_
+
+#include <qstring.h>
+#include <stdio.h>
+
+ /**
+ * An entry in a hash table.
+ */
+ struct HashEntry {
+ /**
+ * s is the key (e.g. a property name)
+ */
+ const char *s;
+ /**
+ * value is the result value (usually an enum value)
+ */
+ int value;
+ /**
+ * attr is a set for flags (e.g. the property flags, see object.h)
+ */
+ short int attr;
+ /**
+ * params is another number. For property hashtables, it is used to
+ * denote the number of argument of the function
+ */
+ short int params;
+ /**
+ * next is the pointer to the next entry for the same hash value
+ */
+ const HashEntry *next;
+ };
+
+ /**
+ * A hash table
+ * Usually the hashtable is generated by the create_hash_table script, from a .table file.
+ *
+ * The implementation uses an array of entries, "size" is the total size of that array.
+ * The entries between 0 and hashSize-1 are the entry points
+ * for each hash value, and the entries between hashSize and size-1
+ * are the overflow entries for the hash values that need one.
+ * The "next" pointer of the entry links entry points to overflow entries,
+ * and links overflow entries between them.
+ */
+ struct HashTable {
+ /**
+ * type is a version number. Currently always 2
+ */
+ int type;
+ /**
+ * size is the total number of entries in the hashtable, including the null entries,
+ * i.e. the size of the "entries" array.
+ * Used to iterate over all entries in the table
+ */
+ int size;
+ /**
+ * pointer to the array of entries
+ * Mind that some entries in the array are null (0,0,0,0).
+ */
+ const HashEntry *entries;
+ /**
+ * the maximum value for the hash. Always smaller than size.
+ */
+ int hashSize;
+ };
+
+ /**
+ * @short Fast keyword lookup.
+ */
+ class Lookup {
+ public:
+ /**
+ * Find an entry in the table, and return its value (i.e. the value field of HashEntry)
+ */
+ static int find(const struct HashTable *table, const QString& s);
+ static int find(const struct HashTable *table, const QChar *c, unsigned int len);
+
+ /**
+ * Find an entry in the table, and return the entry
+ * This variant gives access to the other attributes of the entry,
+ * especially the attr field.
+ */
+ static const HashEntry* findEntry(const struct HashTable *table,
+ const QString &s);
+ static const HashEntry* findEntry(const struct HashTable *table,
+ const QChar *c, unsigned int len);
+
+ /**
+ * Calculate the hash value for a given key
+ */
+ static unsigned int hash(const QString &key);
+ static unsigned int hash(const QChar *c, unsigned int len);
+ static unsigned int hash(const char *s);
+ };
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp b/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp
new file mode 100644
index 00000000..0314a60c
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/parser.cpp
@@ -0,0 +1,4238 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+// c++ support
+#include "parser.h"
+#include "driver.h"
+#include "lexer.h"
+#include "errors.h"
+
+// qt
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qasciidict.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace std;
+
+#define ADVANCE(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \
+ return false; \
+ } \
+ lex->nextToken(); \
+}
+
+#define ADVANCE_NR(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( i18n("'%1' expected found '%2'").arg(descr).arg(token.text()) ); \
+ } \
+ else \
+ lex->nextToken(); \
+}
+
+#define CHECK(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ return false; \
+ } \
+ lex->nextToken(); \
+}
+
+#define MATCH(tk, descr) \
+{ \
+ const Token& token = lex->lookAhead( 0 ); \
+ if( token != tk ){ \
+ reportError( Errors::SyntaxError ); \
+ return false; \
+ } \
+}
+
+#define UPDATE_POS(node, start, end) \
+{ \
+ int line, col; \
+ const Token &a = lex->tokenAt(start); \
+ const Token &b = lex->tokenAt( end!=start ? end-1 : end ); \
+ a.getStartPosition( &line, &col ); \
+ (node)->setStartPosition( line, col ); \
+ b.getEndPosition( &line, &col ); \
+ (node)->setEndPosition( line, col ); \
+ if( (node)->nodeType() == NodeType_Generic ) { \
+ if ((start) == (end) || (end) == (start)+1) \
+ (node)->setSlice(lex->source(), a.position(), a.length()); \
+ else \
+ (node)->setText( toString((start),(end)) ); \
+ } \
+}
+
+#define AST_FROM_TOKEN(node, tk) \
+ AST::Node node = CreateNode<AST>(); \
+ UPDATE_POS( node, (tk), (tk)+1 );
+
+
+//@todo remove me
+enum
+{
+ OBJC_CLASS,
+ OBJC_PROTOCOL,
+ OBJC_ALIAS
+};
+
+struct ParserPrivateData
+{
+ ParserPrivateData()
+ {}
+};
+
+Parser::Parser( Driver* driver, Lexer* lexer )
+ : m_driver( driver ),
+ lex( lexer )
+{
+ d = new ParserPrivateData();
+
+ m_maxProblems = 5;
+ objcp = false;
+}
+
+Parser::~Parser()
+{
+ delete d;
+ d = 0;
+}
+
+bool Parser::reportError( const Error& err )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl;
+ if( m_problems < m_maxProblems ){
+ ++m_problems;
+ int line=0, col=0;
+ const Token& token = lex->lookAhead( 0 );
+ lex->getTokenPosition( token, &line, &col );
+
+ QString s = lex->lookAhead(0).text();
+ s = s.left( 30 ).stripWhiteSpace();
+ if( s.isEmpty() )
+ s = i18n( "<eof>" );
+
+ m_driver->addProblem( m_driver->currentFileName(), Problem(err.text.arg(s), line, col) );
+ }
+
+ return true;
+}
+
+bool Parser::reportError( const QString& msg )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::reportError()" << endl;
+ if( m_problems < m_maxProblems ){
+ ++m_problems;
+ int line=0, col=0;
+ const Token& token = lex->lookAhead( 0 );
+ lex->getTokenPosition( token, &line, &col );
+
+ m_driver->addProblem( m_driver->currentFileName(), Problem(msg, line, col) );
+ }
+
+ return true;
+}
+
+void Parser::syntaxError()
+{
+ (void) reportError( Errors::SyntaxError );
+}
+
+bool Parser::skipUntil( int token )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntil()" << endl;
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == token )
+ return true;
+
+ lex->nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilDeclaration()" << endl;
+
+ while( !lex->lookAhead(0).isNull() ){
+
+ switch( lex->lookAhead(0) ){
+ case ';':
+ case '~':
+ case Token_scope:
+ case Token_identifier:
+ case Token_operator:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_extern:
+ case Token_namespace:
+ case Token_using:
+ case Token_typedef:
+ case Token_asm:
+ case Token_template:
+ case Token_export:
+
+ case Token_const: // cv
+ case Token_volatile: // cv
+
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ case Token_signals: // Qt
+ case Token_slots: // Qt
+ return true;
+
+ case '}':
+ return false;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipUntilStatement() -- token = " << lex->lookAhead(0).text() << endl;
+
+ while( !lex->lookAhead(0).isNull() ){
+ switch( lex->lookAhead(0) ){
+ case ';':
+ case '{':
+ case '}':
+ case Token_const:
+ case Token_volatile:
+ case Token_identifier:
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_switch:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ case Token_try:
+ case Token_catch:
+ case Token_throw:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_class:
+ case Token_struct:
+ case Token_union:
+ case Token_enum:
+ case Token_scope:
+ case Token_template:
+ case Token_using:
+ return true;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip( int l, int r )
+{
+ int count = 0;
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ if( tk == l )
+ ++count;
+ else if( tk == r )
+ --count;
+ else if( l != '{' && (tk == '{' || tk == '}' || tk == ';') )
+ return false;
+
+ if( count == 0 )
+ return true;
+
+ lex->nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipCommaExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipCommaExpression()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !skipExpression(expr) )
+ return false;
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !skipExpression(expr) ){
+ reportError( i18n("expression expected") );
+ return false;
+ }
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::skipExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpression()" << endl;
+
+ int start = lex->index();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ switch( tk ){
+ case '(':
+ skip( '(', ')' );
+ lex->nextToken();
+ break;
+
+ case '[':
+ skip( '[', ']' );
+ lex->nextToken();
+ break;
+
+#if 0
+ case Token_identifier:
+ lex->nextToken();
+ if( lex->lookAhead( 0 ) == Token_identifier )
+ return true;
+ break;
+#endif
+
+ case ';':
+ case ',':
+ case ']':
+ case ')':
+ case '{':
+ case '}':
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ {
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ }
+ return true;
+
+ default:
+ lex->nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseName( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseName()" << endl;
+
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ int start = lex->index();
+
+ NameAST::Node ast = CreateNode<NameAST>();
+
+ if( lex->lookAhead(0) == Token_scope ){
+ ast->setGlobal( true );
+ lex->nextToken();
+ }
+
+ int idx = lex->index();
+
+ while( true ){
+ ClassOrNamespaceNameAST::Node n;
+ if( !parseUnqualifiedName(n) ) {
+ return false;
+ }
+
+ if( lex->lookAhead(0) == Token_scope ){
+ lex->nextToken();
+ ast->addClassOrNamespaceName( n );
+ if( lex->lookAhead(0) == Token_template )
+ lex->nextToken(); /// skip optional template #### @todo CHECK
+ } else {
+ ast->setUnqualifiedName( n );
+ break;
+ }
+ }
+
+ if( idx == lex->index() )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTranslationUnit( TranslationUnitAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTranslationUnit()" << endl;
+
+ int start = lex->index();
+
+ m_problems = 0;
+ TranslationUnitAST::Node tun = CreateNode<TranslationUnitAST>();
+ node = tun;
+ while( !lex->lookAhead(0).isNull() ){
+ DeclarationAST::Node def;
+ int startDecl = lex->index();
+ if( !parseDeclaration(def) ){
+ // error recovery
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ node->addDeclaration( def );
+ }
+
+ UPDATE_POS( node, start, lex->index() );
+
+ // force (0,0) as start position
+ node->setStartPosition( 0, 0 );
+
+ return m_problems == 0;
+}
+
+bool Parser::parseDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaration()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+ bool success = false;
+
+ switch( lex->lookAhead(0) ){
+
+ case ';':
+ lex->nextToken();
+ return true;
+
+ case Token_extern:
+ success = parseLinkageSpecification( node );
+ break;
+
+ case Token_namespace:
+ success = parseNamespace( node );
+ break;
+
+ case Token_using:
+ success = parseUsing( node );
+ break;
+
+ case Token_typedef:
+ success = parseTypedef( node );
+ break;
+
+ case Token_asm:
+ success = parseAsmDefinition( node );
+ break;
+
+ case Token_template:
+ case Token_export:
+ success = parseTemplateDeclaration( node );
+ break;
+
+ default:
+ {
+ // lex->setIndex( start );
+
+ if( objcp && parseObjcDef(node) )
+ return true;
+
+ lex->setIndex( start );
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ AST::Node declarator;
+ if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList(declarators);
+ ADVANCE( ';', ";" );
+
+ if( !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseDeclaration(spec): comment is " << comment << endl;
+ spec->setComment( comment );
+ }
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+
+ lex->setIndex( start );
+ success = parseDeclarationInternal( node, comment );
+ }
+
+ } // end switch
+
+ if( success && !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseDeclaration(): comment is " << comment << endl;
+ node->setComment( comment );
+ }
+ return success;
+}
+
+bool Parser::parseLinkageSpecification( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageSpecification()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_extern ){
+ return false;
+ }
+ lex->nextToken();
+
+ LinkageSpecificationAST::Node ast = CreateNode<LinkageSpecificationAST>();
+
+ int startExternType = lex->index();
+ if( lex->lookAhead(0) == Token_string_literal ){
+ lex->nextToken();
+ AST::Node externType = CreateNode<AST>();
+ UPDATE_POS( externType, startExternType, lex->index() );
+
+ ast->setExternType( externType );
+ }
+
+ if( lex->lookAhead(0) == '{' ){
+ LinkageBodyAST::Node linkageBody;
+ parseLinkageBody( linkageBody );
+ ast->setLinkageBody( linkageBody );
+ } else {
+ DeclarationAST::Node decl;
+ if( !parseDeclaration(decl) ){
+ reportError( i18n("Declaration syntax error") );
+ }
+ ast->setDeclaration( decl );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLinkageBody( LinkageBodyAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLinkageBody()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ LinkageBodyAST::Node lba = CreateNode<LinkageBodyAST>();
+ node = lba;
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+
+ if( tk == '}' )
+ break;
+
+ DeclarationAST::Node def;
+ int startDecl = lex->index();
+ if( parseDeclaration(def) ){
+ node->addDeclaration( def );
+ } else {
+ // error recovery
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+}
+
+bool Parser::parseNamespace( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNamespace()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_namespace ){
+ return false;
+ }
+ lex->nextToken();
+
+ int startNamespaceName = lex->index();
+ if( lex->lookAhead(0) == Token_identifier ){
+ lex->nextToken();
+ }
+ AST::Node namespaceName = CreateNode<AST>();
+ UPDATE_POS( namespaceName, startNamespaceName, lex->index() );
+
+ if ( lex->lookAhead(0) == '=' ) {
+ // namespace alias
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( parseName(name) ){
+ ADVANCE( ';', ";" );
+
+ NamespaceAliasAST::Node ast = CreateNode<NamespaceAliasAST>();
+ ast->setNamespaceName( namespaceName );
+ ast->setAliasName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ } else {
+ reportError( i18n("namespace expected") );
+ return false;
+ }
+ } else if( lex->lookAhead(0) != '{' ){
+ reportError( i18n("{ expected") );
+ return false;
+ }
+
+ NamespaceAST::Node ast = CreateNode<NamespaceAST>();
+ ast->setNamespaceName( namespaceName );
+
+ LinkageBodyAST::Node linkageBody;
+ parseLinkageBody( linkageBody );
+
+ ast->setLinkageBody( linkageBody );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsing( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsing()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_using ){
+ return false;
+ }
+ lex->nextToken();
+
+ if( lex->lookAhead(0) == Token_namespace ){
+ if( !parseUsingDirective(node) ){
+ return false;
+ }
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+
+ UsingAST::Node ast = CreateNode<UsingAST>();
+
+ int startTypeName = lex->index();
+ if( lex->lookAhead(0) == Token_typename ){
+ lex->nextToken();
+ AST::Node tn = CreateNode<AST>();
+ UPDATE_POS( tn, startTypeName, lex->index() );
+ ast->setTypeName( tn );
+ }
+
+ NameAST::Node name;
+ if( !parseName(name) )
+ return false;
+
+ ast->setName( name );
+
+ ADVANCE( ';', ";" );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsingDirective( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUsingDirective()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_namespace ){
+ return false;
+ }
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Namespace name expected") );
+ return false;
+ }
+
+ ADVANCE( ';', ";" );
+
+ UsingDirectiveAST::Node ast = CreateNode<UsingDirectiveAST>();
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseOperatorFunctionId( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperatorFunctionId()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_operator ){
+ return false;
+ }
+ lex->nextToken();
+
+ AST::Node op;
+ if( parseOperator(op) ){
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ } else {
+ // parse cast operator
+ GroupAST::Node cv;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST::Node spec;
+ if( !parseSimpleTypeSpecifier(spec) ){
+ syntaxError();
+ return false;
+ }
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify( cv2 );
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) )
+ ;
+
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+}
+
+bool Parser::parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgumentList()" << endl;
+
+ int start = lex->index();
+
+ TemplateArgumentListAST::Node ast = CreateNode<TemplateArgumentListAST>();
+
+ AST::Node templArg;
+ if( !parseTemplateArgument(templArg) )
+ return false;
+ ast->addArgument( templArg );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseTemplateArgument(templArg) ){
+ if( reportError ){
+ syntaxError();
+ break;
+ } else
+ return false;
+ }
+ if (!comment.isEmpty())
+ templArg->setComment(comment);
+ ast->addArgument( templArg );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypedef( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypedef()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_typedef ){
+ return false;
+ }
+ lex->nextToken();
+
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifierOrClassSpec(spec) ){
+ reportError( i18n("Need a type specifier to declare") );
+ return false;
+ }
+
+ InitDeclaratorListAST::Node declarators;
+ if( !parseInitDeclaratorList(declarators) ){
+ //reportError( i18n("Need an identifier to declare") );
+ //return false;
+ }
+
+ ADVANCE( ';', ";" );
+
+ TypedefAST::Node ast = CreateNode<TypedefAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAsmDefinition( DeclarationAST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAsmDefinition()" << endl;
+
+ ADVANCE( Token_asm, "asm" );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ skip( '(', ')' );
+ ADVANCE( ')', ")" );
+ ADVANCE( ';', ';' );
+
+ return true;
+}
+
+bool Parser::parseTemplateDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateDeclaration()" << endl;
+
+ int start = lex->index();
+
+ AST::Node exp;
+
+ int startExport = lex->index();
+ if( lex->lookAhead(0) == Token_export ){
+ lex->nextToken();
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startExport, lex->index() );
+ exp = n;
+ }
+
+ if( lex->lookAhead(0) != Token_template ){
+ return false;
+ }
+ lex->nextToken();
+
+ TemplateParameterListAST::Node params;
+ if( lex->lookAhead(0) == '<' ){
+ lex->nextToken();
+ if (lex->lookAhead(0) != '>')
+ parseTemplateParameterList( params );
+
+ ADVANCE( '>', ">" );
+ }
+
+ DeclarationAST::Node def;
+ if( !parseDeclaration(def) ){
+ reportError( i18n("expected a declaration") );
+ }
+
+ TemplateDeclarationAST::Node ast = CreateNode<TemplateDeclarationAST>();
+ ast->setExported( exp );
+ ast->setTemplateParameterList( params );
+ ast->setDeclaration( def );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseOperator( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseOperator()" << endl;
+ QString text = lex->lookAhead(0).text();
+
+ switch( lex->lookAhead(0) ){
+ case Token_new:
+ case Token_delete:
+ lex->nextToken();
+ if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){
+ lex->nextToken();
+ lex->nextToken();
+ text += "[]";
+ }
+ return true;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case '~':
+ case '!':
+ case '=':
+ case '<':
+ case '>':
+ case ',':
+ case Token_assign:
+ case Token_shift:
+ case Token_eq:
+ case Token_not_eq:
+ case Token_leq:
+ case Token_geq:
+ case Token_and:
+ case Token_or:
+ case Token_incr:
+ case Token_decr:
+ case Token_ptrmem:
+ case Token_arrow:
+ lex->nextToken();
+ return true;
+
+ default:
+ if( lex->lookAhead(0) == '(' && lex->lookAhead(1) == ')' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ } else if( lex->lookAhead(0) == '[' && lex->lookAhead(1) == ']' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseCvQualify( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCvQualify()" << endl;
+
+ int start = lex->index();
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ int n = 0;
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_const || tk == Token_volatile ){
+ ++n;
+ int startWord = lex->index();
+ lex->nextToken();
+ AST::Node word = CreateNode<AST>();
+ UPDATE_POS( word, startWord, lex->index() );
+ ast->addNode( word );
+ } else
+ break;
+ }
+
+ if( n == 0 )
+ return false;
+
+
+ //kdDebug(9007)<< "-----------------> token = " << lex->lookAhead(0).text() << endl;
+ UPDATE_POS( ast, start, lex->index() );
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node )
+{
+ int start = lex->index();
+ bool isIntegral = false;
+ bool done = false;
+
+ while( !done ){
+
+ switch( lex->lookAhead(0) ){
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ isIntegral = true;
+ lex->nextToken();
+ break;
+
+ default:
+ done = true;
+ }
+ }
+
+ TypeSpecifierAST::Node ast = CreateNode<TypeSpecifierAST>();
+ if( isIntegral ){
+ ClassOrNamespaceNameAST::Node cl = CreateNode<ClassOrNamespaceNameAST>();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, start, lex->index() );
+ cl->setName( n );
+ UPDATE_POS( cl, start, lex->index() );
+
+ NameAST::Node name = CreateNode<NameAST>();
+ name->setUnqualifiedName( cl );
+ UPDATE_POS( name, start, lex->index() );
+ ast->setName( name );
+
+ } else {
+ NameAST::Node name;
+ if( !parseName(name) ){
+ lex->setIndex( start );
+ return false;
+ }
+ ast->setName( name );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parsePtrOperator( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrOperator()" << endl;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) == '&' ){
+ lex->nextToken();
+ } else if( lex->lookAhead(0) == '*' ){
+ lex->nextToken();
+ } else {
+ int index = lex->index();
+ AST::Node memPtr;
+ if( !parsePtrToMember(memPtr) ){
+ lex->setIndex( index );
+ return false;
+ }
+ }
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseTemplateArgument( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateArgument()" << endl;
+
+ int start = lex->index();
+ if( parseTypeId(node) ){
+ if( lex->lookAhead(0) == ',' || lex->lookAhead(0) == '>' )
+ return true;
+ }
+
+ lex->setIndex( start );
+ if( !parseLogicalOrExpression(node, true) ){
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifier( TypeSpecifierAST::Node& spec )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeSpecifier()" << endl;
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ if( parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseDeclarator( DeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl;
+
+ int start = lex->index();
+
+ DeclaratorAST::Node ast = CreateNode<DeclaratorAST>();
+
+ DeclaratorAST::Node decl;
+ NameAST::Node declId;
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) ){
+ ast->addPtrOp( ptrOp );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ if( !parseDeclarator(decl) ){
+ return false;
+ }
+ ast->setSubDeclarator( decl );
+
+ if( lex->lookAhead(0) != ')'){
+ return false;
+ }
+ lex->nextToken();
+ } else {
+
+ if( lex->lookAhead(0) == ':' ){
+ // unnamed bitfield
+ } else if( parseDeclaratorId(declId) ){
+ ast->setDeclaratorId( declId );
+ } else {
+ lex->setIndex( start );
+ return false;
+ }
+
+ if( lex->lookAhead(0) == ':' ){
+ lex->nextToken();
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("Constant expression expected") );
+ }
+ goto update_pos;
+ }
+ }
+
+ {
+ bool isVector = true;
+
+ while( lex->lookAhead(0) == '[' ){
+ int startArray = lex->index();
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+
+ ADVANCE( ']', "]" );
+ AST::Node array = CreateNode<AST>();
+ UPDATE_POS( array, startArray, lex->index() );
+ ast->addArrayDimension( array );
+ isVector = true;
+ }
+
+ bool skipParen = false;
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){
+ lex->nextToken();
+ lex->nextToken();
+ skipParen = true;
+ }
+
+ if( ast->subDeclarator() && (!isVector || lex->lookAhead(0) != '(') ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ ParameterDeclarationClauseAST::Node params;
+ if( !parseParameterDeclarationClause(params) ){
+ //kdDebug(9007)<< "----------------------> not a parameter declaration, maybe an initializer!?" << endl;
+ lex->setIndex( index );
+ goto update_pos;
+ }
+ ast->setParameterDeclarationClause( params );
+
+ if( lex->lookAhead(0) != ')' ){
+ lex->setIndex( index );
+ goto update_pos;
+ }
+
+ lex->nextToken(); // skip ')'
+
+ int startConstant = lex->index();
+ if( lex->lookAhead(0) == Token_const ){
+ lex->nextToken();
+ AST::Node constant = CreateNode<AST>();
+ UPDATE_POS( constant, startConstant, lex->index() );
+ ast->setConstant( constant );
+ }
+
+ GroupAST::Node except;
+ if( parseExceptionSpecification(except) ){
+ ast->setExceptionSpecification( except );
+ }
+ }
+
+ if( skipParen ){
+ if( lex->lookAhead(0) != ')' ){
+ reportError( i18n("')' expected") );
+ } else
+ lex->nextToken();
+ }
+
+ }
+
+update_pos:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator( DeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarator()" << endl;
+ int start = lex->index();
+
+ DeclaratorAST::Node ast = CreateNode<DeclaratorAST>();
+
+ DeclaratorAST::Node decl;
+ NameAST::Node declId;
+
+ AST::Node ptrOp;
+ while( parsePtrOperator(ptrOp) ){
+ ast->addPtrOp( ptrOp );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ if( !parseAbstractDeclarator(decl) ){
+ return false;
+ }
+ ast->setSubDeclarator( decl );
+
+ if( lex->lookAhead(0) != ')'){
+ return false;
+ }
+ lex->nextToken();
+ }
+
+ {
+
+ while( lex->lookAhead(0) == '[' ){
+ int startArray = lex->index();
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ']', "]" );
+ AST::Node array = CreateNode<AST>();
+ UPDATE_POS( array, startArray, lex->index() );
+ ast->addArrayDimension( array );
+ }
+
+ bool skipParen = false;
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == '(' && lex->lookAhead(2) == '(' ){
+ lex->nextToken();
+ lex->nextToken();
+ skipParen = true;
+ }
+
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+
+ ParameterDeclarationClauseAST::Node params;
+ if( !parseParameterDeclarationClause(params) ){
+ lex->setIndex( index );
+ goto UPDATE_POS;
+ }
+ ast->setParameterDeclarationClause( params );
+
+ if( lex->lookAhead(0) != ')' ){
+ lex->setIndex( index );
+ goto UPDATE_POS;
+ } else
+ lex->nextToken();
+
+ int startConstant = lex->index();
+ if( lex->lookAhead(0) == Token_const ){
+ lex->nextToken();
+ AST::Node constant = CreateNode<AST>();
+ UPDATE_POS( constant, startConstant, lex->index() );
+ ast->setConstant( constant );
+ }
+
+ GroupAST::Node except;
+ if( parseExceptionSpecification(except) ){
+ ast->setExceptionSpecification( except );
+ }
+ }
+
+ if( skipParen ){
+ if( lex->lookAhead(0) != ')' ){
+ reportError( i18n("')' expected") );
+ } else
+ lex->nextToken();
+ }
+
+ }
+
+UPDATE_POS:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseEnumSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumSpecifier()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_enum ){
+ return false;
+ }
+
+ lex->nextToken();
+
+ NameAST::Node name;
+ parseName( name );
+
+ if( lex->lookAhead(0) != '{' ){
+ lex->setIndex( start );
+ return false;
+ }
+ lex->nextToken();
+
+ EnumSpecifierAST::Node ast = CreateNode<EnumSpecifierAST>();
+ ast->setName( name );
+
+ EnumeratorAST::Node enumerator;
+ if( parseEnumerator(enumerator) ){
+ ast->addEnumerator( enumerator );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = "";
+ advanceAndCheckTrailingComment( comment );
+ if ( !comment.isEmpty() ){
+ EnumeratorAST *lastLit = ast->enumeratorList().last();
+ if( lastLit )
+ lastLit->setComment( comment );
+ }
+
+ if( !parseEnumerator(enumerator) ){
+ //reportError( i18n("Enumerator expected") );
+ break;
+ }
+
+ ast->addEnumerator( enumerator );
+ }
+ }
+
+ if( lex->lookAhead(0) == Token_comment )
+ lex->nextToken();
+ if( lex->lookAhead(0) != '}' )
+ reportError( i18n("} missing") );
+ else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameterList( TemplateParameterListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameterList()" << endl;
+
+ int start = lex->index();
+
+ TemplateParameterListAST::Node ast = CreateNode<TemplateParameterListAST>();
+
+ TemplateParameterAST::Node param;
+ if( !parseTemplateParameter(param) ){
+ return false;
+ }
+ ast->addTemplateParameter( param );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseTemplateParameter(param) ){
+ syntaxError();
+ break;
+ } else {
+ if (!comment.isEmpty())
+ param->setComment(comment);
+ ast->addTemplateParameter( param );
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameter( TemplateParameterAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTemplateParameter()" << endl;
+
+ int start = lex->index();
+ TemplateParameterAST::Node ast = CreateNode<TemplateParameterAST>();
+
+ TypeParameterAST::Node typeParameter;
+ ParameterDeclarationAST::Node param;
+
+ int tk = lex->lookAhead( 0 );
+
+ if( (tk == Token_class || tk == Token_typename || tk == Token_template) && parseTypeParameter(typeParameter) ){
+ ast->setTypeParameter( typeParameter );
+ goto ok;
+ }
+
+ if( !parseParameterDeclaration(param) )
+ return false;
+ ast->setTypeValueParameter( param );
+
+ok:
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeParameter( TypeParameterAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeParameter()" << endl;
+
+ int start = lex->index();
+ TypeParameterAST::Node ast = CreateNode<TypeParameterAST>();
+
+ AST_FROM_TOKEN( kind, lex->index() );
+ ast->setKind( kind );
+
+ switch( lex->lookAhead(0) ){
+
+ case Token_class:
+ case Token_typename:
+ {
+ lex->nextToken(); // skip class
+
+ // parse optional name
+ NameAST::Node name;
+ if( parseName(name) ){
+ ast->setName( name );
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId( typeId );
+ }
+ }
+ }
+ break;
+
+ case Token_template:
+ {
+ lex->nextToken(); // skip template
+ ADVANCE( '<', '<' );
+
+ TemplateParameterListAST::Node params;
+ if( !parseTemplateParameterList(params) ){
+ return false;
+ }
+ ast->setTemplateParameterList( params );
+
+ ADVANCE( '>', ">" );
+
+ if( lex->lookAhead(0) == Token_class )
+ lex->nextToken();
+
+ // parse optional name
+ NameAST::Node name;
+ if( parseName(name) ){
+ ast->setName( name );
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId( typeId );
+ }
+ }
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ NameAST::Node templ_name;
+ parseName( templ_name );
+ }
+ }
+ break;
+
+ default:
+ return false;
+
+ } // end switch
+
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseStorageClassSpecifier( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStorageClassSpecifier()" << endl;
+
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static ||
+ tk == Token_extern || tk == Token_mutable ){
+ int startNode = lex->index();
+ lex->nextToken();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startNode, lex->index() );
+ ast->addNode( n );
+ } else
+ break;
+ }
+
+ if( ast->nodeList().count() == 0 )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseFunctionSpecifier( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionSpecifier()" << endl;
+
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_inline || tk == Token_virtual || tk == Token_explicit ){
+ int startNode = lex->index();
+ lex->nextToken();
+
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, startNode, lex->index() );
+ ast->addNode( n );
+ } else {
+ break;
+ }
+ }
+
+ if( ast->nodeList().count() == 0 )
+ return false;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTypeId( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeId()" << endl;
+
+ /// @todo implement the AST for typeId
+ int start = lex->index();
+ AST::Node ast = CreateNode<AST>();
+
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifier(spec) ){
+ return false;
+ }
+
+ DeclaratorAST::Node decl;
+ parseAbstractDeclarator( decl );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclaratorList( InitDeclaratorListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList()" << endl;
+
+ int start = lex->index();
+
+ InitDeclaratorListAST::Node ast = CreateNode<InitDeclaratorListAST>();
+ InitDeclaratorAST::Node decl;
+
+ if( !parseInitDeclarator(decl) ){
+ return false;
+ }
+ ast->addInitDeclarator( decl );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = "";
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseInitDeclarator(decl) ){
+ syntaxError();
+ break;
+ }
+ if ( !comment.isEmpty() )
+ decl->setComment( comment );
+ ast->addInitDeclarator( decl );
+ }
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclaratorList() -- end" << endl;
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationClause()" << endl;
+
+ int start = lex->index();
+
+ ParameterDeclarationClauseAST::Node ast = CreateNode<ParameterDeclarationClauseAST>();
+
+ ParameterDeclarationListAST::Node params;
+ if( !parseParameterDeclarationList(params) ){
+
+ if ( lex->lookAhead(0) == ')' )
+ goto good;
+
+ if( lex->lookAhead(0) == Token_ellipsis && lex->lookAhead(1) == ')' ){
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->setEllipsis( ellipsis );
+ lex->nextToken();
+ goto good;
+ }
+ return false;
+ }
+
+ if( lex->lookAhead(0) == Token_ellipsis ){
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->setEllipsis( ellipsis );
+ lex->nextToken();
+ }
+
+good:
+ ast->setParameterDeclarationList( params );
+
+ /// @todo add ellipsis
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList( ParameterDeclarationListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclarationList()" << endl;
+
+ int start = lex->index();
+
+ ParameterDeclarationListAST::Node ast = CreateNode<ParameterDeclarationListAST>();
+
+ ParameterDeclarationAST::Node param;
+ if( !parseParameterDeclaration(param) ){
+ lex->setIndex( start );
+ return false;
+ }
+ ast->addParameter( param );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( lex->lookAhead(0) == Token_ellipsis )
+ break;
+
+ if( !parseParameterDeclaration(param) ){
+ lex->setIndex( start );
+ return false;
+ }
+ if (!comment.isEmpty())
+ param->setComment(comment);
+ ast->addParameter( param );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclaration( ParameterDeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseParameterDeclaration()" << endl;
+
+ int start = lex->index();
+
+ // parse decl spec
+ TypeSpecifierAST::Node spec;
+ if( !parseTypeSpecifier(spec) ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ int index = lex->index();
+
+ DeclaratorAST::Node decl;
+ if( !parseDeclarator(decl) ){
+ lex->setIndex( index );
+
+ // try with abstract declarator
+ if( !parseAbstractDeclarator(decl) )
+ return false;
+ }
+
+ AST::Node expr;
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+ if( !parseLogicalOrExpression(expr,true) ){
+ //reportError( i18n("Expression expected") );
+ }
+ }
+
+ ParameterDeclarationAST::Node ast = CreateNode<ParameterDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setDeclarator( decl );
+ ast->setExpression( expr );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseClassSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseClassSpecifier()" << endl;
+
+ int start = lex->index();
+
+ AST::Node classKey;
+ int classKeyStart = lex->index();
+
+ int kind = lex->lookAhead( 0 );
+ if( kind == Token_class || kind == Token_struct || kind == Token_union ){
+ AST::Node asn = CreateNode<AST>();
+ classKey = asn;
+ lex->nextToken();
+ UPDATE_POS( classKey, classKeyStart, lex->index() );
+ } else {
+ return false;
+ }
+
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ while( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == Token_identifier )
+ lex->nextToken();
+
+ NameAST::Node name;
+ parseName( name );
+
+ BaseClauseAST::Node bases;
+ if( lex->lookAhead(0) == ':' ){
+ if( !parseBaseClause(bases) ){
+ skipUntil( '{' );
+ }
+ }
+
+ QString comment;
+ while (lex->lookAhead(0) == Token_comment) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0) != '{' ){
+ lex->setIndex( start );
+ return false;
+ }
+
+ ADVANCE( '{', '{' );
+
+ ClassSpecifierAST::Node ast = CreateNode<ClassSpecifierAST>();
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setClassKey( classKey );
+ ast->setName( name );
+ ast->setBaseClause( bases );
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ DeclarationAST::Node memSpec = CreateNode<DeclarationAST>();
+ int startDecl = lex->index();
+ if( !parseMemberSpecification(memSpec) ){
+ if( startDecl == lex->index() )
+ lex->nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ } else
+ ast->addDeclaration( memSpec );
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} missing") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAccessSpecifier( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAccessSpecifier()" << endl;
+
+ int start = lex->index();
+
+ switch( lex->lookAhead(0) ){
+ case Token_public:
+ case Token_protected:
+ case Token_private: {
+ AST::Node asn = CreateNode<AST>();
+ node = asn;
+ lex->nextToken();
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Parser::advanceAndCheckTrailingComment(QString& comment)
+{
+ Token t = lex->tokenAt( lex->index() );
+ int previousTokenEndLine = 0;
+ t.getEndPosition( &previousTokenEndLine, 0 );
+ lex->nextToken();
+ if( lex->lookAhead(0) != Token_comment )
+ return;
+ t = lex->tokenAt( lex->index() );
+ int commentStartLine = 0;
+ t.getStartPosition( &commentStartLine, 0 );
+ if( commentStartLine != previousTokenEndLine )
+ return;
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+}
+
+bool Parser::parseMemberSpecification( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemberSpecification()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ AST::Node access;
+
+ if( lex->lookAhead(0) == ';' ){
+ advanceAndCheckTrailingComment( comment );
+ if ( !comment.isEmpty() )
+ node->setComment( comment );
+ return true;
+ } else if( lex->lookAhead(0) == Token_Q_OBJECT || lex->lookAhead(0) == Token_K_DCOP ){
+ lex->nextToken();
+ return true;
+ } else if( lex->lookAhead(0) == Token_signals || lex->lookAhead(0) == Token_k_dcop || lex->lookAhead(0) == Token_k_dcop_signals ){
+ AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>();
+ lex->nextToken();
+ AST::Node n = CreateNode<AST>();
+ UPDATE_POS( n, start, lex->index() );
+ ast->addAccess( n );
+ ADVANCE( ':', ":" );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ } else if( parseTypedef(node) ){
+ return true;
+ } else if( parseUsing(node) ){
+ return true;
+ } else if( parseTemplateDeclaration(node) ){
+ return true;
+ } else if( parseAccessSpecifier(access) ){
+ AccessDeclarationAST::Node ast = CreateNode<AccessDeclarationAST>();
+ ast->addAccess( access );
+
+ int startSlot = lex->index();
+ if( lex->lookAhead(0) == Token_slots ){
+ lex->nextToken();
+ AST::Node sl = CreateNode<AST>();
+ UPDATE_POS( sl, startSlot, lex->index() );
+ ast->addAccess( sl );
+ }
+ ADVANCE( ':', ":" );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ }
+
+ lex->setIndex( start );
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ if( parseEnumSpecifier(spec) || parseClassSpecifier(spec) ){
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList( declarators );
+ ADVANCE( ';', ";" );
+
+ if( !comment.isEmpty() ) {
+ //kdDebug(9007) << "Parser::parseMemberSpecification(spec): comment is " << comment << endl;
+ spec->setComment( comment );
+ }
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+
+ lex->setIndex( start );
+
+ bool success = parseDeclarationInternal(node, comment);
+ if( success && !comment.isEmpty() ) {
+ node->setComment( comment );
+ //kdDebug(9007) << "Parser::parseMemberSpecification(): comment is " << comment << endl;
+ }
+ return success;
+}
+
+bool Parser::parseCtorInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCtorInitializer()" << endl;
+
+ if( lex->lookAhead(0) != ':' ){
+ return false;
+ }
+ lex->nextToken();
+
+ AST::Node inits;
+ if( !parseMemInitializerList(inits) ){
+ reportError( i18n("Member initializers expected") );
+ }
+
+ return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseElaboratedTypeSpecifier()" << endl;
+
+ int start = lex->index();
+
+ int tk = lex->lookAhead( 0 );
+ if( tk == Token_class ||
+ tk == Token_struct ||
+ tk == Token_union ||
+ tk == Token_enum ||
+ tk == Token_typename )
+ {
+ AST::Node kind = CreateNode<AST>();
+ lex->nextToken();
+ UPDATE_POS( kind, start, lex->index() );
+
+ NameAST::Node name;
+
+ if( parseName(name) ){
+ ElaboratedTypeSpecifierAST::Node ast = CreateNode<ElaboratedTypeSpecifierAST>();
+ ast->setKind( kind );
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+ }
+
+ lex->setIndex( start );
+ return false;
+}
+
+bool Parser::parseDeclaratorId( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclaratorId()" << endl;
+ return parseName( node );
+}
+
+bool Parser::parseExceptionSpecification( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExceptionSpecification()" << endl;
+
+ if( lex->lookAhead(0) != Token_throw ){
+ return false;
+ }
+ lex->nextToken();
+
+ ADVANCE( '(', "(" );
+ if( lex->lookAhead(0) == Token_ellipsis ){
+ // extension found in MSVC++ 7.x headers
+ int start = lex->index();
+ GroupAST::Node ast = CreateNode<GroupAST>();
+ AST_FROM_TOKEN( ellipsis, lex->index() );
+ ast->addNode( ellipsis );
+ lex->nextToken();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ } else {
+ parseTypeIdList( node );
+ }
+ ADVANCE( ')', ")" );
+
+ return true;
+}
+
+bool Parser::parseEnumerator( EnumeratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEnumerator()" << endl;
+
+ QString comment;
+ while( lex->lookAhead(0) == Token_comment ) {
+ comment += lex->lookAhead(0).text();
+ lex->nextToken();
+ }
+ if( lex->lookAhead(0).isNull() )
+ return false;
+
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_identifier ){
+ return false;
+ }
+ lex->nextToken();
+
+ EnumeratorAST::Node ena = CreateNode<EnumeratorAST>();
+ node = ena;
+
+ AST::Node id = CreateNode<AST>();
+ UPDATE_POS( id, start, lex->index() );
+ node->setId( id );
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("Constant expression expected") );
+ }
+ node->setExpr( expr );
+ }
+
+ UPDATE_POS( node, start, lex->index() );
+
+ return true;
+}
+
+bool Parser::parseInitDeclarator( InitDeclaratorAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitDeclarator()" << endl;
+
+ int start = lex->index();
+
+ DeclaratorAST::Node decl;
+ AST::Node init;
+ if( !parseDeclarator(decl) ){
+ return false;
+ }
+
+ parseInitializer( init );
+
+ InitDeclaratorAST::Node ast = CreateNode<InitDeclaratorAST>();
+ ast->setDeclarator( decl );
+ ast->setInitializer( init );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+
+bool Parser::parseBaseClause( BaseClauseAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseClause()" << endl;
+
+ int start = lex->index();
+ if( lex->lookAhead(0) != ':' ){
+ return false;
+ }
+ lex->nextToken();
+
+ BaseClauseAST::Node bca = CreateNode<BaseClauseAST>();
+
+ BaseSpecifierAST::Node baseSpec;
+ if( parseBaseSpecifier(baseSpec) ){
+ bca->addBaseSpecifier( baseSpec );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseBaseSpecifier(baseSpec) ){
+ reportError( i18n("Base class specifier expected") );
+ return false;
+ }
+ if (!comment.isEmpty())
+ baseSpec->setComment(comment);
+ bca->addBaseSpecifier( baseSpec );
+ }
+ } else
+ return false;
+
+ UPDATE_POS( bca, start, lex->index() );
+ node = bca;
+
+ return true;
+}
+
+bool Parser::parseInitializer( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializer()" << endl;
+
+ if( lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ AST::Node init;
+ if( !parseInitializerClause(node) ){
+ reportError( i18n("Initializer clause expected") );
+ return false;
+ }
+ } else if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ')', ")" );
+ }
+
+ return false;
+}
+
+bool Parser::parseMemInitializerList( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerList()" << endl;
+
+ AST::Node init;
+ if( !parseMemInitializer(init) ){
+ return false;
+ }
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( parseMemInitializer(init) ){
+ } else {
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializer()" << endl;
+
+ NameAST::Node initId;
+ if( !parseMemInitializerId(initId) ){
+ reportError( i18n("Identifier expected") );
+ return false;
+ }
+ ADVANCE( '(', '(' );
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ')', ')' );
+
+ return true;
+}
+
+bool Parser::parseTypeIdList( GroupAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTypeIdList()" << endl;
+
+ int start = lex->index();
+
+ AST::Node typeId;
+ if( !parseTypeId(typeId) ){
+ return false;
+ }
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+ ast->addNode( typeId );
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+ if( parseTypeId(typeId) ){
+ if (!comment.isEmpty())
+ typeId->setComment(comment);
+ ast->addNode( typeId );
+ } else {
+ reportError( i18n("Type id expected") );
+ break;
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseBaseSpecifier( BaseSpecifierAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBaseSpecifier()" << endl;
+
+ int start = lex->index();
+ BaseSpecifierAST::Node ast = CreateNode<BaseSpecifierAST>();
+
+ AST::Node access;
+ if( lex->lookAhead(0) == Token_virtual ){
+ AST_FROM_TOKEN( virt, lex->index() );
+ ast->setIsVirtual( virt );
+
+ lex->nextToken();
+
+ parseAccessSpecifier( access );
+ } else {
+ parseAccessSpecifier( access );
+
+ if( lex->lookAhead(0) == Token_virtual ){
+ AST_FROM_TOKEN( virt, lex->index() );
+ ast->setIsVirtual( virt );
+ lex->nextToken();
+ }
+ }
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Class name expected") );
+ }
+
+ ast->setAccess( access );
+ ast->setName( name );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseInitializerClause( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInitializerClause()" << endl;
+
+ if( lex->lookAhead(0) == '{' ){
+ if( !skip('{','}') ){
+ reportError( i18n("} missing") );
+ } else
+ lex->nextToken();
+ } else {
+ if( !parseAssignmentExpression(node) ){
+ //reportError( i18n("Expression expected") );
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializerId( NameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMemInitializerId()" << endl;
+
+ return parseName( node );
+}
+
+bool Parser::parsePtrToMember( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePtrToMember()" << endl;
+
+ if( lex->lookAhead(0) == Token_scope ){
+ lex->nextToken();
+ }
+
+ while( lex->lookAhead(0) == Token_identifier ){
+ lex->nextToken();
+
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == '*' ){
+ lex->nextToken(); // skip ::
+ lex->nextToken(); // skip *
+ return true;
+ } else
+ break;
+ }
+
+ return false;
+}
+
+bool Parser::parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnqualifiedName()" << endl;
+
+ int start = lex->index();
+ bool isDestructor = false;
+
+ ClassOrNamespaceNameAST::Node ast = CreateNode<ClassOrNamespaceNameAST>();
+
+ if( lex->lookAhead(0) == Token_identifier ){
+ int startName = lex->index();
+ AST::Node n = CreateNode<AST>();
+ lex->nextToken();
+ UPDATE_POS( n, startName, lex->index() );
+ ast->setName( n );
+ } else if( lex->lookAhead(0) == '~' && lex->lookAhead(1) == Token_identifier ){
+ int startName = lex->index();
+ AST::Node n = CreateNode<AST>();
+ lex->nextToken(); // skip ~
+ lex->nextToken(); // skip classname
+ UPDATE_POS( n, startName, lex->index() );
+ ast->setName( n );
+ isDestructor = true;
+ } else if( lex->lookAhead(0) == Token_operator ){
+ AST::Node n;
+ if( !parseOperatorFunctionId(n) )
+ return false;
+ ast->setName( n );
+ } else {
+ return false;
+ }
+
+ if( !isDestructor ){
+
+ int index = lex->index();
+
+ if( lex->lookAhead(0) == '<' ){
+ lex->nextToken();
+
+ // optional template arguments
+ TemplateArgumentListAST::Node args;
+ parseTemplateArgumentList( args );
+
+ if( lex->lookAhead(0) != '>' ){
+ lex->setIndex( index );
+ } else {
+ lex->nextToken();
+ ast->setTemplateArgumentList( args );
+ }
+ }
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStringLiteral( AST::Node& /*node*/ )
+{
+ while( !lex->lookAhead(0).isNull() ) {
+ if( lex->lookAhead(0) == Token_identifier &&
+ lex->lookAhead(0).text() == "L" && lex->lookAhead(1) == Token_string_literal ) {
+
+ lex->nextToken();
+ lex->nextToken();
+ } else if( lex->lookAhead(0) == Token_string_literal ) {
+ lex->nextToken();
+ } else
+ return false;
+ }
+ return true;
+}
+
+bool Parser::skipExpressionStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::skipExpressionStatement()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ skipCommaExpression( expr );
+
+ ADVANCE( ';', ";" );
+
+ ExpressionStatementAST::Node ast = CreateNode<ExpressionStatementAST>();
+ ast->setExpression( expr );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStatement( StatementAST::Node& node ) // thanks to fiore@8080.it ;)
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseStatement()" << endl;
+ switch( lex->lookAhead(0) ){
+
+ case Token_while:
+ return parseWhileStatement( node );
+
+ case Token_do:
+ return parseDoStatement( node );
+
+ case Token_for:
+ return parseForStatement( node );
+
+ case Token_if:
+ return parseIfStatement( node );
+
+ case Token_switch:
+ return parseSwitchStatement( node );
+
+ case Token_try:
+ return parseTryBlockStatement( node );
+
+ case Token_case:
+ case Token_default:
+ return parseLabeledStatement( node );
+
+ case Token_break:
+ case Token_continue:
+ lex->nextToken();
+ ADVANCE( ';', ";" );
+ return true;
+
+ case Token_goto:
+ lex->nextToken();
+ ADVANCE( Token_identifier, "identifier" );
+ ADVANCE( ';', ";" );
+ return true;
+
+ case Token_return:
+ {
+ lex->nextToken();
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ';', ";" );
+ }
+ return true;
+
+ case '{':
+ return parseCompoundStatement( node );
+
+ case Token_identifier:
+ if( parseLabeledStatement(node) )
+ return true;
+ break;
+ }
+
+ //kdDebug(9007)<< "------------> try with declaration statement" << endl;
+ if ( parseDeclarationStatement(node) )
+ return true;
+
+ return skipExpressionStatement( node );
+}
+
+bool Parser::parseCondition( ConditionAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCondition()" << endl;
+
+ int start = lex->index();
+
+ ConditionAST::Node ast = CreateNode<ConditionAST>();
+
+ TypeSpecifierAST::Node spec;
+ if( parseTypeSpecifier(spec) ){
+ DeclaratorAST::Node decl;
+ if( parseDeclarator(decl) && lex->lookAhead(0) == '=' ) {
+ lex->nextToken();
+
+ AST::Node expr;
+ if( skipExpression(expr) ){
+ ast->setTypeSpec( spec );
+ ast->setDeclarator( decl );
+ ast->setExpression( expr );
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+ }
+ }
+ }
+
+ lex->setIndex( start );
+
+ AST::Node expr;
+ if( !skipCommaExpression(expr) )
+ return false;
+
+ ast->setExpression( expr );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+
+bool Parser::parseWhileStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseWhileStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_while, "while" );
+ ADVANCE( '(' , "(" );
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) ){
+ reportError( i18n("statement expected") );
+ return false;
+ }
+
+ WhileStatementAST::Node ast = CreateNode<WhileStatementAST>();
+ ast->setCondition( cond );
+ ast->setStatement( body );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDoStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDoStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_do, "do" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) ){
+ reportError( i18n("statement expected") );
+ //return false;
+ }
+
+ ADVANCE_NR( Token_while, "while" );
+ ADVANCE_NR( '(' , "(" );
+
+ AST::Node expr;
+ if( !skipCommaExpression(expr) ){
+ reportError( i18n("expression expected") );
+ //return false;
+ }
+
+ ADVANCE_NR( ')', ")" );
+ ADVANCE_NR( ';', ";" );
+
+ DoStatementAST::Node ast = CreateNode<DoStatementAST>();
+ ast->setStatement( body );
+ //ast->setCondition( condition );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForStatement()" << endl;
+ int start = lex->index();
+
+ ADVANCE( Token_for, "for" );
+ ADVANCE( '(', "(" );
+
+ StatementAST::Node init;
+ if( !parseForInitStatement(init) ){
+ reportError( i18n("for initialization expected") );
+ return false;
+ }
+
+ ConditionAST::Node cond;
+ parseCondition( cond );
+ ADVANCE( ';', ";" );
+
+ AST::Node expr;
+ skipCommaExpression( expr );
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseStatement(body) )
+ return false;
+
+ ForStatementAST::Node ast = CreateNode<ForStatementAST>();
+ ast->setInitStatement( init );
+ ast->setCondition( cond );
+ // ast->setExpression( expression );
+ ast->setStatement( body );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForInitStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseForInitStatement()" << endl;
+
+ if ( parseDeclarationStatement(node) )
+ return true;
+
+ return skipExpressionStatement( node );
+}
+
+bool Parser::parseCompoundStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCompoundStatement()" << endl;
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementListAST::Node ast = CreateNode<StatementListAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ StatementAST::Node stmt;
+ int startStmt = lex->index();
+ if( !parseStatement(stmt) ){
+ if( startStmt == lex->index() )
+ lex->nextToken();
+ skipUntilStatement();
+ } else {
+ ast->addStatement( stmt );
+ }
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else {
+ lex->nextToken();
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseIfStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseIfStatement()" << endl;
+
+ int start = lex->index();
+
+ ADVANCE( Token_if, "if" );
+
+ ADVANCE( '(' , "(" );
+
+ IfStatementAST::Node ast = CreateNode<IfStatementAST>();
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node stmt;
+ if( !parseStatement(stmt) ){
+ reportError( i18n("statement expected") );
+ return false;
+ }
+
+ ast->setCondition( cond );
+ ast->setStatement( stmt );
+
+ if( lex->lookAhead(0) == Token_else ){
+ lex->nextToken();
+ StatementAST::Node elseStmt;
+ if( !parseStatement(elseStmt) ) {
+ reportError( i18n("statement expected") );
+ return false;
+ }
+ ast->setElseStatement( elseStmt );
+ }
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseSwitchStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseSwitchStatement()" << endl;
+ int start = lex->index();
+ ADVANCE( Token_switch, "switch" );
+
+ ADVANCE( '(' , "(" );
+
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node stmt;
+ if( !parseCompoundStatement(stmt) ){
+ syntaxError();
+ return false;
+ }
+
+ SwitchStatementAST::Node ast = CreateNode<SwitchStatementAST>();
+ ast->setCondition( cond );
+ ast->setStatement( stmt );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLabeledStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLabeledStatement()" << endl;
+ switch( lex->lookAhead(0) ){
+ case Token_identifier:
+ case Token_default:
+ if( lex->lookAhead(1) == ':' ){
+ lex->nextToken();
+ lex->nextToken();
+
+ StatementAST::Node stmt;
+ if( parseStatement(stmt) ){
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ case Token_case:
+ {
+ lex->nextToken();
+ AST::Node expr;
+ if( !parseConstantExpression(expr) ){
+ reportError( i18n("expression expected") );
+ } else if( lex->lookAhead(0) == Token_ellipsis ){
+ lex->nextToken();
+
+ AST::Node expr2;
+ if( !parseConstantExpression(expr2) ){
+ reportError( i18n("expression expected") );
+ }
+ }
+ ADVANCE( ':', ":" );
+
+ StatementAST::Node stmt;
+ if( parseStatement(stmt) ){
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ }
+
+ return false;
+}
+
+bool Parser::parseBlockDeclaration( DeclarationAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseBlockDeclaration()" << endl;
+ switch( lex->lookAhead(0) ) {
+ case Token_typedef:
+ return parseTypedef( node );
+ case Token_using:
+ return parseUsing( node );
+ case Token_asm:
+ return parseAsmDefinition( node );
+ case Token_namespace:
+ return parseNamespaceAliasDefinition( node );
+ }
+
+ int start = lex->index();
+
+ GroupAST::Node storageSpec;
+ parseStorageClassSpecifier( storageSpec );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ TypeSpecifierAST::Node spec;
+ if ( !parseTypeSpecifierOrClassSpec(spec) ) { // replace with simpleTypeSpecifier?!?!
+ lex->setIndex( start );
+ return false;
+ }
+ spec->setCvQualify( cv );
+
+ GroupAST::Node cv2;
+ parseCvQualify( cv2 );
+ spec->setCv2Qualify( cv2 );
+
+ InitDeclaratorListAST::Node declarators;
+ parseInitDeclaratorList( declarators );
+
+ if( lex->lookAhead(0) != ';' ){
+ lex->setIndex( start );
+ return false;
+ }
+ lex->nextToken();
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setTypeSpec( spec );
+ ast->setInitDeclaratorList( declarators );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition( DeclarationAST::Node& /*node*/ )
+{
+ if ( lex->lookAhead(0) != Token_namespace ) {
+ return false;
+ }
+ lex->nextToken();
+
+ ADVANCE( Token_identifier, "identifier" );
+ ADVANCE( '=', "=" );
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ reportError( i18n("Namespace name expected") );
+ }
+
+ ADVANCE( ';', ";" );
+
+ return true;
+
+}
+
+bool Parser::parseDeclarationStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationStatement()" << endl;
+
+ int start = lex->index();
+
+ DeclarationAST::Node decl;
+ if ( !parseBlockDeclaration(decl) ){
+ return false;
+ }
+
+ DeclarationStatementAST::Node ast = CreateNode<DeclarationStatementAST>();
+ ast->setDeclaration( decl );
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ //kdDebug(9007)<< "---------------------> found a block declaration" << endl;
+ return true;
+}
+
+bool Parser::parseDeclarationInternal( DeclarationAST::Node& node, QString& comment )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeclarationInternal()" << endl;
+
+ int start = lex->index();
+
+ // that is for the case '__declspec(dllexport) int ...' or
+ // '__declspec(dllexport) inline int ...', etc.
+ GroupAST::Node winDeclSpec;
+ parseWinDeclSpec( winDeclSpec );
+
+ GroupAST::Node funSpec;
+ bool hasFunSpec = parseFunctionSpecifier( funSpec );
+
+ GroupAST::Node storageSpec;
+ bool hasStorageSpec = parseStorageClassSpecifier( storageSpec );
+
+ if( hasStorageSpec && !hasFunSpec )
+ hasFunSpec = parseFunctionSpecifier( funSpec );
+
+ // that is for the case 'friend __declspec(dllexport) ....'
+ GroupAST::Node winDeclSpec2;
+ parseWinDeclSpec( winDeclSpec2 );
+
+ GroupAST::Node cv;
+ parseCvQualify( cv );
+
+ int index = lex->index();
+ NameAST::Node name;
+ if( parseName(name) && lex->lookAhead(0) == '(' ){
+ // no type specifier, maybe a constructor or a cast operator??
+
+ lex->setIndex( index );
+
+ InitDeclaratorAST::Node declarator;
+ if( parseInitDeclarator(declarator) ){
+ int endSignature = lex->index();
+
+ switch( lex->lookAhead(0) ){
+ case ';':
+ {
+ lex->nextToken();
+
+ InitDeclaratorListAST::Node declarators = CreateNode<InitDeclaratorListAST>();
+
+ // update declarators position
+ int startLine, startColumn, endLine, endColumn;
+ if( declarator.get() ){
+ declarator->getStartPosition( &startLine, &startColumn );
+ declarator->getEndPosition( &endLine, &endColumn );
+ declarators->setStartPosition( startLine, startColumn );
+ declarators->setEndPosition( endLine, endColumn );
+ }
+ declarators->addInitDeclarator( declarator );
+
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setInitDeclaratorList( declarators );
+ ast->setText( toString(start, endSignature) );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+
+ }
+ break;
+
+ case ':':
+ {
+ AST::Node ctorInit;
+ StatementListAST::Node funBody;
+ if( parseCtorInitializer(ctorInit) && parseFunctionBody(funBody) ){
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setInitDeclarator( declarator );
+ ast->setFunctionBody( funBody );
+ ast->setText( toString(start, endSignature) );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ case '{':
+ {
+ StatementListAST::Node funBody;
+ if( parseFunctionBody(funBody) ){
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setInitDeclarator( declarator );
+ ast->setText( toString(start, endSignature) );
+ ast->setFunctionBody( funBody );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ case '(':
+ case '[':
+ // ops!! it seems a declarator
+ goto start_decl;
+ break;
+ }
+
+ }
+
+ syntaxError();
+ return false;
+ }
+
+start_decl:
+ lex->setIndex( index );
+
+ if( lex->lookAhead(0) == Token_const && lex->lookAhead(1) == Token_identifier && lex->lookAhead(2) == '=' ){
+ // constant definition
+ lex->nextToken();
+ InitDeclaratorListAST::Node declarators;
+ if( parseInitDeclaratorList(declarators) ){
+ ADVANCE( ';', ";" );
+ DeclarationAST::Node ast = CreateNode<DeclarationAST>();
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ syntaxError();
+ return false;
+ }
+
+ TypeSpecifierAST::Node spec;
+ if( parseTypeSpecifier(spec) ){
+ if ( !hasFunSpec )
+ parseFunctionSpecifier( funSpec ); // e.g. "void inline"
+ spec->setCvQualify( cv );
+
+ InitDeclaratorListAST::Node declarators;
+
+ InitDeclaratorAST::Node decl;
+ int startDeclarator = lex->index();
+ bool maybeFunctionDefinition = false;
+
+ if( lex->lookAhead(0) != ';' ){
+ if( parseInitDeclarator(decl) && lex->lookAhead(0) == '{' ){
+ // function definition
+ maybeFunctionDefinition = true;
+ } else {
+ lex->setIndex( startDeclarator );
+ if( !parseInitDeclaratorList(declarators) ){
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ int endSignature = lex->index();
+ switch( lex->lookAhead(0) ){
+ case ';':
+ {
+ advanceAndCheckTrailingComment( comment );
+ SimpleDeclarationAST::Node ast = CreateNode<SimpleDeclarationAST>();
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setText( toString(start, endSignature) );
+ ast->setTypeSpec( spec );
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setInitDeclaratorList( declarators );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ }
+ return true;
+
+ case '{':
+ {
+ if( !maybeFunctionDefinition ){
+ syntaxError();
+ return false;
+ }
+ StatementListAST::Node funBody;
+ if ( parseFunctionBody(funBody) ) {
+ FunctionDefinitionAST::Node ast = CreateNode<FunctionDefinitionAST>();
+ ast->setWinDeclSpec( winDeclSpec );
+ ast->setStorageSpecifier( storageSpec );
+ ast->setFunctionSpecifier( funSpec );
+ ast->setText( toString(start, endSignature) );
+ ast->setTypeSpec( spec );
+ ast->setFunctionBody( funBody );
+ ast->setInitDeclarator( decl );
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+ }
+ break;
+
+ }
+ }
+
+ syntaxError();
+ return false;
+}
+
+bool Parser::parseFunctionBody( StatementListAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseFunctionBody()" << endl;
+
+ int start = lex->index();
+ if( lex->lookAhead(0) != '{' ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementListAST::Node ast = CreateNode<StatementListAST>();
+
+ while( !lex->lookAhead(0).isNull() ){
+ if( lex->lookAhead(0) == '}' )
+ break;
+
+ StatementAST::Node stmt;
+ int startStmt = lex->index();
+ if( !parseStatement(stmt) ){
+ if( startStmt == lex->index() )
+ lex->nextToken();
+ skipUntilStatement();
+ } else
+ ast->addStatement( stmt );
+ }
+
+ if( lex->lookAhead(0) != '}' ){
+ reportError( i18n("} expected") );
+ } else
+ lex->nextToken();
+
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+
+ return true;
+}
+
+QString Parser::toString( int start, int end, const QString& sep ) const
+{
+ QStringList l;
+
+ for( int i=start; i<end; ++i ){
+ l << lex->tokenAt(i).text();
+ }
+
+ return l.join( sep ).stripWhiteSpace();
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& node )
+{
+ if( parseClassSpecifier(node) )
+ return true;
+ else if( parseEnumSpecifier(node) )
+ return true;
+ else if( parseTypeSpecifier(node) )
+ return true;
+
+ return false;
+}
+
+bool Parser::parseTryBlockStatement( StatementAST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseTryBlockStatement()" << endl;
+
+ if( lex->lookAhead(0) != Token_try ){
+ return false;
+ }
+ lex->nextToken();
+
+ StatementAST::Node stmt;
+ if( !parseCompoundStatement(stmt) ){
+ syntaxError();
+ return false;
+ }
+
+ if( lex->lookAhead(0) != Token_catch ){
+ reportError( i18n("catch expected") );
+ return false;
+ }
+
+ while( lex->lookAhead(0) == Token_catch ){
+ lex->nextToken();
+ ADVANCE( '(', "(" );
+ ConditionAST::Node cond;
+ if( !parseCondition(cond) ){
+ reportError( i18n("condition expected") );
+ return false;
+ }
+ ADVANCE( ')', ")" );
+
+ StatementAST::Node body;
+ if( !parseCompoundStatement(body) ){
+ syntaxError();
+ return false;
+ }
+ }
+
+ node = stmt;
+ return true;
+}
+
+bool Parser::parsePrimaryExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePrimarExpression()" << endl;
+
+
+ switch( lex->lookAhead(0) ){
+ case Token_string_literal:
+ {
+ AST::Node lit;
+ parseStringLiteral( lit );
+ }
+ return true;
+
+ case Token_number_literal:
+ case Token_char_literal:
+ case Token_true:
+ case Token_false:
+ lex->nextToken();
+ return true;
+
+ case Token_this:
+ lex->nextToken();
+ return true;
+
+ case Token_dynamic_cast:
+ case Token_static_cast:
+ case Token_reinterpret_cast:
+ case Token_const_cast:
+ {
+ lex->nextToken();
+
+ CHECK( '<', "<" );
+ AST::Node typeId;
+ parseTypeId( typeId );
+ CHECK( '>', ">" );
+
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ case Token_typeid:
+ {
+ lex->nextToken();
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ case '(':
+ {
+ lex->nextToken();
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "token = " << lex->lookAhead(0).text() << endl;
+ AST::Node expr;
+ if( !parseExpression(expr) ){
+ return false;
+ }
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ default:
+ {
+ int start = lex->index();
+ TypeSpecifierAST::Node typeSpec;
+ if( parseSimpleTypeSpecifier(typeSpec) && lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ return true;
+ }
+
+ lex->setIndex( start );
+ NameAST::Node name;
+ if( parseName(name) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parsePostfixExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parsePostfixExpression()" << endl;
+
+ AST::Node expr;
+ if( !parsePrimaryExpression(expr) )
+ return false;
+
+ while( true ){
+ switch(lex->lookAhead(0))
+ {
+ case '[':
+ {
+ lex->nextToken();
+ AST::Node e;
+ parseCommaExpression( e );
+ CHECK( ']', "]" );
+ }
+ break;
+
+ case '(':
+ {
+ lex->nextToken();
+ AST::Node funArgs;
+ parseCommaExpression( funArgs );
+ CHECK( ')', ")" );
+ }
+ break;
+
+ case Token_incr:
+ case Token_decr:
+ lex->nextToken();
+ break;
+
+ case '.':
+ case Token_arrow:
+ {
+ lex->nextToken();
+ if( lex->lookAhead(0) == Token_template )
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ return false;
+ }
+ }
+ break;
+
+ case Token_typename:
+ {
+ lex->nextToken();
+
+ NameAST::Node name;
+ if( !parseName(name) ){
+ return false;
+ }
+
+ CHECK( '(', "(" );
+ AST::Node expr;
+ parseCommaExpression(expr);
+ CHECK( ')', ")" );
+ }
+ return true;
+
+ default:
+ return true;
+
+ } // end switch
+
+ } // end while
+
+ return true;
+}
+
+bool Parser::parseUnaryExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseUnaryExpression()" << endl;
+
+ switch( lex->lookAhead(0) ){
+ case Token_incr:
+ case Token_decr:
+ case '*':
+ case '&':
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ lex->nextToken();
+ AST::Node expr;
+ return parseCastExpression( expr );
+ }
+
+ case Token_sizeof:
+ {
+ lex->nextToken();
+ int index = lex->index();
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ if( parseTypeId(typeId) && lex->lookAhead(0) == ')' ){
+ lex->nextToken();
+ return true;
+ }
+ lex->setIndex( index );
+ }
+ AST::Node expr;
+ return parseUnaryExpression( expr );
+ }
+
+ case Token_new:
+ return parseNewExpression( node );
+
+ case Token_delete:
+ return parseDeleteExpression( node );
+ }
+
+ return parsePostfixExpression( node );
+}
+
+bool Parser::parseNewExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewExpression()" << endl;
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_new )
+ lex->nextToken();
+
+ CHECK( Token_new, "new");
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+ }
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ parseTypeId( typeId );
+ CHECK( ')', ")" );
+ } else {
+ AST::Node typeId;
+ parseNewTypeId( typeId );
+ }
+
+ AST::Node init;
+ parseNewInitializer( init );
+ return true;
+}
+
+bool Parser::parseNewTypeId( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewTypeId()" << endl;
+ TypeSpecifierAST::Node typeSpec;
+ if( parseTypeSpecifier(typeSpec) ){
+ AST::Node declarator;
+ parseNewDeclarator( declarator );
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNewDeclarator( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewDeclarator()" << endl;
+ AST::Node ptrOp;
+ if( parsePtrOperator(ptrOp) ){
+ AST::Node declarator;
+ parseNewDeclarator( declarator );
+ return true;
+ }
+
+ if( lex->lookAhead(0) == '[' ){
+ while( lex->lookAhead(0) == '[' ){
+ lex->nextToken();
+ AST::Node expr;
+ parseExpression( expr );
+ ADVANCE( ']', "]" );
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNewInitializer( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseNewInitializer()" << endl;
+ if( lex->lookAhead(0) != '(' )
+ return false;
+
+ lex->nextToken();
+ AST::Node expr;
+ parseCommaExpression( expr );
+ CHECK( ')', ")" );
+
+ return true;
+}
+
+bool Parser::parseDeleteExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseDeleteExpression()" << endl;
+ if( lex->lookAhead(0) == Token_scope && lex->lookAhead(1) == Token_delete )
+ lex->nextToken();
+
+ CHECK( Token_delete, "delete" );
+
+ if( lex->lookAhead(0) == '[' ){
+ lex->nextToken();
+ CHECK( ']', "]" );
+ }
+
+ AST::Node expr;
+ return parseCastExpression( expr );
+}
+
+bool Parser::parseCastExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCastExpression()" << endl;
+
+ int index = lex->index();
+
+ if( lex->lookAhead(0) == '(' ){
+ lex->nextToken();
+ AST::Node typeId;
+ if ( parseTypeId(typeId) ) {
+ if ( lex->lookAhead(0) == ')' ) {
+ lex->nextToken();
+ AST::Node expr;
+ if( parseCastExpression(expr) )
+ return true;
+ }
+ }
+ }
+
+ lex->setIndex( index );
+
+ AST::Node expr;
+ return parseUnaryExpression( expr );
+}
+
+bool Parser::parsePmExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser:parsePmExpression()" << endl;
+ AST::Node expr;
+ if( !parseCastExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_ptrmem ){
+ lex->nextToken();
+
+ if( !parseCastExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseMultiplicativeExpression()" << endl;
+ AST::Node expr;
+ if( !parsePmExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '*' || lex->lookAhead(0) == '/' || lex->lookAhead(0) == '%' ){
+ lex->nextToken();
+
+ if( !parsePmExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Parser::parseAdditiveExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAdditiveExpression()" << endl;
+ AST::Node expr;
+ if( !parseMultiplicativeExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '+' || lex->lookAhead(0) == '-' ){
+ lex->nextToken();
+
+ if( !parseMultiplicativeExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseShiftExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseShiftExpression()" << endl;
+ AST::Node expr;
+ if( !parseAdditiveExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_shift ){
+ lex->nextToken();
+
+ if( !parseAdditiveExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseRelationalExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseRelationalExpression()" << endl;
+ AST::Node expr;
+ if( !parseShiftExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == '<' || (lex->lookAhead(0) == '>' && !templArgs) ||
+ lex->lookAhead(0) == Token_leq || lex->lookAhead(0) == Token_geq ){
+ lex->nextToken();
+
+ if( !parseShiftExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseEqualityExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseEqualityExpression()" << endl;
+ AST::Node expr;
+ if( !parseRelationalExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_eq || lex->lookAhead(0) == Token_not_eq ){
+ lex->nextToken();
+
+ if( !parseRelationalExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseAndExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAndExpression()" << endl;
+ AST::Node expr;
+ if( !parseEqualityExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '&' ){
+ lex->nextToken();
+
+ if( !parseEqualityExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExclusiveOrExpression()" << endl;
+ AST::Node expr;
+ if( !parseAndExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '^' ){
+ lex->nextToken();
+
+ if( !parseAndExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseInclusiveOrExpression()" << endl;
+ AST::Node expr;
+ if( !parseExclusiveOrExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == '|' ){
+ lex->nextToken();
+
+ if( !parseExclusiveOrExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression( AST::Node& /*node*/, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalAndExpression()" << endl;
+
+ AST::Node expr;
+ if( !parseInclusiveOrExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_and ){
+ lex->nextToken();
+
+ if( !parseInclusiveOrExpression(expr, templArgs) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression( AST::Node& node, bool templArgs )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseLogicalOrExpression()" << endl;
+
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !parseLogicalAndExpression(expr, templArgs) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_or ){
+ lex->nextToken();
+
+ if( !parseLogicalAndExpression(expr, templArgs) )
+ return false;
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConditionalExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConditionalExpression()" << endl;
+ AST::Node expr;
+ if( !parseLogicalOrExpression(expr) )
+ return false;
+
+ if( lex->lookAhead(0) == '?' ){
+ lex->nextToken();
+
+ if( !parseExpression(expr) )
+ return false;
+
+ CHECK( ':', ":" );
+
+ if( !parseAssignmentExpression(expr) )
+ return false;
+ }
+
+ return true;
+}
+
+bool Parser::parseAssignmentExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseAssignmentExpression()" << endl;
+ int start = lex->index();
+ AST::Node expr;
+ if( lex->lookAhead(0) == Token_throw && !parseThrowExpression(expr) )
+ return false;
+ else if( !parseConditionalExpression(expr) )
+ return false;
+
+ while( lex->lookAhead(0) == Token_assign || lex->lookAhead(0) == '=' ){
+ lex->nextToken();
+
+ if( !parseConditionalExpression(expr) )
+ return false;
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConstantExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseConstantExpression()" << endl;
+ int start = lex->index();
+ if( parseConditionalExpression(node) ){
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+ }
+ return false;
+}
+
+bool Parser::parseExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseExpression()" << endl;
+
+ int start = lex->index();
+
+ if( !parseCommaExpression(node) )
+ return false;
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseCommaExpression( AST::Node& node )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseCommaExpression()" << endl;
+ int start = lex->index();
+
+ AST::Node expr;
+ if( !parseAssignmentExpression(expr) )
+ return false;
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+
+ if( !parseAssignmentExpression(expr) )
+ return false;
+ if (!comment.isEmpty())
+ expr->setComment(comment);
+ }
+
+ AST::Node ast = CreateNode<AST>();
+ UPDATE_POS( ast, start, lex->index() );
+ node = ast;
+ return true;
+}
+
+bool Parser::parseThrowExpression( AST::Node& /*node*/ )
+{
+ //kdDebug(9007)<< "--- tok = " << lex->lookAhead(0).text() << " -- " << "Parser::parseThrowExpression()" << endl;
+ if( lex->lookAhead(0) != Token_throw )
+ return false;
+
+ CHECK( Token_throw, "throw" );
+ AST::Node expr;
+ if( !parseAssignmentExpression(expr) )
+ return false;
+
+ return true;
+}
+
+bool Parser::parseIvarDeclList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDecls( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvars( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIvarDeclarator( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMethodDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseUnarySelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordSelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseSelector( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordDecl( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseReceiver( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcMessageExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMessageArgs( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordArgList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordArg( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseReservedWord( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMyParms( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseMyParm( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseOptParmList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcSelectorExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseSelectorArg( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordNameList( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseKeywordName( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcEncodeExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcString( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseProtocolRefs( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseIdentifierList( GroupAST::Node & node )
+{
+ int start = lex->index();
+
+ if( lex->lookAhead(0) != Token_identifier )
+ return false;
+
+ GroupAST::Node ast = CreateNode<GroupAST>();
+
+ AST_FROM_TOKEN( tk, lex->index() );
+ ast->addNode( tk );
+ lex->nextToken();
+
+ QString comment;
+ while( lex->lookAhead(0) == ',' ){
+ comment = QString::null;
+ advanceAndCheckTrailingComment( comment );
+ if( lex->lookAhead(0) == Token_identifier ){
+ AST_FROM_TOKEN( tk, lex->index() );
+ ast->addNode( tk );
+ lex->nextToken();
+ }
+ ADVANCE( Token_identifier, "identifier" );
+ }
+
+ node = ast;
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+}
+
+bool Parser::parseIdentifierColon( AST::Node & node )
+{
+ Q_UNUSED( node );
+
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(1) == ':' ){
+ lex->nextToken();
+ lex->nextToken();
+ return true;
+ } // ### else if PTYPENAME -> return true ;
+
+ return false;
+}
+
+bool Parser::parseObjcProtocolExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcOpenBracketExpr( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcCloseBracket( AST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcClassDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcClassDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_CLASS, "@class" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_PROTOCOL, "@protocol" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcAliasDecl( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+
+ ADVANCE( OBJC_ALIAS, "@alias" );
+
+ GroupAST::Node idList;
+ parseIdentifierList( idList );
+ ADVANCE( ';', ";" );
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseObjcMethodDef( DeclarationAST::Node & node )
+{
+ Q_UNUSED( node );
+ return false;
+}
+
+bool Parser::parseWinDeclSpec( GroupAST::Node & node )
+{
+ if( lex->lookAhead(0) == Token_identifier && lex->lookAhead(0).text() == "__declspec" && lex->lookAhead(1) == '(' ){
+ int start = lex->index();
+ lex->nextToken();
+ lex->nextToken(); // skip '('
+
+ parseIdentifierList( node );
+ ADVANCE( ')', ")" );
+
+ UPDATE_POS( node, start, lex->index() );
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/parser.h b/umbrello/umbrello/codeimport/kdevcppparser/parser.h
new file mode 100644
index 00000000..611ceb14
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/parser.h
@@ -0,0 +1,221 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qvaluestack.h>
+
+struct ParserPrivateData;
+
+class Driver;
+class Lexer;
+class Token;
+struct Error;
+
+class Parser
+{
+public:
+ Parser( Driver* driver, Lexer* lexer );
+ virtual ~Parser();
+
+private:
+ virtual bool reportError( const Error& err );
+ /** @todo remove*/ virtual bool reportError( const QString& msg );
+ /** @todo remove*/ virtual void syntaxError();
+
+public: /*rules*/
+
+ bool parseTranslationUnit( TranslationUnitAST::Node& node );
+
+ bool parseDeclaration( DeclarationAST::Node& node );
+ bool parseBlockDeclaration( DeclarationAST::Node& node );
+ bool parseLinkageSpecification( DeclarationAST::Node& node );
+ bool parseLinkageBody( LinkageBodyAST::Node& node );
+ bool parseNamespace( DeclarationAST::Node& node );
+ bool parseNamespaceAliasDefinition( DeclarationAST::Node& node );
+ bool parseUsing( DeclarationAST::Node& node );
+ bool parseUsingDirective( DeclarationAST::Node& node );
+ bool parseTypedef( DeclarationAST::Node& node );
+ bool parseAsmDefinition( DeclarationAST::Node& node );
+ bool parseTemplateDeclaration( DeclarationAST::Node& node );
+ bool parseDeclarationInternal( DeclarationAST::Node& node, QString& comment );
+
+ bool parseUnqualifiedName( ClassOrNamespaceNameAST::Node& node );
+ bool parseStringLiteral( AST::Node& node );
+ bool parseName( NameAST::Node& node );
+ bool parseOperatorFunctionId( AST::Node& node );
+ bool parseTemplateArgumentList( TemplateArgumentListAST::Node& node, bool reportError=true );
+ bool parseOperator( AST::Node& node );
+ bool parseCvQualify( GroupAST::Node& node );
+ bool parseSimpleTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parsePtrOperator( AST::Node& node );
+ bool parseTemplateArgument( AST::Node& node );
+ bool parseTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseTypeSpecifierOrClassSpec( TypeSpecifierAST::Node& node );
+ bool parseDeclarator( DeclaratorAST::Node& node );
+ bool parseTemplateParameterList( TemplateParameterListAST::Node& node );
+ bool parseTemplateParameter( TemplateParameterAST::Node& node );
+ bool parseStorageClassSpecifier( GroupAST::Node& node );
+ bool parseFunctionSpecifier( GroupAST::Node& node );
+ bool parseInitDeclaratorList( InitDeclaratorListAST::Node& node );
+ bool parseInitDeclarator( InitDeclaratorAST::Node& node );
+ bool parseParameterDeclarationClause( ParameterDeclarationClauseAST::Node& node );
+ bool parseCtorInitializer( AST::Node& node );
+ bool parsePtrToMember( AST::Node& node );
+ bool parseEnumSpecifier( TypeSpecifierAST::Node& node );
+ bool parseClassSpecifier( TypeSpecifierAST::Node& node );
+ bool parseWinDeclSpec( GroupAST::Node& node );
+ bool parseElaboratedTypeSpecifier( TypeSpecifierAST::Node& node );
+ bool parseDeclaratorId( NameAST::Node& node );
+ bool parseExceptionSpecification( GroupAST::Node& node );
+ bool parseEnumerator( EnumeratorAST::Node& node );
+ bool parseTypeParameter( TypeParameterAST::Node& node );
+ bool parseParameterDeclaration( ParameterDeclarationAST::Node& node );
+ bool parseTypeId( AST::Node& node );
+ bool parseAbstractDeclarator( DeclaratorAST::Node& node );
+ bool parseParameterDeclarationList( ParameterDeclarationListAST::Node& node );
+ bool parseMemberSpecification( DeclarationAST::Node& node );
+ bool parseAccessSpecifier( AST::Node& node );
+ bool parseTypeIdList( GroupAST::Node& node );
+ bool parseMemInitializerList( AST::Node& node );
+ bool parseMemInitializer( AST::Node& node );
+ bool parseInitializer( AST::Node& node );
+ bool parseBaseClause( BaseClauseAST::Node& node );
+ bool parseBaseSpecifier( BaseSpecifierAST::Node& node );
+ bool parseInitializerClause( AST::Node& node );
+ bool parseMemInitializerId( NameAST::Node& node );
+ bool parseFunctionBody( StatementListAST::Node& node );
+
+ // expression
+ bool skipExpression( AST::Node& node );
+ bool skipCommaExpression( AST::Node& node );
+ bool skipExpressionStatement( StatementAST::Node& node );
+
+ bool parseExpression( AST::Node& node );
+ bool parsePrimaryExpression( AST::Node& node );
+ bool parsePostfixExpression( AST::Node& node );
+ bool parseUnaryExpression( AST::Node& node );
+ bool parseNewExpression( AST::Node& node );
+ bool parseNewTypeId( AST::Node& node );
+ bool parseNewDeclarator( AST::Node& node );
+ bool parseNewInitializer( AST::Node& node );
+ bool parseDeleteExpression( AST::Node& node );
+ bool parseCastExpression( AST::Node& node );
+ bool parsePmExpression( AST::Node& node );
+ bool parseMultiplicativeExpression( AST::Node& node );
+ bool parseAdditiveExpression( AST::Node& node );
+ bool parseShiftExpression( AST::Node& node );
+ bool parseRelationalExpression( AST::Node& node, bool templArgs=false );
+ bool parseEqualityExpression( AST::Node& node, bool templArgs=false );
+ bool parseAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseExclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseInclusiveOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalAndExpression( AST::Node& node, bool templArgs=false );
+ bool parseLogicalOrExpression( AST::Node& node, bool templArgs=false );
+ bool parseConditionalExpression( AST::Node& node );
+ bool parseAssignmentExpression( AST::Node& node );
+ bool parseConstantExpression( AST::Node& node );
+ bool parseCommaExpression( AST::Node& node );
+ bool parseThrowExpression( AST::Node& node );
+
+ // statement
+ bool parseCondition( ConditionAST::Node& node );
+ bool parseStatement( StatementAST::Node& node );
+ bool parseWhileStatement( StatementAST::Node& node );
+ bool parseDoStatement( StatementAST::Node& node );
+ bool parseForStatement( StatementAST::Node& node );
+ bool parseCompoundStatement( StatementAST::Node& node );
+ bool parseForInitStatement( StatementAST::Node& node );
+ bool parseIfStatement( StatementAST::Node& node );
+ bool parseSwitchStatement( StatementAST::Node& node );
+ bool parseLabeledStatement( StatementAST::Node& node );
+ bool parseDeclarationStatement( StatementAST::Node& node );
+ bool parseTryBlockStatement( StatementAST::Node& node );
+
+ // objective c
+ bool parseObjcDef( DeclarationAST::Node& node );
+ bool parseObjcClassDef( DeclarationAST::Node& node );
+ bool parseObjcClassDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDecl( DeclarationAST::Node& node );
+ bool parseObjcAliasDecl( DeclarationAST::Node& node );
+ bool parseObjcProtocolDef( DeclarationAST::Node& node );
+ bool parseObjcMethodDef( DeclarationAST::Node& node );
+
+ bool parseIvarDeclList( AST::Node& node );
+ bool parseIvarDecls( AST::Node& node );
+ bool parseIvarDecl( AST::Node& node );
+ bool parseIvars( AST::Node& node );
+ bool parseIvarDeclarator( AST::Node& node );
+ bool parseMethodDecl( AST::Node& node );
+ bool parseUnarySelector( AST::Node& node );
+ bool parseKeywordSelector( AST::Node& node );
+ bool parseSelector( AST::Node& node );
+ bool parseKeywordDecl( AST::Node& node );
+ bool parseReceiver( AST::Node& node );
+ bool parseObjcMessageExpr( AST::Node& node );
+ bool parseMessageArgs( AST::Node& node );
+ bool parseKeywordExpr( AST::Node& node );
+ bool parseKeywordArgList( AST::Node& node );
+ bool parseKeywordArg( AST::Node& node );
+ bool parseReservedWord( AST::Node& node );
+ bool parseMyParms( AST::Node& node );
+ bool parseMyParm( AST::Node& node );
+ bool parseOptParmList( AST::Node& node );
+ bool parseObjcSelectorExpr( AST::Node& node );
+ bool parseSelectorArg( AST::Node& node );
+ bool parseKeywordNameList( AST::Node& node );
+ bool parseKeywordName( AST::Node& node );
+ bool parseObjcEncodeExpr( AST::Node& node );
+ bool parseObjcString( AST::Node& node );
+ bool parseProtocolRefs( AST::Node& node );
+ bool parseIdentifierList( GroupAST::Node& node );
+ bool parseIdentifierColon( AST::Node& node );
+ bool parseObjcProtocolExpr( AST::Node& node );
+ bool parseObjcOpenBracketExpr( AST::Node& node );
+ bool parseObjcCloseBracket( AST::Node& node );
+
+ void advanceAndCheckTrailingComment(QString& comment);
+
+ bool skipUntil( int token );
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip( int l, int r );
+ QString toString( int start, int end, const QString& sep=" " ) const;
+
+private:
+ ParserPrivateData* d;
+ Driver* m_driver;
+ Lexer* lex;
+ int m_problems;
+ int m_maxProblems;
+ bool objcp;
+
+private:
+ Parser( const Parser& source );
+ void operator = ( const Parser& source );
+};
+
+
+#endif
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp
new file mode 100644
index 00000000..7f9210e2
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.cpp
@@ -0,0 +1,207 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "tree_parser.h"
+#include <kdebug.h>
+
+TreeParser::TreeParser()
+{
+}
+
+TreeParser::~TreeParser()
+{
+}
+
+void TreeParser::parseTranslationUnit( TranslationUnitAST* translationUnit )
+{
+ //kdDebug(9007) << "TreeParser::parseTranslationUnit()" << endl;
+
+ QPtrList<DeclarationAST> declarations = translationUnit->declarationList();
+ QPtrListIterator<DeclarationAST> it( declarations );
+ while( it.current() ){
+ parseDeclaration( it.current() );
+ ++it;
+ }
+}
+
+void TreeParser::parseDeclaration( DeclarationAST* declaration )
+{
+ //kdDebug(9007) << "TreeParser::parseDeclaration()" << endl;
+
+ if( !declaration )
+ return;
+
+ switch( declaration->nodeType() )
+ {
+ case NodeType_LinkageSpecification:
+ parseLinkageSpecification( static_cast<LinkageSpecificationAST*>(declaration) );
+ break;
+
+ case NodeType_Namespace:
+ parseNamespace( static_cast<NamespaceAST*>(declaration) );
+ break;
+
+ case NodeType_NamespaceAlias:
+ parseNamespaceAlias( static_cast<NamespaceAliasAST*>(declaration) );
+ break;
+
+ case NodeType_Using:
+ parseUsing( static_cast<UsingAST*>(declaration) );
+ break;
+
+ case NodeType_UsingDirective:
+ parseUsingDirective( static_cast<UsingDirectiveAST*>(declaration) );
+ break;
+
+ case NodeType_Typedef:
+ parseTypedef( static_cast<TypedefAST*>(declaration) );
+ break;
+
+ case NodeType_TemplateDeclaration:
+ parseTemplateDeclaration( static_cast<TemplateDeclarationAST*>(declaration) );
+ break;
+
+ case NodeType_SimpleDeclaration:
+ parseSimpleDeclaration( static_cast<SimpleDeclarationAST*>(declaration) );
+ break;
+
+ case NodeType_FunctionDefinition:
+ parseFunctionDefinition( static_cast<FunctionDefinitionAST*>(declaration) );
+ break;
+
+ case NodeType_AccessDeclaration:
+ parseAccessDeclaration( static_cast<AccessDeclarationAST*>(declaration) );
+ break;
+ }
+}
+
+void TreeParser::parseLinkageSpecification( LinkageSpecificationAST* ast )
+{
+ //kdDebug(9007) << "TreeParser::parseLinkageSpecification()" << endl;
+ if( ast->linkageBody() )
+ parseLinkageBody( ast->linkageBody() );
+ else if( ast->declaration() )
+ parseDeclaration( ast->declaration() );
+}
+
+void TreeParser::parseNamespace( NamespaceAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseNamespace()" << endl;
+ if( decl->linkageBody() )
+ parseLinkageBody( decl->linkageBody() );
+}
+
+void TreeParser::parseNamespaceAlias( NamespaceAliasAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseNamespaceAlias()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseUsing( UsingAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseUsing()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseUsingDirective( UsingDirectiveAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseUsingDirective()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseTypedef( TypedefAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseTypedef()" << endl;
+ if( decl->typeSpec() )
+ parseTypeSpecifier( decl->typeSpec() );
+}
+
+void TreeParser::parseTemplateDeclaration( TemplateDeclarationAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseTemplateDeclaration()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseSimpleDeclaration( SimpleDeclarationAST* decl )
+{
+ //kdDebug(9007) << "TreeParser::parseSimpleDeclaration()" << endl;
+ Q_UNUSED( decl );
+}
+
+void TreeParser::parseFunctionDefinition( FunctionDefinitionAST* def )
+{
+ //kdDebug(9007) << "TreeParser::parseFunctionDefinition()" << endl;
+ Q_UNUSED( def );
+}
+
+void TreeParser::parseLinkageBody( LinkageBodyAST* linkageBody )
+{
+ //kdDebug(9007) << "TreeParser::parseLinkageBody()" << endl;
+ QPtrList<DeclarationAST> declarations = linkageBody->declarationList();
+ for( QPtrListIterator<DeclarationAST> it(declarations); it.current(); ++it ){
+ parseDeclaration( it.current() );
+ }
+}
+
+void TreeParser::parseTypeSpecifier( TypeSpecifierAST* typeSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseTypeSpecifier()" << endl;
+ switch( typeSpec->nodeType() )
+ {
+ case NodeType_ClassSpecifier:
+ parseClassSpecifier( static_cast<ClassSpecifierAST*>(typeSpec) );
+ break;
+
+ case NodeType_EnumSpecifier:
+ parseEnumSpecifier( static_cast<EnumSpecifierAST*>(typeSpec) );
+ break;
+
+ case NodeType_ElaboratedTypeSpecifier:
+ parseElaboratedTypeSpecifier( static_cast<ElaboratedTypeSpecifierAST*>(typeSpec) );
+ break;
+ }
+}
+
+void TreeParser::parseClassSpecifier( ClassSpecifierAST* classSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseClassSpecifier()" << endl;
+ QPtrList<DeclarationAST> declarations = classSpec->declarationList();
+ for( QPtrListIterator<DeclarationAST> it(declarations); it.current(); ++it ){
+ parseDeclaration( it.current() );
+ }
+}
+
+void TreeParser::parseEnumSpecifier( EnumSpecifierAST* enumSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseEnumSpecifier()" << endl;
+ Q_UNUSED( enumSpec );
+}
+
+void TreeParser::parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* typeSpec )
+{
+ //kdDebug(9007) << "TreeParser::parseElaboratedTypeSpecifier()" << endl;
+ Q_UNUSED( typeSpec );
+}
+
+void TreeParser::parseAccessDeclaration ( AccessDeclarationAST * access )
+{
+ //kdDebug(9007) << "TreeParser::parseAccessDeclaration()" << endl;
+ Q_UNUSED( access );
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h
new file mode 100644
index 00000000..42059408
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/tree_parser.h
@@ -0,0 +1,59 @@
+/* This file is part of KDevelop
+ Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __tree_parser_h
+#define __tree_parser_h
+
+#include "ast.h"
+
+class TreeParser
+{
+public:
+ TreeParser();
+ virtual ~TreeParser();
+
+ // translation-unit
+ virtual void parseTranslationUnit( TranslationUnitAST* );
+
+ // declarations
+ virtual void parseDeclaration( DeclarationAST* );
+ virtual void parseLinkageSpecification( LinkageSpecificationAST* );
+ virtual void parseNamespace( NamespaceAST* );
+ virtual void parseNamespaceAlias( NamespaceAliasAST* );
+ virtual void parseUsing( UsingAST* );
+ virtual void parseUsingDirective( UsingDirectiveAST* );
+ virtual void parseTypedef( TypedefAST* );
+ virtual void parseTemplateDeclaration( TemplateDeclarationAST* );
+ virtual void parseSimpleDeclaration( SimpleDeclarationAST* );
+ virtual void parseFunctionDefinition( FunctionDefinitionAST* );
+ virtual void parseLinkageBody( LinkageBodyAST* );
+ virtual void parseAccessDeclaration( AccessDeclarationAST* );
+
+ // type-specifier
+ virtual void parseTypeSpecifier( TypeSpecifierAST* );
+ virtual void parseClassSpecifier( ClassSpecifierAST* );
+ virtual void parseEnumSpecifier( EnumSpecifierAST* );
+ virtual void parseElaboratedTypeSpecifier( ElaboratedTypeSpecifierAST* );
+
+private:
+ TreeParser( const TreeParser& source );
+ void operator = ( const TreeParser& source );
+};
+
+#endif // __tree_parser_h
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp
new file mode 100644
index 00000000..a2fd29dd
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.cpp
@@ -0,0 +1,310 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Julian Rockey <linux@jrockey.com>
+ Copyright (C) 2003 Alexander Dymo <cloudtemple@mksat.net>
+ Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "urlutil.h"
+
+#include <qstringlist.h>
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <kdebug.h>
+
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <kdeversion.h>
+#if (KDE_VERSION_MINOR==0) && (KDE_VERSION_MAJOR==3)
+#include <kdevkurl.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Namespace URLUtil
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::filename(const QString & name) {
+ int slashPos = name.findRev("/");
+ return slashPos<0 ? name : name.mid(slashPos+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::directory(const QString & name) {
+ int slashPos = name.findRev("/");
+ return slashPos<0 ? QString("") : name.left(slashPos);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePath(const KURL & parent, const KURL & child, uint slashPolicy) {
+ bool slashPrefix = slashPolicy & SLASH_PREFIX;
+ bool slashSuffix = slashPolicy & SLASH_SUFFIX;
+ if (parent == child)
+ return slashPrefix ? QString("/") : QString("");
+
+ if (!parent.isParentOf(child)) return QString();
+ int a=slashPrefix ? -1 : 1;
+ int b=slashSuffix ? 1 : -1;
+ return child.path(b).mid(parent.path(a).length());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePath(const QString & parent, const QString & child, uint slashPolicy) {
+ return relativePath(KURL(parent), KURL(child), slashPolicy);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::upDir(const QString & path, bool slashSuffix) {
+ int slashPos = path.findRev("/");
+ if (slashPos<1) return QString::null;
+ return path.mid(0,slashPos+ (slashSuffix ? 1 : 0) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+KURL URLUtil::mergeURL(const KURL & source, const KURL & dest, const KURL & child) {
+
+ // if already a child of source, then fine
+ if (source.isParentOf(child) || source == child) return child;
+
+ // if not a child of dest, return blank URL (error)
+ if (!dest.isParentOf(child) && dest != child) return KURL();
+
+ // if child is same as dest, return source
+ if (dest == child) return source;
+
+ // calculate
+ QString childUrlStr = child.url(-1);
+ QString destStemStr = dest.url(1);
+ QString sourceStemStr = source.url(1);
+ return KURL(sourceStemStr.append( childUrlStr.mid( destStemStr.length() ) ) );
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::getExtension(const QString & path) {
+ int dotPos = path.findRev('.');
+ if (dotPos<0) return QString("");
+ return path.mid(dotPos+1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const KURL &baseDirUrl, const KURL &url )
+{
+ QString absBase = extractPathNameAbsolute( baseDirUrl ),
+ absRef = extractPathNameAbsolute( url );
+ int i = absRef.find( absBase, 0, true );
+
+ if (i == -1)
+ return QString();
+
+ if (absRef == absBase)
+ return QString( "." );
+ else
+ return absRef.replace( 0, absBase.length(), QString() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const QString &basePath, const KURL &url )
+{
+#if (KDE_VERSION_MINOR!=0) || (KDE_VERSION_MAJOR!=3)
+ KURL baseDirUrl = KURL::fromPathOrURL( basePath );
+#else
+ KURL baseDirUrl = KdevKURL::fromPathOrURL( basePath );
+#endif
+ return extractPathNameRelative( baseDirUrl, url );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameRelative(const QString &basePath, const QString &absFilePath )
+{
+#if (KDE_VERSION_MINOR!=0) || (KDE_VERSION_MAJOR!=3)
+ KURL baseDirUrl = KURL::fromPathOrURL( basePath ),
+ fileUrl = KURL::fromPathOrURL( absFilePath );
+#else
+ KURL baseDirUrl = KdevKURL::fromPathOrURL( basePath ),
+ fileUrl = KdevKURL::fromPathOrURL( absFilePath );
+#endif
+ return extractPathNameRelative( baseDirUrl, fileUrl );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::extractPathNameAbsolute( const KURL &url )
+{
+ if (isDirectory( url ))
+ return url.path( +1 ); // with trailing "/" if none is present
+ else
+ {
+ // Ok, this is an over-tight pre-condition on "url" since I hope nobody will never
+ // stress this function with absurd cases ... but who knows?
+ /*
+ QString path = url.path();
+ QFileInfo fi( path ); // Argh: QFileInfo is back ;))
+ return ( fi.exists()? path : QString() );
+ */
+ return url.path();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool URLUtil::isDirectory( const KURL &url )
+{
+ return isDirectory( url.path() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool URLUtil::isDirectory( const QString &absFilePath )
+{
+ return QDir( absFilePath ).exists();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void URLUtil::dump( const KURL::List &urls, const QString &aMessage )
+{
+ if (!aMessage.isNull())
+ {
+ kdDebug(9000) << aMessage << endl;
+ }
+ kdDebug(9000) << " List has " << urls.count() << " elements." << endl;
+
+ for (size_t i = 0; i<urls.count(); ++i)
+ {
+ KURL url = urls[ i ];
+// kdDebug(9000) << " * Element = " << url.path() << endl;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QStringList URLUtil::toRelativePaths( const QString &baseDir, const KURL::List &urls)
+{
+ QStringList paths;
+
+ for (size_t i=0; i<urls.count(); ++i)
+ {
+ paths << extractPathNameRelative( baseDir, urls[i] );
+ }
+
+ return paths;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+QString URLUtil::relativePathToFile( const QString & dirUrl, const QString & fileUrl )
+{
+ if (dirUrl.isEmpty() || (dirUrl == "/"))
+ return fileUrl;
+
+ QStringList dir = QStringList::split("/", dirUrl, false);
+ QStringList file = QStringList::split("/", fileUrl, false);
+
+ QString resFileName = file.last();
+ file.remove(file.last());
+
+ uint i = 0;
+ while ( (i < dir.count()) && (i < (file.count())) && (dir[i] == file[i]) )
+ i++;
+
+ QString result_up;
+ QString result_down;
+ QString currDir;
+ QString currFile;
+ do
+ {
+ i >= dir.count() ? currDir = "" : currDir = dir[i];
+ i >= file.count() ? currFile = "" : currFile = file[i];
+ qWarning("i = %d, currDir = %s, currFile = %s", i, currDir.latin1(), currFile.latin1());
+ if (currDir.isEmpty() && currFile.isEmpty())
+ break;
+ else if (currDir.isEmpty())
+ result_down += file[i] + '/';
+ else if (currFile.isEmpty())
+ result_up += "../";
+ else
+ {
+ result_down += file[i] + '/';
+ result_up += "../";
+ }
+ i++;
+ }
+ while ( (!currDir.isEmpty()) || (!currFile.isEmpty()) );
+
+ return result_up + result_down + resFileName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// code from qt-3.1.2 version of QDir::canonicalPath()
+QString URLUtil::canonicalPath( const QString & path )
+{
+ QString r;
+ char cur[PATH_MAX+1];
+ if ( ::getcwd( cur, PATH_MAX ) )
+ {
+ char tmp[PATH_MAX+1];
+ if( ::realpath( QFile::encodeName( path ), tmp ) )
+ {
+ r = QFile::decodeName( tmp );
+ }
+ //always make sure we go back to the current dir
+ ::chdir( cur );
+ }
+ return r;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//written by "Dawit A." <adawit@kde.org>
+//borrowed from his patch to KShell
+QString URLUtil::envExpand ( const QString& str )
+{
+ uint len = str.length();
+
+ if (len > 1 && str[0] == '$')
+ {
+ int pos = str.find ('/');
+
+ if (pos < 0)
+ pos = len;
+
+ char* ret = getenv( QConstString(str.unicode()+1, pos-1).string().local8Bit().data() );
+
+ if (ret)
+ {
+ QString expandedStr ( QFile::decodeName( ret ) );
+ if (pos < (int)len)
+ expandedStr += str.mid(pos);
+ return expandedStr;
+ }
+ }
+
+ return str;
+}
+
diff --git a/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h
new file mode 100644
index 00000000..3460d28b
--- /dev/null
+++ b/umbrello/umbrello/codeimport/kdevcppparser/urlutil.h
@@ -0,0 +1,132 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Julian Rockey <linux@jrockey.com>
+ Copyright (C) 2003 Mario Scalas <mario.scalas@libero.it>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _URLUTIL_H_
+#define _URLUTIL_H_
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <kurl.h>
+
+namespace URLUtil
+{
+ enum SlashesPosition { SLASH_PREFIX = 1, SLASH_SUFFIX = 2 };
+
+ /**
+ * Returns the filename part of a pathname (i.e. everything past the last slash)
+ */
+ QString filename(const QString & pathName);
+ /**
+ * Returns the directory part of a path (i.e. everything up to but not including the last slash)
+ */
+ QString directory(const QString & pathName);
+ /**
+ * Returns the relative path between a parent and child URL, or blank if the specified child is not a child of parent
+ */
+ QString relativePath(const KURL & parent, const KURL & child, uint slashPolicy = SLASH_PREFIX);
+ /**
+ * Returns the relative path between a parent and child URL, or blank if the specified child is not a child of parent
+ */
+ QString relativePath(const QString & parent, const QString & child, uint slashPolicy = SLASH_PREFIX);
+ /**
+ * Returns the relative path between a directory and file. Should never return empty path.
+ * Example:
+ * dirUrl: /home/test/src
+ * fileUrl: /home/test/lib/mylib.cpp
+ * returns: ../lib/mylib.cpp
+ */
+ QString relativePathToFile( const QString & dirUrl, const QString & fileUrl );
+ /**
+ *Returns the path 'up one level' - the opposite of what filename returns
+ */
+ QString upDir(const QString & path, bool slashSuffix = false);
+ /**
+ * 'Merges' URLs - changes a URL that starts with dest to start with source instead
+ * Example:
+ * source is /home/me/
+ * dest is /home/you/
+ * child is /home/you/dir1/file1
+ * returns /home/me/dir1/fil1
+ */
+ KURL mergeURL(const KURL & source, const KURL & dest, const KURL & child);
+ /**
+ * Returns the file extension for a filename or path
+ */
+ QString getExtension(const QString & path);
+
+ /**
+ * Given a base directory url in @p baseDirUrl and the url referring to a date sub-directory or file,
+ * it will return the path relative to @p baseDirUrl.
+ * If baseDirUrl == url.path() then it will return ".".
+ * <code>
+ * KURL baseUrl, dirUrl;
+ * baseUrl.setPath( "/home/mario/src/kdevelop/" );
+ * dirUrl.setPath( "/home/mario/src/kdevelop/parts/cvs/" );
+ * QString relPathName = extractDirPathRelative( baseUrl, url ); // == "parts/cvs/"
+ * QString absPathName = extractDirPathAbsolute( url ); // == "/home/mario/src/kdevelop/parts/cvs/"
+ * </code>
+ * Note that if you pass a file name in @p url (instead of a directory) or the @p baseUrl is not contained
+ * in @p url then the function will return "" (void string).
+ */
+ QString extractPathNameRelative(const KURL &baseDirUrl, const KURL &url );
+ QString extractPathNameRelative(const QString &basePath, const KURL &url );
+ QString extractPathNameRelative(const QString &basePath, const QString &absFilePath );
+
+ /**
+ * Will return the absolute path name referred in @p url.
+ * Look at above for an example.
+ */
+ QString extractPathNameAbsolute( const KURL &url );
+
+ /**
+ * Returns a QStringList of relative (to @p baseDir) paths from a list of KURLs in @p urls
+ */
+ QStringList toRelativePaths( const QString &baseDir, const KURL::List &urls);
+
+ /**
+ * If @p url is a directory will return true, false otherwise.
+ */
+ bool isDirectory( const KURL &url );
+ bool isDirectory( const QString &absFilePath );
+
+ /**
+ * Will dump the list of KURL @p urls on standard output, eventually printing @ aMessage if it
+ * is not null.
+ */
+ void dump( const KURL::List &urls, const QString &aMessage = QString::null );
+
+ /**
+ * Same as QDir::canonicalPath in later versions of QT. Earlier versions of QT
+ * had this broken, so it's reproduced here.
+ */
+ QString canonicalPath( const QString & path );
+
+ /**
+ * Performs environment variable expansion on @p variable.
+ *
+ * @param variable the string with the environment variable to expand.
+ * @return the expanded environment variable value. if the variable
+ * cannot be expanded, @p variable itself is returned.
+ */
+ QString envExpand ( const QString &variable );
+
+}
+
+#endif
diff --git a/umbrello/umbrello/codeimport/nativeimportbase.cpp b/umbrello/umbrello/codeimport/nativeimportbase.cpp
new file mode 100644
index 00000000..058b4d19
--- /dev/null
+++ b/umbrello/umbrello/codeimport/nativeimportbase.cpp
@@ -0,0 +1,340 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "nativeimportbase.h"
+
+// qt/kde includes
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <klocale.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+
+NativeImportBase::NativeImportBase(const QString &singleLineCommentIntro) {
+ m_singleLineCommentIntro = singleLineCommentIntro;
+ m_srcIndex = 0;
+ m_scopeIndex = 0; // index 0 is reserved for global scope
+ m_klass = NULL;
+ m_currentAccess = Uml::Visibility::Public;
+ m_isAbstract = false;
+ m_inComment = false;
+}
+
+NativeImportBase::~NativeImportBase() {
+}
+
+void NativeImportBase::setMultiLineComment(const QString &intro, const QString &end) {
+ m_multiLineCommentIntro = intro;
+ m_multiLineCommentEnd = end;
+}
+
+void NativeImportBase::setMultiLineAltComment(const QString &intro, const QString &end) {
+ m_multiLineAltCommentIntro = intro;
+ m_multiLineAltCommentEnd = end;
+}
+
+void NativeImportBase::skipStmt(QString until /* = ";" */) {
+ const uint srcLength = m_source.count();
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != until)
+ m_srcIndex++;
+}
+
+bool NativeImportBase::skipToClosing(QChar opener) {
+ QString closing;
+ switch (opener) {
+ case '{':
+ closing = "}";
+ break;
+ case '[':
+ closing = "]";
+ break;
+ case '(':
+ closing = ")";
+ break;
+ case '<':
+ closing = ">";
+ break;
+ default:
+ kError() << "NativeImportBase::skipToClosing(" << opener
+ << "): " << "illegal input character" << endl;
+ return false;
+ }
+ const QString opening(opener);
+ skipStmt(opening);
+ const uint srcLength = m_source.count();
+ int nesting = 0;
+ while (m_srcIndex < srcLength) {
+ QString nextToken = advance();
+ if (nextToken.isEmpty())
+ break;
+ if (nextToken == closing) {
+ if (nesting <= 0)
+ break;
+ nesting--;
+ } else if (nextToken == opening) {
+ nesting++;
+ }
+ }
+ if (m_srcIndex == srcLength)
+ return false;
+ return true;
+}
+
+QString NativeImportBase::advance() {
+ while (m_srcIndex < m_source.count() - 1) {
+ if (m_source[++m_srcIndex].startsWith(m_singleLineCommentIntro))
+ m_comment += m_source[m_srcIndex];
+ else
+ break;
+ }
+ if (m_srcIndex >= m_source.count() - 1 ||
+ // if last item in m_source is a comment then it is dropped too
+ (m_srcIndex == m_source.count() - 1 &&
+ m_source[m_srcIndex].startsWith(m_singleLineCommentIntro))) {
+ return QString();
+ }
+ return m_source[m_srcIndex];
+}
+
+bool NativeImportBase::preprocess(QString& line) {
+ if (m_multiLineCommentIntro.isEmpty())
+ return false;
+ // Check for end of multi line comment.
+ if (m_inComment) {
+ int delimiterLen = 0;
+ int pos = line.find(m_multiLineCommentEnd);
+ if (pos == -1) {
+ if (! m_multiLineAltCommentEnd.isEmpty())
+ pos = line.find(m_multiLineAltCommentEnd);
+ if (pos == -1) {
+ m_comment += line + "\n";
+ return true; // done
+ }
+ delimiterLen = m_multiLineAltCommentEnd.length();
+ } else {
+ delimiterLen = m_multiLineCommentEnd.length();
+ }
+ if (pos > 0) {
+ QString text = line.mid(0, pos - 1);
+ m_comment += text.stripWhiteSpace();
+ }
+ m_source.append(m_singleLineCommentIntro + m_comment); // denotes comments in `m_source'
+ m_srcIndex++;
+ m_comment = "";
+ m_inComment = false;
+ pos += delimiterLen; // pos now points behind the closed comment
+ if (pos == (int)line.length())
+ return true; // done
+ line = line.mid(pos);
+ }
+ // If we get here then m_inComment is false.
+ // Check for start of multi line comment.
+ int delimIntroLen = 0;
+ int delimEndLen = 0;
+ int pos = line.find(m_multiLineCommentIntro);
+ if (pos != -1) {
+ delimIntroLen = m_multiLineCommentIntro.length();
+ } else if (!m_multiLineAltCommentIntro.isEmpty()) {
+ pos = line.find(m_multiLineAltCommentIntro);
+ if (pos != -1)
+ delimIntroLen = m_multiLineAltCommentIntro.length();
+ }
+ if (pos != -1) {
+ int endpos = line.find(m_multiLineCommentEnd);
+ if (endpos != -1) {
+ delimEndLen = m_multiLineCommentEnd.length();
+ } else if (!m_multiLineAltCommentEnd.isEmpty()) {
+ endpos = line.find(m_multiLineAltCommentEnd);
+ if (endpos != -1)
+ delimEndLen = m_multiLineAltCommentEnd.length();
+ }
+ if (endpos == -1) {
+ m_inComment = true;
+ if (pos + delimIntroLen < (int)line.length()) {
+ QString cmnt = line.mid(pos + delimIntroLen);
+ m_comment += cmnt.stripWhiteSpace() + "\n";
+ }
+ if (pos == 0)
+ return true; // done
+ line = line.left(pos);
+ } else { // It's a multiline comment on a single line.
+ if (endpos > pos + delimIntroLen) {
+ QString cmnt = line.mid(pos + delimIntroLen, endpos - pos - delimIntroLen);
+ cmnt = cmnt.stripWhiteSpace();
+ if (!cmnt.isEmpty())
+ m_source.append(m_singleLineCommentIntro + cmnt);
+ }
+ endpos++; // endpos now points at the slash of "*/"
+ QString pre;
+ if (pos > 0)
+ pre = line.left(pos);
+ QString post;
+ if (endpos + delimEndLen < (int)line.length())
+ post = line.mid(endpos + 1);
+ line = pre + post;
+ }
+ }
+ return false; // The input was not completely consumed by preprocessing.
+}
+
+/// Split the line so that a string is returned as a single element of the list,
+/// when not in a string then split at white space.
+QStringList NativeImportBase::split(const QString& lin) {
+ QStringList list;
+ QString listElement;
+ QChar stringIntro = 0; // buffers the string introducer character
+ bool seenSpace = false;
+ QString line = lin.stripWhiteSpace();
+ for (uint i = 0; i < line.length(); i++) {
+ const QChar& c = line[i];
+ if (stringIntro) { // we are in a string
+ listElement += c;
+ if (c == stringIntro) {
+ if (line[i - 1] != '\\') {
+ list.append(listElement);
+ listElement = QString();
+ stringIntro = 0; // we are no longer in a string
+ }
+ }
+ } else if (c == '"' || c == '\'') {
+ if (!listElement.isEmpty()) {
+ list.append(listElement);
+ }
+ listElement = stringIntro = c;
+ seenSpace = false;
+ } else if (c == ' ' || c == '\t') {
+ if (seenSpace)
+ continue;
+ seenSpace = true;
+ if (!listElement.isEmpty()) {
+ list.append(listElement);
+ listElement = QString();
+ }
+ } else {
+ listElement += c;
+ seenSpace = false;
+ }
+ }
+ if (!listElement.isEmpty())
+ list.append(listElement);
+ return list;
+}
+
+/// The lexer. Tokenizes the given string and fills `m_source'.
+/// Stores possible comments in `m_comment'.
+void NativeImportBase::scan(QString line) {
+ if (preprocess(line))
+ return;
+ // Check for single line comment.
+ int pos = line.find(m_singleLineCommentIntro);
+ if (pos != -1) {
+ QString cmnt = line.mid(pos);
+ m_source.append(cmnt);
+ if (pos == 0)
+ return;
+ line = line.left(pos);
+ }
+ if (line.contains(QRegExp("^\\s*$")))
+ return;
+ QStringList words = split(line);
+ for (QStringList::Iterator it = words.begin(); it != words.end(); ++it) {
+ QString word = *it;
+ if (word[0] == '"' || word[0] == '\'')
+ m_source.append(word); // string constants are handled by split()
+ else
+ fillSource(word);
+ }
+}
+
+void NativeImportBase::initVars() {
+}
+
+void NativeImportBase::parseFile(const QString& filename) {
+ QString nameWithoutPath = filename;
+ nameWithoutPath.remove(QRegExp("^.*/"));
+ if (m_parsedFiles.contains(nameWithoutPath))
+ return;
+ m_parsedFiles.append(nameWithoutPath);
+ QString fname = filename;
+ const QString msgPrefix = "NativeImportBase::parseFile(" + filename + "): ";
+ if (filename.contains('/')) {
+ QString path = filename;
+ path.remove( QRegExp("/[^/]+$") );
+ kDebug() << msgPrefix << "adding path " << path << endl;
+ Import_Utils::addIncludePath(path);
+ }
+ if (! QFile::exists(filename)) {
+ if (filename.startsWith("/")) {
+ kError() << msgPrefix << "cannot find file" << endl;
+ return;
+ }
+ bool found = false;
+ QStringList includePaths = Import_Utils::includePathList();
+ for (QStringList::Iterator pathIt = includePaths.begin();
+ pathIt != includePaths.end(); ++pathIt) {
+ QString path = (*pathIt);
+ if (! path.endsWith("/")) {
+ path.append("/");
+ }
+ if (QFile::exists(path + filename)) {
+ fname.prepend(path);
+ found = true;
+ break;
+ }
+ }
+ if (! found) {
+ kError() << msgPrefix << "cannot find file" << endl;
+ return;
+ }
+ }
+ QFile file(fname);
+ if (! file.open(IO_ReadOnly)) {
+ kError() << msgPrefix << "cannot open file" << endl;
+ return;
+ }
+ kDebug() << msgPrefix << "parsing." << endl;
+ // Scan the input file into the QStringList m_source.
+ m_source.clear();
+ m_srcIndex = 0;
+ initVars();
+ QTextStream stream(&file);
+ while (! stream.atEnd()) {
+ QString line = stream.readLine();
+ scan(line);
+ }
+ file.close();
+ // Parse the QStringList m_source.
+ m_klass = NULL;
+ m_currentAccess = Uml::Visibility::Public;
+ m_scopeIndex = 0;
+ m_scope[0] = NULL; // index 0 is reserved for global scope
+ const uint srcLength = m_source.count();
+ for (m_srcIndex = 0; m_srcIndex < srcLength; m_srcIndex++) {
+ const QString& firstToken = m_source[m_srcIndex];
+ //kDebug() << '"' << firstToken << '"' << endl;
+ if (firstToken.startsWith(m_singleLineCommentIntro)) {
+ m_comment = firstToken.mid(m_singleLineCommentIntro.length());
+ continue;
+ }
+ if (! parseStmt())
+ skipStmt();
+ m_comment = QString();
+ }
+ kDebug() << msgPrefix << "end of parse." << endl;
+}
+
+void NativeImportBase::initialize() {
+ m_parsedFiles.clear();
+}
+
diff --git a/umbrello/umbrello/codeimport/nativeimportbase.h b/umbrello/umbrello/codeimport/nativeimportbase.h
new file mode 100644
index 00000000..cc82fd91
--- /dev/null
+++ b/umbrello/umbrello/codeimport/nativeimportbase.h
@@ -0,0 +1,227 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2005-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef NATIVEIMPORTBASE_H
+#define NATIVEIMPORTBASE_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include "classimport.h"
+#include "../umlnamespace.h"
+
+class UMLPackage;
+class UMLClassifier;
+
+/**
+ * Intermediate base class for native Umbrello implementations of
+ * programming language import
+ *
+ * The default call sequence is as follows (RealizedLanguageImport
+ * is used as a placeholder name for the concrete language importer.)
+ * NativeImportBase RealizedLanguageImport
+ * --> importFiles()
+ * parseFile()
+ * -----------------------------------> initVars()
+ * scan()
+ * preprocess() (may be reimplemented)
+ * ---------------------------------> fillSource()
+ * -----------------------------------> parseStmt()
+ * This sequence may be changed by overriding default implementations
+ * of virtual methods in NativeImportBase.
+ *
+ * @short Base class for native implementations of language import
+ * @author Oliver Kellogg <okellogg@users.sourceforge.net>
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class NativeImportBase : public ClassImport {
+public:
+ /**
+ * Constructor
+ * @param singleLineCommentIntro "//" for IDL and Java, "--" for Ada
+ */
+ NativeImportBase(const QString &singleLineCommentIntro);
+ virtual ~NativeImportBase();
+
+protected:
+ /**
+ * Implement abstract operation from ClassImport.
+ */
+ void initialize();
+
+ /**
+ * Set the delimiter strings for a multi line comment.
+ *
+ * @param intro In languages with a C style multiline comment
+ * this is slash-star.
+ * @param end In languages with a C style multiline comment
+ * this is star-slash.
+ */
+ void setMultiLineComment(const QString &intro, const QString &end);
+ /**
+ * Set the delimiter strings for an alternative form of
+ * multi line comment. See setMultiLineComment().
+ */
+ void setMultiLineAltComment(const QString &intro, const QString &end);
+
+ /**
+ * Import a single file.
+ * The default implementation should be feasible for languages that
+ * don't depend on an external preprocessor.
+ *
+ * @param filename The file to import.
+ */
+ virtual void parseFile(const QString& filename);
+
+ /**
+ * Initialize auxiliary variables.
+ * This is called by the default implementation of parseFile()
+ * after scanning (before parsing the QStringList m_source.)
+ * The default implementation is empty.
+ */
+ virtual void initVars();
+
+ /**
+ * Scan a single line.
+ * parseFile() calls this for each line read from the input file.
+ * This in turn calls other methods such as preprocess() and fillSource().
+ *
+ * @param line The line to scan.
+ */
+ void scan(QString line);
+
+ /**
+ * Preprocess a line.
+ * May modify the given line to remove items consumed by the
+ * preprocessing such as comments or preprocessor directives.
+ * The default implementation handles multi-line comments.
+ *
+ * @param line The line to preprocess.
+ * @return True if the line was completely consumed,
+ * false if there are still items left in the line
+ * for further analysis.
+ */
+ virtual bool preprocess(QString& line);
+
+ /**
+ * Split the line so that a string is returned as a single element of the list.
+ * When not in a string then split at white space.
+ * The default implementation is suitable for C style strings and char constants.
+ */
+ virtual QStringList split(const QString& line);
+
+ /**
+ * Analyze the given word and fill `m_source'.
+ * A "word" is a whitespace delimited item from the input line.
+ * To be provided by the specific importer class.
+ */
+ virtual void fillSource(const QString& word) = 0;
+
+ /**
+ * Parse the statement which starts at m_source[m_srcIndex]
+ * leaving m_srcIndex pointing to the end of the recognized
+ * statement.
+ * To be provided by the concrete importer.
+ *
+ * @return True if the statement was recognized.
+ */
+ virtual bool parseStmt() = 0;
+
+ /**
+ * Advance m_srcIndex until m_source[m_srcIndex] contains the lexeme
+ * given by `until'.
+ */
+ void skipStmt(QString until = ";");
+
+ /**
+ * Advance m_srcIndex to the index of the corresponding closing character
+ * of the given opening. Nested opening/closing pairs are respected.
+ * Valid openers are: '{' '[' '(' '<'
+ *
+ * @return True for success, false for misuse (invalid opener) or
+ * if no matching closing character is found in m_source.
+ */
+ bool skipToClosing(QChar opener);
+
+ /**
+ * Advance m_srcIndex until m_source[m_srcIndex] contains a non-comment.
+ * Comments encountered during advancement are accumulated in `m_comment'.
+ * If m_srcIndex hits the end of m_source then QString::null is returned.
+ */
+ QString advance();
+
+ /**
+ * How to start a single line comment in this programming language.
+ */
+ QString m_singleLineCommentIntro;
+
+ /**
+ * The scanned lexemes.
+ */
+ QStringList m_source;
+ /**
+ * Used for indexing m_source.
+ */
+ uint m_srcIndex;
+
+ /**
+ * Stack of scopes for use by the specific importer.
+ */
+ UMLPackage *m_scope[32];
+ /**
+ * Indexes m_scope. Index 0 is reserved for global scope.
+ */
+ uint m_scopeIndex;
+
+ /**
+ * The class currently being processed.
+ */
+ UMLClassifier *m_klass;
+ /**
+ * The current access (public/protected/private)
+ */
+ Uml::Visibility m_currentAccess;
+ /**
+ * Intermediate accumulator for comment text.
+ */
+ QString m_comment;
+ /**
+ * True if we are currently in a multi-line comment.
+ * Only applies to languages with multi-line comments.
+ */
+ bool m_inComment;
+ /**
+ * Accumulator for abstractness
+ */
+ bool m_isAbstract;
+
+ /**
+ * List of parsed files. Contains file names without paths.
+ * Before actually parsing a given file, NativeImportBase checks
+ * whether the name is already present in this list in order to
+ * avoid parsing the same file multiple times.
+ */
+ QStringList m_parsedFiles;
+
+ /**
+ * Multi line comment delimiters
+ */
+ QString m_multiLineCommentIntro;
+ QString m_multiLineCommentEnd;
+ /**
+ * Some languages support an alternative set of multi line
+ * comment delimiters.
+ */
+ QString m_multiLineAltCommentIntro;
+ QString m_multiLineAltCommentEnd;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/pascalimport.cpp b/umbrello/umbrello/codeimport/pascalimport.cpp
new file mode 100644
index 00000000..ffe291ff
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pascalimport.cpp
@@ -0,0 +1,413 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006-2007 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "pascalimport.h"
+
+#include <stdio.h>
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+PascalImport::PascalImport() : NativeImportBase("//") {
+ setMultiLineComment("(*", "*)");
+ setMultiLineAltComment("{", "}");
+ initVars();
+}
+
+PascalImport::~PascalImport() {
+}
+
+void PascalImport::initVars() {
+ m_inInterface = false;
+ m_section = sect_NONE;
+ NativeImportBase::m_currentAccess = Uml::Visibility::Public;
+}
+
+void PascalImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ QChar c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.' || c == '#') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ lexeme = QString();
+ }
+ if (c == ':' && word[i + 1] == '=') {
+ m_source.append(":=");
+ i++;
+ } else {
+ m_source.append(QString(c));
+ }
+ }
+ }
+ if (!lexeme.isEmpty())
+ m_source.append(lexeme);
+}
+
+void PascalImport::checkModifiers(bool& isVirtual, bool& isAbstract) {
+ const uint srcLength = m_source.count();
+ while (m_srcIndex < srcLength - 1) {
+ QString lookAhead = m_source[m_srcIndex + 1].lower();
+ if (lookAhead != "virtual" && lookAhead != "abstract" &&
+ lookAhead != "override" &&
+ lookAhead != "register" && lookAhead != "cdecl" &&
+ lookAhead != "pascal" && lookAhead != "stdcall" &&
+ lookAhead != "safecall" && lookAhead != "saveregisters" &&
+ lookAhead != "popstack")
+ break;
+ if (lookAhead == "abstract")
+ isAbstract = true;
+ else if (lookAhead == "virtual")
+ isVirtual = true;
+ advance();
+ skipStmt();
+ }
+}
+
+bool PascalImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ QString keyword = m_source[m_srcIndex].lower();
+ //kDebug() << '"' << keyword << '"' << endl;
+ if (keyword == "uses") {
+ while (m_srcIndex < srcLength - 1) {
+ QString unit = advance();
+ const QString& prefix = unit.lower();
+ if (prefix == "sysutils" || prefix == "types" || prefix == "classes" ||
+ prefix == "graphics" || prefix == "controls" || prefix == "strings" ||
+ prefix == "forms" || prefix == "windows" || prefix == "messages" ||
+ prefix == "variants" || prefix == "stdctrls" || prefix == "extctrls" ||
+ prefix == "activex" || prefix == "comobj" || prefix == "registry" ||
+ prefix == "classes" || prefix == "dialogs") {
+ if (advance() != ",")
+ break;
+ continue;
+ }
+ QString filename = unit + ".pas";
+ if (! m_parsedFiles.contains(unit)) {
+ // Save current m_source and m_srcIndex.
+ QStringList source(m_source);
+ uint srcIndex = m_srcIndex;
+ m_source.clear();
+ parseFile(filename);
+ // Restore m_source and m_srcIndex.
+ m_source = source;
+ m_srcIndex = srcIndex;
+ // Also reset m_currentAccess.
+ // CHECK: need to reset more stuff?
+ m_currentAccess = Uml::Visibility::Public;
+ }
+ if (advance() != ",")
+ break;
+ }
+ return true;
+ }
+ if (keyword == "unit") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Package, name,
+ m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = static_cast<UMLPackage*>(ns);
+ skipStmt();
+ return true;
+ }
+ if (keyword == "interface") {
+ m_inInterface = true;
+ return true;
+ }
+ if (keyword == "initialization" || keyword == "implementation") {
+ m_inInterface = false;
+ return true;
+ }
+ if (! m_inInterface) {
+ // @todo parseStmt() should support a notion for "quit parsing, close file immediately"
+ return false;
+ }
+ if (keyword == "label") {
+ m_section = sect_LABEL;
+ return true;
+ }
+ if (keyword == "const") {
+ m_section = sect_CONST;
+ return true;
+ }
+ if (keyword == "resourcestring") {
+ m_section = sect_RESOURCESTRING;
+ return true;
+ }
+ if (keyword == "type") {
+ m_section = sect_TYPE;
+ return true;
+ }
+ if (keyword == "var") {
+ m_section = sect_VAR;
+ return true;
+ }
+ if (keyword == "threadvar") {
+ m_section = sect_THREADVAR;
+ return true;
+ }
+ if (keyword == "automated" || keyword == "published" // no concept in UML
+ || keyword == "public") {
+ m_currentAccess = Uml::Visibility::Public;
+ return true;
+ }
+ if (keyword == "protected") {
+ m_currentAccess = Uml::Visibility::Protected;
+ return true;
+ }
+ if (keyword == "private") {
+ m_currentAccess = Uml::Visibility::Private;
+ return true;
+ }
+ if (keyword == "packed") {
+ return true; // TBC: perhaps this could be stored in a TaggedValue
+ }
+ if (keyword == "[") {
+ skipStmt("]");
+ return true;
+ }
+ if (keyword == "end") {
+ if (m_klass) {
+ m_klass = NULL;
+ } else if (m_scopeIndex) {
+ m_scopeIndex--;
+ m_currentAccess = Uml::Visibility::Public;
+ } else {
+ kError() << "importPascal: too many \"end\"" << endl;
+ }
+ skipStmt();
+ return true;
+ }
+ if (keyword == "function" || keyword == "procedure" ||
+ keyword == "constructor" || keyword == "destructor") {
+ if (m_klass == NULL) {
+ // Unlike a Pascal unit, a UML package does not support subprograms.
+ // In order to map those, we would need to create a UML class with
+ // stereotype <<utility>> for the unit, http://bugs.kde.org/89167
+ bool dummyVirtual = false;
+ bool dummyAbstract = false;
+ checkModifiers(dummyVirtual, dummyAbstract);
+ return true;
+ }
+ const QString& name = advance();
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ if (m_source[m_srcIndex + 1] == "(") {
+ advance();
+ const uint MAX_PARNAMES = 16;
+ while (m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ QString nextToken = m_source[m_srcIndex + 1].lower();
+ Uml::Parameter_Direction dir = Uml::pd_In;
+ if (nextToken == "var") {
+ dir = Uml::pd_InOut;
+ advance();
+ } else if (nextToken == "const") {
+ advance();
+ } else if (nextToken == "out") {
+ dir = Uml::pd_Out;
+ advance();
+ }
+ QString parName[MAX_PARNAMES];
+ uint parNameCount = 0;
+ do {
+ if (parNameCount >= MAX_PARNAMES) {
+ kError() << "MAX_PARNAMES is exceeded at " << name << endl;
+ break;
+ }
+ parName[parNameCount++] = advance();
+ } while (advance() == ",");
+ if (m_source[m_srcIndex] != ":") {
+ kError() << "importPascal: expecting ':' at " << m_source[m_srcIndex] << endl;
+ skipStmt();
+ break;
+ }
+ nextToken = advance();
+ if (nextToken.lower() == "array") {
+ nextToken = advance().lower();
+ if (nextToken != "of") {
+ kError() << "importPascal(" << name << "): expecting 'array OF' at "
+ << nextToken << endl;
+ skipStmt();
+ return false;
+ }
+ nextToken = advance();
+ }
+ for (uint i = 0; i < parNameCount; i++) {
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, nextToken, parName[i]);
+ att->setParmKind(dir);
+ }
+ if (advance() != ";")
+ break;
+ }
+ }
+ QString returnType;
+ if (keyword == "function") {
+ if (advance() != ":") {
+ kError() << "importPascal: expecting \":\" at function "
+ << name << endl;
+ return false;
+ }
+ returnType = advance();
+ } else if (keyword == "constructor" || keyword == "destructor") {
+ op->setStereotype(keyword);
+ }
+ skipStmt();
+ bool isVirtual = false;
+ bool isAbstract = false;
+ checkModifiers(isVirtual, isAbstract);
+ Import_Utils::insertMethod(m_klass, op, m_currentAccess, returnType,
+ !isVirtual, isAbstract, false, false, m_comment);
+ return true;
+ }
+ if (m_section != sect_TYPE) {
+ skipStmt();
+ return true;
+ }
+ if (m_klass == NULL) {
+ const QString& name = m_source[m_srcIndex];
+ QString nextToken = advance();
+ if (nextToken != "=") {
+ kDebug() << "PascalImport::parseStmt(" << name << "): "
+ << "expecting '=' at " << nextToken << endl;
+ return false;
+ }
+ keyword = advance().lower();
+ if (keyword == "(") {
+ // enum type
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Enum,
+ name, m_scope[m_scopeIndex], m_comment);
+ UMLEnum *enumType = static_cast<UMLEnum*>(ns);
+ while (++m_srcIndex < srcLength && m_source[m_srcIndex] != ")") {
+ Import_Utils::addEnumLiteral(enumType, m_source[m_srcIndex]);
+ if (advance() != ",")
+ break;
+ }
+ skipStmt();
+ return true;
+ }
+ if (keyword == "set") { // @todo implement Pascal set types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "array") { // @todo implement Pascal array types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "file") { // @todo implement Pascal file types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "^") { // @todo implement Pascal pointer types
+ skipStmt();
+ return true;
+ }
+ if (keyword == "class" || keyword == "interface") {
+ Uml::Object_Type t = (keyword == "class" ? Uml::ot_Class : Uml::ot_Interface);
+ UMLObject *ns = Import_Utils::createUMLObject(t, name,
+ m_scope[m_scopeIndex], m_comment);
+ UMLClassifier *klass = static_cast<UMLClassifier*>(ns);
+ m_comment = QString();
+ QString lookAhead = m_source[m_srcIndex + 1];
+ if (lookAhead == "(") {
+ advance();
+ do {
+ QString base = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class, base, NULL);
+ UMLClassifier *parent = static_cast<UMLClassifier*>(ns);
+ m_comment = QString();
+ Import_Utils::createGeneralization(klass, parent);
+ } while (advance() == ",");
+ if (m_source[m_srcIndex] != ")") {
+ kError() << "PascalImport: expecting \")\" at "
+ << m_source[m_srcIndex] << endl;
+ return false;
+ }
+ lookAhead = m_source[m_srcIndex + 1];
+ }
+ if (lookAhead == ";") {
+ skipStmt();
+ return true;
+ }
+ if (lookAhead == "of") {
+ // @todo implement class-reference type
+ return false;
+ }
+ m_klass = klass;
+ m_currentAccess = Uml::Visibility::Public;
+ return true;
+ }
+ if (keyword == "record") {
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class, name,
+ m_scope[m_scopeIndex], m_comment);
+ ns->setStereotype("record");
+ m_klass = static_cast<UMLClassifier*>(ns);
+ return true;
+ }
+ if (keyword == "function" || keyword == "procedure") {
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Datatype, name,
+ m_scope[m_scopeIndex], m_comment);
+ if (m_source[m_srcIndex + 1] == "(")
+ skipToClosing('(');
+ skipStmt();
+ return true;
+ }
+ // Datatypes: TO BE DONE
+ return false;
+ }
+ // At this point we need a class because we're expecting its member attributes.
+ if (m_klass == NULL) {
+ kDebug() << "importPascal: skipping " << m_source[m_srcIndex] << endl;
+ skipStmt();
+ return true;
+ }
+ QString name, stereotype;
+ if (keyword == "property") {
+ stereotype = keyword;
+ name = advance();
+ } else {
+ name = m_source[m_srcIndex];
+ }
+ if (advance() != ":") {
+ kError() << "PascalImport: expecting \":\" at " << name << " "
+ << m_source[m_srcIndex] << endl;
+ skipStmt();
+ return true;
+ }
+ QString typeName = advance();
+ QString initialValue;
+ if (advance() == "=") {
+ initialValue = advance();
+ QString token;
+ while ((token = advance()) != ";") {
+ initialValue.append(' ' + token);
+ }
+ }
+ UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name,
+ typeName, m_comment);
+ UMLAttribute *attr = static_cast<UMLAttribute*>(o);
+ attr->setStereotype(stereotype);
+ attr->setInitialValue(initialValue);
+ skipStmt();
+ return true;
+}
+
+
diff --git a/umbrello/umbrello/codeimport/pascalimport.h b/umbrello/umbrello/codeimport/pascalimport.h
new file mode 100644
index 00000000..975dc423
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pascalimport.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PASCALIMPORT_H
+#define PASCALIMPORT_H
+
+#include "nativeimportbase.h"
+
+/**
+ * Pascal code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PascalImport : public NativeImportBase {
+public:
+ PascalImport();
+ virtual ~PascalImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& word);
+
+ /**
+ * Check for, and skip over, all modifiers following a method.
+ * Set the output arguments on encountering abstract and/or virtual.
+ *
+ * @param isVirtual return value, set to true when "virtual" seen
+ * @param isAbstract return value, set to true when "abstract" seen
+ */
+ void checkModifiers(bool& isVirtual, bool& isAbstract);
+
+ /**
+ * Auxiliary variable, becomes true when keyword "interface" is seen
+ */
+ bool m_inInterface;
+
+ enum Section_Type { sect_NONE, sect_LABEL, sect_CONST, sect_RESOURCESTRING,
+ sect_TYPE, sect_VAR, sect_THREADVAR };
+ /**
+ * Auxiliary variable, contains the current section
+ */
+ Section_Type m_section;
+};
+
+#endif
+
diff --git a/umbrello/umbrello/codeimport/pythonimport.cpp b/umbrello/umbrello/codeimport/pythonimport.cpp
new file mode 100644
index 00000000..af59cf8a
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pythonimport.cpp
@@ -0,0 +1,190 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "pythonimport.h"
+
+// qt/kde includes
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kdebug.h>
+// app includes
+#include "import_utils.h"
+#include "../uml.h"
+#include "../umldoc.h"
+#include "../umlpackagelist.h"
+#include "../package.h"
+#include "../classifier.h"
+#include "../enum.h"
+#include "../operation.h"
+#include "../attribute.h"
+
+PythonImport::PythonImport() : NativeImportBase("#") {
+ setMultiLineComment("\"\"\"", "\"\"\"");
+ initVars();
+}
+
+PythonImport::~PythonImport() {
+}
+
+void PythonImport::initVars() {
+ m_srcIndentIndex = 0;
+ m_srcIndent[m_srcIndentIndex] = 0;
+ m_braceWasOpened = false;
+}
+
+bool PythonImport::preprocess(QString& line) {
+ if (NativeImportBase::preprocess(line))
+ return true;
+ // Handle single line comment
+ int pos = line.find(m_singleLineCommentIntro);
+ if (pos != -1) {
+ QString cmnt = line.mid(pos);
+ m_source.append(cmnt);
+ m_srcIndex++;
+ if (pos == 0)
+ return true;
+ line = line.left(pos);
+ line.remove( QRegExp("\\s+$") );
+ }
+ // Transform changes in indentation into braces a la C++/Java/Perl/...
+ pos = line.find( QRegExp("\\S") );
+ if (pos == -1)
+ return true;
+ bool isContinuation = false;
+ int leadingWhite = line.left(pos).contains( QRegExp("\\s") );
+ if (leadingWhite > m_srcIndent[m_srcIndentIndex]) {
+ if (m_srcIndex == 0) {
+ kError() << "PythonImport::preprocess(): internal error 1" << endl;
+ return true;
+ }
+ if (m_braceWasOpened) {
+ m_srcIndent[++m_srcIndentIndex] = leadingWhite;
+ m_braceWasOpened = false;
+ } else {
+ isContinuation = true;
+ }
+ } else {
+ while (m_srcIndentIndex > 0 && leadingWhite < m_srcIndent[m_srcIndentIndex]) {
+ m_srcIndentIndex--;
+ m_source.append("}");
+ m_srcIndex++;
+ }
+ }
+ if (line.endsWith(":")) {
+ line.replace( QRegExp(":$"), "{" );
+ m_braceWasOpened = true;
+ } else {
+ m_braceWasOpened = false;
+ }
+ if (!isContinuation && !m_braceWasOpened)
+ line += ';';
+ return false; // The input was not completely consumed by preprocessing.
+}
+
+void PythonImport::fillSource(const QString& word) {
+ QString lexeme;
+ const uint len = word.length();
+ for (uint i = 0; i < len; i++) {
+ const QChar& c = word[i];
+ if (c.isLetterOrNumber() || c == '_' || c == '.') {
+ lexeme += c;
+ } else {
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ m_srcIndex++;
+ lexeme = QString();
+ }
+ m_source.append(QString(c));
+ m_srcIndex++;
+ }
+ }
+ if (!lexeme.isEmpty()) {
+ m_source.append(lexeme);
+ m_srcIndex++;
+ }
+}
+
+void PythonImport::skipBody() {
+ if (m_source[m_srcIndex] != "{")
+ skipStmt("{");
+ int braceNesting = 0;
+ QString token;
+ while (!(token = advance()).isNull()) {
+ if (token == "}") {
+ if (braceNesting <= 0)
+ break;
+ braceNesting--;
+ } else if (token == "{") {
+ braceNesting++;
+ }
+ }
+}
+
+bool PythonImport::parseStmt() {
+ const uint srcLength = m_source.count();
+ const QString& keyword = m_source[m_srcIndex];
+ if (keyword == "class") {
+ const QString& name = advance();
+ UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
+ name, m_scope[m_scopeIndex], m_comment);
+ m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
+ m_comment = QString();
+ if (advance() == "(") {
+ while (m_srcIndex < srcLength - 1 && advance() != ")") {
+ const QString& baseName = m_source[m_srcIndex];
+ Import_Utils::createGeneralization(m_klass, baseName);
+ if (advance() != ",")
+ break;
+ }
+ }
+ if (m_source[m_srcIndex] != "{") {
+ skipStmt("{");
+ }
+ return true;
+ }
+ if (keyword == "def") {
+ if (m_klass == NULL) {
+ // skip functions outside of a class
+ skipBody();
+ return true;
+ }
+ const QString& name = advance();
+ // operation
+ UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
+ if (advance() != "(") {
+ kError() << "importPython def " << name << ": expecting \"(\"" << endl;
+ skipBody();
+ return true;
+ }
+ while (m_srcIndex < srcLength && advance() != ")") {
+ const QString& parName = m_source[m_srcIndex];
+ UMLAttribute *att = Import_Utils::addMethodParameter(op, "string", parName);
+ if (advance() != ",")
+ break;
+ }
+ Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, "string",
+ false /*isStatic*/, false /*isAbstract*/, false /*isFriend*/,
+ false /*isConstructor*/, m_comment);
+ skipBody();
+ return true;
+ }
+ if (keyword == "}") {
+ if (m_scopeIndex)
+ m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
+ else
+ kError() << "importPython: too many }" << endl;
+ return true;
+ }
+ return false; // @todo parsing of attributes
+}
+
+
diff --git a/umbrello/umbrello/codeimport/pythonimport.h b/umbrello/umbrello/codeimport/pythonimport.h
new file mode 100644
index 00000000..41fea0d4
--- /dev/null
+++ b/umbrello/umbrello/codeimport/pythonimport.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * copyright (C) 2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+#ifndef PYTHONIMPORT_H
+#define PYTHONIMPORT_H
+
+#include "nativeimportbase.h"
+
+/**
+ * Python code import
+ * @author Oliver Kellogg
+ * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org
+ */
+class PythonImport : public NativeImportBase {
+public:
+ PythonImport();
+ virtual ~PythonImport();
+
+protected:
+ /**
+ * Reimplement operation from NativeImportBase.
+ */
+ void initVars();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ bool parseStmt();
+
+ /**
+ * Implement abstract operation from NativeImportBase.
+ */
+ void fillSource(const QString& line);
+
+ /**
+ * Reimplement operation from NativeImportBase.
+ * In addition to handling multiline comments, this method transforms
+ * changes in leading indentation into braces (opening brace for increase
+ * in indentation, closing brace for decrease in indentation) in m_source.
+ * Removal of Python's indentation sensitivity simplifies subsequent
+ * processing using Umbrello's native import framework.
+ */
+ bool preprocess(QString& line);
+
+ /**
+ * Skip ahead to outermost closing brace
+ */
+ void skipBody();
+
+ /**
+ * Buffer for number of indentation characters (whitespace,
+ * i.e. tabs or spaces) at beginning of input line.
+ */
+ int m_srcIndent[100];
+
+ /**
+ * Index for m_srcIndent[]. Index 0 is reserved and contains 0.
+ */
+ int m_srcIndentIndex;
+
+ /**
+ * Auxiliary flag denoting the opening of a block
+ */
+ bool m_braceWasOpened;
+};
+
+#endif
+