umbrello API Documentation

pythonimport.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *  copyright (C) 2006                                                     *
00009  *  Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                   *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "pythonimport.h"
00014 
00015 // qt/kde includes
00016 #include <qstringlist.h>
00017 #include <qregexp.h>
00018 #include <kdebug.h>
00019 // app includes
00020 #include "import_utils.h"
00021 #include "../uml.h"
00022 #include "../umldoc.h"
00023 #include "../umlpackagelist.h"
00024 #include "../package.h"
00025 #include "../classifier.h"
00026 #include "../enum.h"
00027 #include "../operation.h"
00028 #include "../attribute.h"
00029 
00030 PythonImport::PythonImport() : NativeImportBase("#") {
00031     setMultiLineComment("\"\"\"", "\"\"\"");
00032     initVars();
00033 }
00034 
00035 PythonImport::~PythonImport() {
00036 }
00037 
00038 void PythonImport::initVars() {
00039     m_srcIndentIndex = 0;
00040     m_srcIndent[m_srcIndentIndex] = 0;
00041     m_braceWasOpened = false;
00042 }
00043 
00044 bool PythonImport::preprocess(QString& line) {
00045     if (NativeImportBase::preprocess(line))
00046         return true;
00047     // Handle single line comment
00048     int pos = line.find(m_singleLineCommentIntro);
00049     if (pos != -1) {
00050         QString cmnt = line.mid(pos);
00051         m_source.append(cmnt);
00052         m_srcIndex++;
00053         if (pos == 0)
00054             return true;
00055         line = line.left(pos);
00056         line.remove( QRegExp("\\s+$") );
00057     }
00058     // Transform changes in indentation into braces a la C++/Java/Perl/...
00059     pos = line.find( QRegExp("\\S") );
00060     if (pos == -1)
00061         return true;
00062     bool isContinuation = false;
00063     int leadingWhite = line.left(pos).contains( QRegExp("\\s") );
00064     if (leadingWhite > m_srcIndent[m_srcIndentIndex]) {
00065         if (m_srcIndex == 0) {
00066             kError() << "PythonImport::preprocess(): internal error 1" << endl;
00067             return true;
00068         }
00069         if (m_braceWasOpened) {
00070             m_srcIndent[++m_srcIndentIndex] = leadingWhite;
00071             m_braceWasOpened = false;
00072         } else {
00073             isContinuation = true;
00074         }
00075     } else {
00076         while (m_srcIndentIndex > 0 && leadingWhite < m_srcIndent[m_srcIndentIndex]) {
00077             m_srcIndentIndex--;
00078             m_source.append("}");
00079             m_srcIndex++;
00080         }
00081     }
00082     if (line.endsWith(":")) {
00083         line.replace( QRegExp(":$"), "{" );
00084         m_braceWasOpened = true;
00085     } else {
00086         m_braceWasOpened = false;
00087     }
00088     if (!isContinuation && !m_braceWasOpened)
00089         line += ';';
00090     return false;  // The input was not completely consumed by preprocessing.
00091 }
00092 
00093 void PythonImport::fillSource(const QString& word) {
00094     QString lexeme;
00095     const uint len = word.length();
00096     for (uint i = 0; i < len; i++) {
00097         const QChar& c = word[i];
00098         if (c.isLetterOrNumber() || c == '_' || c == '.') {
00099             lexeme += c;
00100         } else {
00101             if (!lexeme.isEmpty()) {
00102                 m_source.append(lexeme);
00103                 m_srcIndex++;
00104                 lexeme = QString();
00105             }
00106             m_source.append(QString(c));
00107             m_srcIndex++;
00108         }
00109     }
00110     if (!lexeme.isEmpty()) {
00111         m_source.append(lexeme);
00112         m_srcIndex++;
00113     }
00114 }
00115 
00116 void PythonImport::skipBody() {
00117     if (m_source[m_srcIndex] != "{")
00118         skipStmt("{");
00119     int braceNesting = 0;
00120     QString token;
00121     while (!(token = advance()).isNull()) {
00122         if (token == "}") {
00123             if (braceNesting <= 0)
00124                 break;
00125             braceNesting--;
00126         } else if (token == "{") {
00127             braceNesting++;
00128         }
00129     }
00130 }
00131 
00132 bool PythonImport::parseStmt() {
00133     const uint srcLength = m_source.count();
00134     const QString& keyword = m_source[m_srcIndex];
00135     if (keyword == "class") {
00136         const QString& name = advance();
00137         UMLObject *ns = Import_Utils::createUMLObject(Uml::ot_Class,
00138                         name, m_scope[m_scopeIndex], m_comment);
00139         m_scope[++m_scopeIndex] = m_klass = static_cast<UMLClassifier*>(ns);
00140         m_comment = QString();
00141         if (advance() == "(") {
00142             while (m_srcIndex < srcLength - 1 && advance() != ")") {
00143                 const QString& baseName = m_source[m_srcIndex];
00144                 Import_Utils::createGeneralization(m_klass, baseName);
00145                 if (advance() != ",")
00146                     break;
00147             }
00148         }
00149         if (m_source[m_srcIndex] != "{") {
00150             skipStmt("{");
00151         }
00152         return true;
00153     }
00154     if (keyword == "def") {
00155         if (m_klass == NULL) {
00156             // skip functions outside of a class
00157             skipBody();
00158             return true;
00159         }
00160         const QString& name = advance();
00161         // operation
00162         UMLOperation *op = Import_Utils::makeOperation(m_klass, name);
00163         if (advance() != "(") {
00164             kError() << "importPython def " << name << ": expecting \"(\"" << endl;
00165             skipBody();
00166             return true;
00167         }
00168         while (m_srcIndex < srcLength && advance() != ")") {
00169             const QString& parName = m_source[m_srcIndex];
00170             UMLAttribute *att = Import_Utils::addMethodParameter(op, "string", parName);
00171             if (advance() != ",")
00172                 break;
00173         }
00174         Import_Utils::insertMethod(m_klass, op, Uml::Visibility::Public, "string",
00175                                    false /*isStatic*/, false /*isAbstract*/, false /*isFriend*/,
00176                                    false /*isConstructor*/, m_comment);
00177         skipBody();
00178         return true;
00179     }
00180     if (keyword == "}") {
00181         if (m_scopeIndex)
00182             m_klass = dynamic_cast<UMLClassifier*>(m_scope[--m_scopeIndex]);
00183         else
00184             kError() << "importPython: too many }" << endl;
00185         return true;
00186     }
00187     return false;  // @todo parsing of attributes
00188 }
00189 
00190 
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:07:59 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003