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.
191 lines
6.1 KiB
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
|
|
}
|
|
|
|
|