import_rose.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "import_rose.h"
00014
00015
00016 #include <qstring.h>
00017 #include <qtextstream.h>
00018 #include <qptrlist.h>
00019 #include <qstringlist.h>
00020 #include <qregexp.h>
00021 #include <qmessagebox.h>
00022 #include <klocale.h>
00023 #include <kdebug.h>
00024
00025 #include "petalnode.h"
00026 #include "petaltree2uml.h"
00027 #include "umlnamespace.h"
00028
00029 namespace Import_Rose {
00030
00031 typedef QPtrList<PetalNode> PetalNodeList;
00032
00033 uint nClosures;
00034
00035
00036
00037
00038
00039
00040
00041
00042 uint linum;
00043 QString g_methodName;
00044 void methodName(const QString& m) {
00045 g_methodName = m;
00046 }
00050 QString loc() {
00051 return "Import_Rose::" + g_methodName + " line " + QString::number(linum) + ": ";
00052 }
00053
00057 QStringList scan(const QString& lin) {
00058 QStringList result;
00059 QString line = lin.stripWhiteSpace();
00060 if (line.isEmpty())
00061 return result;
00062 QString lexeme;
00063 const uint len = line.length();
00064 bool inString = false;
00065 for (uint i = 0; i < len; i++) {
00066 QChar c = line[i];
00067 if (c == '"') {
00068 lexeme += c;
00069 if (inString) {
00070 result.append(lexeme);
00071 lexeme = QString::null;
00072 }
00073 inString = !inString;
00074 } else if (inString ||
00075 c.isLetterOrNumber() || c == '_' || c == '@') {
00076 lexeme += c;
00077 } else {
00078 if (!lexeme.isEmpty()) {
00079 result.append(lexeme);
00080 lexeme = QString::null;
00081 }
00082 if (! c.isSpace()) {
00083 result.append(QString(c));
00084 }
00085 }
00086 }
00087 if (!lexeme.isEmpty())
00088 result.append(lexeme);
00089 return result;
00090 }
00091
00095 QString shift(QStringList& l) {
00096 QString first = l.first();
00097 l.pop_front();
00098 return first;
00099 }
00100
00104 bool checkClosing(QStringList& tokens) {
00105 if (tokens.count() == 0)
00106 return false;
00107 if (tokens.last() == ")") {
00108
00109
00110
00111 tokens.pop_back();
00112 while (tokens.count() && tokens.last() == ")") {
00113 nClosures++;
00114 tokens.pop_back();
00115 }
00116 return true;
00117 }
00118 return false;
00119 }
00120
00126 bool isImmediateValue(QString s) {
00127 return s.contains(QRegExp("^[\\d\\-\"]"));
00128 }
00129
00142 QString extractImmediateValues(QStringList& l) {
00143 if (l.count() == 0)
00144 return QString::null;
00145 if (l.first() == "(")
00146 l.pop_front();
00147 QString result;
00148 bool start = true;
00149 while (l.count() && isImmediateValue(l.first())) {
00150 if (start)
00151 start = false;
00152 else
00153 result += ' ';
00154 result += shift(l);
00155 if (l.first() == ",")
00156 l.pop_front();
00157 }
00158 if (l.first() == ")")
00159 l.pop_front();
00160 while (l.count() && l.first() == ")") {
00161 nClosures++;
00162 l.pop_front();
00163 }
00164 return result;
00165 }
00166
00167 QString collectVerbatimText(QTextStream& stream) {
00168 QString result;
00169 QString line;
00170 methodName("collectVerbatimText");
00171 while (!(line = stream.readLine()).isNull()) {
00172 linum++;
00173 line = line.stripWhiteSpace();
00174 if (line.isEmpty() || line.startsWith(")"))
00175 break;
00176 if (line[0] != '|') {
00177 kError() << loc() << "expecting '|' at start of verbatim text" << endl;
00178 return QString::null;
00179 } else {
00180 result += line.mid(1) + "\n";
00181 }
00182 }
00183 if (line.isNull()) {
00184 kError() << loc() << "premature EOF" << endl;
00185 return QString::null;
00186 }
00187 if (! line.isEmpty()) {
00188 for (uint i = 0; i < line.length(); i++) {
00189 const QChar& clParenth = line[i];
00190 if (clParenth != ')') {
00191 kError() << loc() << "expected ')', found: " << clParenth << endl;
00192 return QString::null;
00193 }
00194 nClosures++;
00195 }
00196 }
00197 return result;
00198 }
00199
00220 QString extractValue(QStringList& l, QTextStream& stream) {
00221 methodName("extractValue");
00222 if (l.count() == 0)
00223 return QString::null;
00224 if (l.first() == "(")
00225 l.pop_front();
00226 if (l.first() != "value")
00227 return QString::null;
00228 l.pop_front();
00229 l.pop_front();
00230 QString result;
00231 if (l.count() == 0) {
00232 QString text = collectVerbatimText(stream);
00233 nClosures--;
00234 return text;
00235 } else {
00236 result = shift(l);
00237 if (l.first() != ")") {
00238 kError() << loc() << "expecting closing parenthesis" << endl;
00239 return result;
00240 }
00241 l.pop_front();
00242 }
00243 while (l.count() && l.first() == ")") {
00244 nClosures++;
00245 l.pop_front();
00246 }
00247 return result;
00248 }
00249
00257 PetalNode *readAttributes(QStringList initialArgs, QTextStream& stream) {
00258 methodName("readAttributes");
00259 if (initialArgs.count() == 0) {
00260 kError() << loc() << "initialArgs is empty" << endl;
00261 return NULL;
00262 }
00263 PetalNode::NodeType nt;
00264 QString type = shift(initialArgs);
00265 if (type == "object")
00266 nt = PetalNode::nt_object;
00267 else if (type == "list")
00268 nt = PetalNode::nt_list;
00269 else {
00270 kError() << loc() << "unknown node type " << type << endl;
00271 return NULL;
00272 }
00273 PetalNode *node = new PetalNode(nt);
00274 bool seenClosing = checkClosing(initialArgs);
00275 node->setInitialArgs(initialArgs);
00276 if (seenClosing)
00277 return node;
00278 PetalNode::NameValueList attrs;
00279 QString line;
00280 while (!(line = stream.readLine()).isNull()) {
00281 linum++;
00282 line = line.stripWhiteSpace();
00283 if (line.isEmpty())
00284 continue;
00285 QStringList tokens = scan(line);
00286 QString stringOrNodeOpener = shift(tokens);
00287 QString name;
00288 if (nt == PetalNode::nt_object && !stringOrNodeOpener.contains(QRegExp("^[A-Za-z]"))) {
00289 kError() << loc() << "unexpected line " << line << endl;
00290 return NULL;
00291 }
00292 PetalNode::StringOrNode value;
00293 if (nt == PetalNode::nt_object) {
00294 name = stringOrNodeOpener;
00295 if (tokens.count() == 0) {
00296 value.string = collectVerbatimText(stream);
00297 PetalNode::NameValue attr(name, value);
00298 attrs.append(attr);
00299 if (nClosures) {
00300
00301
00302
00303
00304 nClosures--;
00305 break;
00306 }
00307 continue;
00308 }
00309 stringOrNodeOpener = shift(tokens);
00310 } else if (stringOrNodeOpener != "(") {
00311 value.string = stringOrNodeOpener;
00312 PetalNode::NameValue attr(QString::null, value);
00313 attrs.append(attr);
00314 if (tokens.count() && tokens.first() != ")") {
00315 kDebug() << loc()
00316 << "NYI - immediate list entry with more than one item" << endl;
00317 }
00318 if (checkClosing(tokens))
00319 break;
00320 continue;
00321 }
00322 if (stringOrNodeOpener == "(") {
00323 QString nxt = tokens.first();
00324 if (isImmediateValue(nxt)) {
00325 value.string = extractImmediateValues(tokens);
00326 } else if (nxt == "value" || nxt.startsWith("\"")) {
00327 value.string = extractValue(tokens, stream);
00328 } else {
00329 value.node = readAttributes(tokens, stream);
00330 if (value.node == NULL)
00331 return NULL;
00332 }
00333 PetalNode::NameValue attr(name, value);
00334 attrs.append(attr);
00335 if (nClosures) {
00336
00337
00338
00339
00340 nClosures--;
00341 break;
00342 }
00343 } else {
00344 value.string = stringOrNodeOpener;
00345 bool seenClosing = checkClosing(tokens);
00346 PetalNode::NameValue attr(name, value);
00347 attrs.append(attr);
00348 if (seenClosing) {
00349 break;
00350 }
00351 }
00352 }
00353 node->setAttributes(attrs);
00354 return node;
00355 }
00356
00357 bool loadFromMDL(QIODevice& file) {
00358 QTextStream stream(&file);
00359 QString line;
00360 PetalNode *root = NULL;
00361 linum = 0;
00362 while (!(line = stream.readLine()).isNull()) {
00363 linum++;
00364 if (line.contains( QRegExp("^\\s*\\(object Petal") )) {
00365 while (!(line = stream.readLine()).isNull() && !line.contains(')')) {
00366 linum++;
00367 }
00368 if (line.isNull())
00369 break;
00370 } else {
00371 QRegExp objectRx("^\\s*\\(object ");
00372 if (line.contains(objectRx)) {
00373 nClosures = 0;
00374 QStringList initialArgs = scan(line);
00375 initialArgs.pop_front();
00376 root = readAttributes(initialArgs, stream);
00377 }
00378 }
00379 }
00380 file.close();
00381 if (root == NULL)
00382 return false;
00383 return petalTree2Uml(root);
00384 }
00385
00386 }
00387
This file is part of the documentation for umbrello Version 3.1.0.