You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/umbrello/umbrello/codeimport/pythonimport.cpp

191 lines
6.1 KiB

/***************************************************************************
* *
* 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 <tqstringlist.h>
#include <tqregexp.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(TQString& line) {
if (NativeImportBase::preprocess(line))
return true;
// Handle single line comment
int pos = line.find(m_singleLineCommentIntro);
if (pos != -1) {
TQString cmnt = line.mid(pos);
m_source.append(cmnt);
m_srcIndex++;
if (pos == 0)
return true;
line = line.left(pos);
line.remove( TQRegExp("\\s+$") );
}
// Transform changes in indentation into braces a la C++/Java/Perl/...
pos = line.find( TQRegExp("\\S") );
if (pos == -1)
return true;
bool isContinuation = false;
int leadingWhite = line.left(pos).contains( TQRegExp("\\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( TQRegExp(":$"), "{" );
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 TQString& word) {
TQString lexeme;
const uint len = word.length();
for (uint i = 0; i < len; i++) {
const TQChar& c = word[i];
if (c.isLetterOrNumber() || c == '_' || c == '.') {
lexeme += c;
} else {
if (!lexeme.isEmpty()) {
m_source.append(lexeme);
m_srcIndex++;
lexeme = TQString();
}
m_source.append(TQString(c));
m_srcIndex++;
}
}
if (!lexeme.isEmpty()) {
m_source.append(lexeme);
m_srcIndex++;
}
}
void PythonImport::skipBody() {
if (m_source[m_srcIndex] != "{")
skipStmt("{");
int braceNesting = 0;
TQString 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 TQString& keyword = m_source[m_srcIndex];
if (keyword == "class") {
const TQString& 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 = TQString();
if (advance() == "(") {
while (m_srcIndex < srcLength - 1 && advance() != ")") {
const TQString& 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 TQString& 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 TQString& 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
}