00001 #include "constants.h"
00002
00003 #include "automataCreator.h"
00004 #include "stringProcessor.h"
00005 #include "state.h"
00006 #include "transition.h"
00007 #include "utils.h"
00008
00009 #include "istate.h"
00010 #include "itransition.h"
00011 #include <QStringList>
00012 #include <QVector>
00013 #include <QSharedPointer>
00014 #include <QQueue>
00015 #include <QPainterPath>
00016
00017 #include <QtDebug>
00018
00019 const QStringList AutomataCreator::defaultAlphabetSymbList = QStringList() << "A" << "\\Sigma";
00020 const QStringList AutomataCreator::defaultEpsilonSymbList = QStringList() << "\\varepsilon" << "\\epsilon";
00021
00022 #ifdef TESTING_AUTOMATA_CREATOR
00023 # define DBGLOG_AC(x) DBGLOG_("AUTOMATACREATOR", x)
00024 #else
00025 # define DBGLOG_AC(x)
00026 #endif
00027
00028
00029
00030 class TTRowImpl : public ITTRow
00031 {
00032 public:
00033 TTRowImpl(const QStringList &head)
00034 : m_head(head)
00035 {}
00036
00037 typedef QMap<QString, QStringList> TRowDataMap;
00038 TTRowImpl(const QStringList &head, const TRowDataMap &rowDataMap)
00039 : m_head(head), m_dataMap(rowDataMap), m_initialFlag(false), m_finalFlag(false)
00040 {}
00041
00042 const QStringList head() const
00043 {
00044 return m_head;
00045 }
00046
00047 const QStringList getValue(const QString &character) const
00048 {
00049 return m_dataMap[character];
00050 }
00051
00052
00053
00054
00055
00056
00057 QStringList& operator[](const QString &character)
00058 {
00059 return m_dataMap[character];
00060 }
00061
00062 QList<QString> getUniqueKeys() const
00063 {
00064 return m_dataMap.uniqueKeys();
00065 }
00066
00067 void setInitialFlag(bool initial)
00068 {
00069 m_initialFlag = initial;
00070 }
00071
00072 void setFinalFlag(bool final)
00073 {
00074 m_finalFlag = final;
00075 }
00076
00077 bool initialFlag() const
00078 {
00079 return m_initialFlag;
00080 }
00081
00082 bool finalFlag() const
00083 {
00084 return m_finalFlag;
00085 }
00086
00087 protected:
00088 QStringList m_head;
00089 TRowDataMap m_dataMap;
00090
00091 bool m_initialFlag;
00092 bool m_finalFlag;
00093 };
00094
00095
00096
00097
00098
00099
00100
00101 class TransitionTableImpl : public ITransitionTable
00102 {
00103 public:
00104 TransitionTableImpl()
00105 {}
00106
00107 typedef QVector<QSharedPointer<ITTRow> > TITTRowList;
00108
00109 TransitionTableImpl(const TITTRowList &rows)
00110 : m_rows(rows)
00111 {}
00112
00113 ~TransitionTableImpl()
00114 {
00115 DBGLOG_AC("called");
00116 }
00117
00118 int getRowCount() const
00119 {
00120 return m_rows.count();
00121 }
00122
00123 QSharedPointer<ITTRow> getRow(int idx) const
00124 {
00125 if (idx >= m_rows.count()) return QSharedPointer<ITTRow>(NULL);
00126
00127 return m_rows[idx];
00128 }
00129
00130 int addRow(const QSharedPointer<ITTRow> &row)
00131 {
00132 m_rows << row;
00133
00134 return m_rows.count()-1;
00135 }
00136
00137 QList<QString> getUniqueKeys() const
00138 {
00139 QSet<QString> uniqueKeys;
00140 foreach(const QSharedPointer<ITTRow> &row, m_rows)
00141 {
00142 uniqueKeys |= row->getUniqueKeys().toSet();
00143 }
00144
00145 return uniqueKeys.toList();
00146 }
00147
00148 QString toLaTeXTable() const
00149 {
00150 QString laTeXTable;
00151
00152 laTeXTable += "\
00153 \\begin{table}[h]\n\
00154 \\begin{center}\n\
00155 \\begin{tabular}{r r|";
00156
00157 QString rowString = " & $\\mathbf{\\delta{}_M}$";
00158 QList<QString> uniqueKeys = getUniqueKeys();
00159 foreach(const QString &character, uniqueKeys)
00160 {
00161 laTeXTable += "|c";
00162 QString symb =
00163 StringProcessor::isSpecialSymbol(character) ?
00164 "$%1$" : "%1";
00165 rowString += " & \\textbf{" + symb.arg(character) + "}";
00166 }
00167 laTeXTable += "}\n";
00168 laTeXTable += rowString + "\\\\\n";
00169
00170 for (int i = 0; i < getRowCount(); ++i)
00171 {
00172 laTeXTable += QString("\\cline{2-%1}\n").arg(2+uniqueKeys.count());
00173
00174 QSharedPointer<ITTRow> row = getRow(i);
00175
00176 Q_ASSERT(row->head().count() == 1);
00177
00178 QString fieldString = " & " + row->head()[0];
00179 if (row->initialFlag() && row->finalFlag())
00180 fieldString = "$\\leftrightarrow$" + fieldString;
00181 else if (row->initialFlag())
00182 fieldString = "$\\rightarrow$" + fieldString;
00183 else if (row->finalFlag())
00184 fieldString = "$\\leftarrow$" + fieldString;
00185
00186 rowString = fieldString;
00187 foreach(const QString &character, uniqueKeys)
00188 {
00189 fieldString = trStringListToString((*row)[character]);
00190 rowString += " & " + fieldString;
00191 }
00192
00193 laTeXTable += rowString + "\\\\\n";
00194 }
00195
00196 laTeXTable += "\
00197 \\end{tabular}\n\
00198 \\end{center}\n\
00199 \\caption{Transition table}\n\
00200 \\label{tab:transitionTable}\n\
00201 \\end{table}";
00202
00203 return laTeXTable;
00204 }
00205
00206 QString toStringTable() const
00207 {
00208 QString stringTable;
00209
00210 const int columnWidth = 15;
00211
00212 QList<QString> uniqueKeys = getUniqueKeys();
00213 QString rowString = QString("%1").arg("M", columnWidth+4) + " -> ";
00214 foreach(const QString &character, uniqueKeys)
00215 {
00216 rowString += QString("%1").arg(character, columnWidth);
00217 }
00218 stringTable += rowString + "\n";
00219
00220 for (int i = 0; i < getRowCount(); ++i)
00221 {
00222 QSharedPointer<ITTRow> row = getRow(i);
00223
00224 Q_ASSERT(row->head().count() == 1);
00225
00226 QString fieldString = row->head()[0];
00227 if (row->initialFlag() && row->finalFlag())
00228 fieldString = "<=> " + fieldString;
00229 else if (row->initialFlag())
00230 fieldString = " -> " + fieldString;
00231 else if (row->finalFlag())
00232 fieldString = "<- " + fieldString;
00233 rowString = QString("%1").arg(fieldString, columnWidth+4) + " -> ";
00234 foreach(const QString &character, uniqueKeys)
00235 {
00236 fieldString = trStringListToString((*row)[character]);
00237 rowString += QString("%1").arg(fieldString, columnWidth);
00238 }
00239
00240 stringTable += rowString + "\n";
00241 }
00242
00243 return stringTable;
00244 }
00245
00246 protected:
00247 TITTRowList m_rows;
00248 };
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 TransitionImpl::TransitionImpl(const QString &source, const QString &destination,
00259 const ITransition::TCharSet characters,
00260 Transition *graphicsTransition)
00261 : m_sourceState(source), m_destinationState(destination), m_characters(characters),
00262 m_graphicsTransition(graphicsTransition)
00263 {}
00264
00265 TransitionImpl::~TransitionImpl()
00266 {
00267 DBGLOG_AC(DBGPAR(m_sourceState) << DBGPAR(m_destinationState) <<
00268 DBGPAR(m_characters) << "deleted");
00269 }
00270
00271 void TransitionImpl::setSourceState(const QString &stateName)
00272 {
00273 m_sourceState = stateName;
00274 }
00275
00276 void TransitionImpl::setDestinationState(const QString &stateName)
00277 {
00278 m_destinationState = stateName;
00279 }
00280
00281 QString TransitionImpl::getSourceState() const
00282 {
00283 return m_sourceState;
00284 }
00285
00286 QString TransitionImpl::getDestinationState() const
00287 {
00288 return m_destinationState;
00289 }
00290
00291 bool TransitionImpl::passOn(const QString &character) const
00292 {
00293 return m_characters.contains(character);
00294 }
00295
00296 ITransition::TCharSet TransitionImpl::getCharacters() const
00297 {
00298 return m_characters;
00299 }
00300
00301 void TransitionImpl::setCharacters(const TCharSet &characters)
00302 {
00303 m_characters = characters;
00304 }
00305
00306 Transition* TransitionImpl::getGraphicsTransition()
00307 {
00308 return m_graphicsTransition;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 StateImpl::StateImpl(const QString &name, const QString &label, bool initial, bool final,
00318 State *graphicsState)
00319 : m_name(name), m_label(label), m_initial(initial), m_final(final), m_graphicsState(graphicsState)
00320 {}
00321
00322 StateImpl::~StateImpl()
00323 {
00324 DBGLOG_AC(DBGPAR(getName()) << "deleted");
00325 }
00326
00327 void StateImpl::setName(const QString &name)
00328 {
00329 m_name = name;
00330
00331 foreach(QSharedPointer<ITransition> tr, getTransitions())
00332 {
00333 tr->setSourceState(name);
00334 }
00335
00336 foreach(QSharedPointer<ITransition> tr, getTransitionsTo())
00337 {
00338 tr->setDestinationState(name);
00339 }
00340 }
00341
00342 QString StateImpl::getName() const
00343 {
00344 return m_name;
00345 }
00346
00347 void StateImpl::setLabel(const QString &label)
00348 {
00349 m_label = label;
00350 }
00351
00352 QString StateImpl::getLabel() const
00353 {
00354 return m_label;
00355 }
00356
00357 bool StateImpl::isInitial() const
00358 {
00359 return m_initial;
00360 }
00361
00362 bool StateImpl::isFinal() const
00363 {
00364 return m_final;
00365 }
00366
00367 void StateImpl::setInitial(bool is)
00368 {
00369 m_initial = is;
00370 }
00371
00372 void StateImpl::setFinal(bool is)
00373 {
00374 m_final = is;
00375 }
00376
00377 IState::TIStateNameSet StateImpl::getStatesOn(const QString &character) const
00378 {
00379 IState::TIStateNameSet result;
00380
00381 foreach(const QSharedPointer<TransitionImpl> &tr, m_transitions)
00382 {
00383 if (tr->passOn(character))
00384 {
00385 result << tr->getDestinationState();
00386 }
00387 }
00388
00389 return result;
00390 }
00391
00392 IState::TIStateNameList StateImpl::getAdjacentStates() const
00393 {
00394 IState::TIStateNameList stateNames;
00395 foreach(const QSharedPointer<TransitionImpl> &tr, m_transitions)
00396 {
00397 stateNames << tr->getDestinationState();
00398 }
00399
00400 return stateNames;
00401 }
00402
00403 ITransition::TITransitionList StateImpl::getTransitions() const
00404 {
00405 return trSharedPointerListStaticCast<TransitionImpl, ITransition>(m_transitions);
00406 }
00407
00408 ITransition::TITransitionList StateImpl::getTransitionsTo() const
00409 {
00410 return trSharedPointerListStaticCast<TransitionImpl, ITransition>(m_transitionsTo);
00411 }
00412
00413 TransitionImpl::TTransitionList StateImpl::getPrivateTransitions() const
00414 {
00415 return m_transitions;
00416 }
00417
00418 TransitionImpl::TTransitionList StateImpl::getPrivateTransitionsTo() const
00419 {
00420 return m_transitionsTo;
00421 }
00422
00423 void StateImpl::addTransition(const QSharedPointer<TransitionImpl> &tr)
00424 {
00425 Q_ASSERT(tr->getSourceState() == getName() &&
00426 "set only transitions which starts in this state");
00427 if (tr->getSourceState() != getName())
00428 {
00429 RELLOG("Transition isn't added because it doesn't start in this state!!!");
00430 return;
00431 }
00432
00433 m_transitions << tr;
00434 }
00435
00436 void StateImpl::addTransitionTo(const QSharedPointer<TransitionImpl> &tr)
00437 {
00438 Q_ASSERT(tr->getDestinationState() == getName() &&
00439 "set only transitions which ends in this state");
00440 if (tr->getDestinationState() != getName())
00441 {
00442 RELLOG("Transition isn't added because it doesn't end in this state!!!");
00443 return;
00444 }
00445
00446 m_transitionsTo << tr;
00447 }
00448
00449 void StateImpl::removeTransition(const QSharedPointer<TransitionImpl> &tr)
00450 {
00451 Q_ASSERT(tr->getSourceState() == m_name && "inconsistency in automaton system!");
00452 {
00453 bool ret = m_transitions.removeOne(tr);
00454 Q_UNUSED(ret);
00455 Q_ASSERT(ret && "inconsistency in automaton system!");
00456 }
00457 }
00458
00459 void StateImpl::removeTransitionTo(const QSharedPointer<TransitionImpl> &tr)
00460 {
00461 Q_ASSERT(tr->getDestinationState() == m_name && "inconsistency in automaton system!");
00462 {
00463 bool ret = m_transitionsTo.removeOne(tr);
00464 Q_UNUSED(ret);
00465 Q_ASSERT(ret && "inconsistency in automaton system!");
00466 }
00467 }
00468
00469 State* StateImpl::getGraphicsState() const
00470 {
00471 return m_graphicsState;
00472 }
00473
00474 IState::TIStateNameSet StateImpl::getStatesAndPathsOn
00475 (const QString &character, QList<QPainterPath> &paths) const
00476 {
00477 IState::TIStateNameSet result;
00478
00479 foreach(const QSharedPointer<TransitionImpl> &tr, m_transitions)
00480 {
00481 if (tr->passOn(character))
00482 {
00483 result << tr->getDestinationState();
00484
00485 Transition *graphicsTransition = tr->getGraphicsTransition();
00486 paths << graphicsTransition->path();
00487 }
00488 }
00489
00490 return result;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500 AutomatonImpl::AutomatonImpl(const ITransition::TCharSet &alphabet, const QString &alphabetSymbol,
00501 const QString &epsilonSymbol)
00502 : m_alphabet(alphabet), m_alphabetSymbol(alphabetSymbol), m_epsilonSymbol(epsilonSymbol),
00503 m_allowRenundancies(false)
00504 {
00505 Q_ASSERT(m_positioningMap.isEmpty() && "it should be empty by default!!!");
00506 }
00507
00508 AutomatonImpl::~AutomatonImpl()
00509 {
00510 DBGLOG_AC("called");
00511 }
00512
00513 QSharedPointer<IState> AutomatonImpl::createState(const QString &name, const QString &label,
00514 bool initial, bool final)
00515 {
00516 if (m_stateMap.contains(name))
00517 {
00518 Q_ASSERT(0 && "state name has to be unique!");
00519 return QSharedPointer<IState>(NULL);
00520 }
00521
00522 QSharedPointer<StateImpl> state(new StateImpl(name, label, initial, final, NULL));
00523 Q_ASSERT(state);
00524
00525 bool ret = addState(state);
00526 Q_UNUSED(ret);
00527 Q_ASSERT(ret && "state couldn't be added!");
00528
00529 return state;
00530 }
00531
00532 QSharedPointer<ITransition> AutomatonImpl::createTransition(const QString &source, const QString &dest,
00533 const ITransition::TCharSet &characters)
00534 {
00535 if (!m_stateMap.contains(source) || !m_stateMap.contains(dest) || characters.isEmpty())
00536 {
00537 Q_ASSERT(0 && "some state doesn't exist!");
00538 return QSharedPointer<ITransition>(NULL);
00539 }
00540
00541 if (allowRedundantTransitions())
00542 {
00543 QSharedPointer<TransitionImpl> newTransition(new TransitionImpl(source, dest, characters, NULL));
00544 Q_ASSERT(newTransition);
00545 bool ret = addTransition(newTransition);
00546 Q_UNUSED(ret)
00547 Q_ASSERT(ret && "transition couldn't be added!");
00548
00549 return newTransition;
00550 }
00551
00552 ITransition::TCharSet tmpCharacters = characters;
00553
00554 bool eps = tmpCharacters.remove(getEpsilonSymbol());
00555 bool created = false;
00556 if (eps)
00557 {
00558 QSharedPointer<TransitionImpl> newTransition =
00559 createPrivateTransitionInternal(source, dest, ITransition::TCharSet() << getEpsilonSymbol(), created);
00560 Q_ASSERT(newTransition);
00561 if (created)
00562 {
00563 bool ret = addTransition(newTransition);
00564 Q_UNUSED(ret)
00565 Q_ASSERT(ret && "transition couldn't be added!");
00566 }
00567 if (tmpCharacters.isEmpty()) return newTransition;
00568 }
00569
00570 created = false;
00571 QSharedPointer<TransitionImpl> newTransition = createPrivateTransitionInternal(source, dest, tmpCharacters, created);
00572 Q_ASSERT(newTransition);
00573 if (created)
00574 {
00575 bool ret = addTransition(newTransition);
00576 Q_UNUSED(ret)
00577 Q_ASSERT(ret && "transition couldn't be added!");
00578 }
00579 return newTransition;
00580 }
00581
00582 QSharedPointer<TransitionImpl> AutomatonImpl::createPrivateTransitionInternal
00583 (const QString &source, const QString &dest, const ITransition::TCharSet &characters, bool &created)
00584 {
00585 QSharedPointer<StateImpl> state = getPrivateState(source);
00586 TransitionImpl::TTransitionList transitions = state->getPrivateTransitions();
00587
00588 return createPrivateTransitionIfNotExists(source, dest, characters, transitions, created, NULL);
00589 }
00590
00591 QSharedPointer<TransitionImpl> AutomatonImpl::createAndAddPrivateTransition
00592 (const QString &source, const QString &dest, const ITransition::TCharSet &characters, Transition *graphicsTransition)
00593 {
00594 QSharedPointer<StateImpl> state = getPrivateState(source);
00595 TransitionImpl::TTransitionList transitions = state->getPrivateTransitions();
00596
00597 bool created = false;
00598 QSharedPointer<TransitionImpl> newTransition = createPrivateTransition(source, dest, characters, transitions, created, graphicsTransition);
00599 Q_ASSERT(newTransition);
00600 if (created)
00601 {
00602 bool ret = addTransition(newTransition);
00603 Q_UNUSED(ret)
00604 Q_ASSERT(ret && "transition couldn't be added!");
00605 }
00606 return newTransition;
00607 }
00608
00609 QSharedPointer<TransitionImpl> AutomatonImpl::createPrivateTransition
00610 (const QString &source, const QString &dest, const ITransition::TCharSet &characters,
00611 const TransitionImpl::TTransitionList &transitions, bool &created, Transition *graphicsTransition)
00612 {
00613 if (!m_stateMap.contains(source) || !m_stateMap.contains(dest) || characters.isEmpty())
00614 {
00615 Q_ASSERT(0 && "some state doesn't exist!");
00616 return QSharedPointer<TransitionImpl>(NULL);
00617 }
00618
00619 if (allowRedundantTransitions())
00620 {
00621 created = true;
00622 return QSharedPointer<TransitionImpl>(new TransitionImpl(source, dest, characters, graphicsTransition));
00623 }
00624
00625 return createPrivateTransitionIfNotExists(source, dest, characters, transitions, created, graphicsTransition);
00626 }
00627
00628 QSharedPointer<TransitionImpl> AutomatonImpl::createPrivateTransitionIfNotExists
00629 (const QString &source, const QString &dest, const ITransition::TCharSet &characters,
00630 const TransitionImpl::TTransitionList &transitions, bool &created, Transition *graphicsTransition)
00631 {
00632 ITransition::TCharSet tmpCharacters = characters;
00633
00634 bool eps = tmpCharacters.remove(getEpsilonSymbol());
00635 if (eps)
00636 {
00637 Q_ASSERT(tmpCharacters.isEmpty() && "epsilon transition has to be created separately!!!");
00638 #ifdef QT_NO_DEBUG
00639 if (!tmpCharacters.isEmpty())
00640 RELLOG("Epsilon transition has to be created separately when redundancies are disallowed!");
00641 #endif
00642 return createEpsilonTransitionIfNotExists(source, dest, getEpsilonSymbol(), transitions, created, graphicsTransition);
00643 }
00644 else
00645 {
00646 Q_ASSERT(!tmpCharacters.isEmpty() && "no characters for transition!!!");
00647 return createCharactersTransitionIfNotExists(source, dest, tmpCharacters, transitions, created, graphicsTransition);
00648 }
00649 }
00650
00651 QSharedPointer<TransitionImpl> AutomatonImpl::createEpsilonTransitionIfNotExists
00652 (const QString &source, const QString &dest, const QString &epsilonSymbol,
00653 const TransitionImpl::TTransitionList &transitions, bool &created, Transition *graphicsTransition)
00654 {
00655 foreach(const QSharedPointer<TransitionImpl> &transition, transitions)
00656 {
00657 if (transition->getSourceState() != source || transition->getDestinationState() != dest) continue;
00658
00659 if (transition->getCharacters().contains(epsilonSymbol))
00660 {
00661 Q_ASSERT(transition->getCharacters().size() == 1 &&
00662 "should be transition only for epsilon symbol when redundancies aren't allowed");
00663 return transition;
00664 }
00665 }
00666 created = true;
00667 return QSharedPointer<TransitionImpl>(new TransitionImpl(source, dest, ITransition::TCharSet() << getEpsilonSymbol(), graphicsTransition));
00668 }
00669
00670 QSharedPointer<TransitionImpl> AutomatonImpl::createCharactersTransitionIfNotExists
00671 (const QString &source, const QString &dest, ITransition::TCharSet &characters,
00672 const TransitionImpl::TTransitionList &transitions, bool &created, Transition *graphicsTransition)
00673 {
00674 foreach(const QSharedPointer<TransitionImpl> &transition, transitions)
00675 {
00676 if (transition->getSourceState() != source ||transition->getDestinationState() != dest) continue;
00677
00678 characters |= transition->getCharacters();
00679 transition->setCharacters(characters);
00680 return transition;
00681 }
00682 created = true;
00683 return QSharedPointer<TransitionImpl>(new TransitionImpl(source, dest, characters, graphicsTransition));
00684 }
00685
00686 IState::TIStateList AutomatonImpl::getStates() const
00687 {
00688 return trSharedPointerListStaticCast<StateImpl, IState>(getPrivateStates());
00689 }
00690
00691 IState::TIStateList AutomatonImpl::getInitialStates() const
00692 {
00693 IState::TIStateList initialStates;
00694
00695 StateImpl::TStateList states = getPrivateStates();
00696 foreach(const QSharedPointer<StateImpl> &state, states)
00697 {
00698 if (state->isInitial())
00699 initialStates << state;
00700 }
00701
00702 return initialStates;
00703 }
00704
00705 IState::TIStateList AutomatonImpl::getFinalStates() const
00706 {
00707 IState::TIStateList finalStates;
00708
00709 StateImpl::TStateList states = getPrivateStates();
00710 foreach(const QSharedPointer<StateImpl> &state, states)
00711 {
00712 if (state->isFinal())
00713 finalStates << state;
00714 }
00715
00716 return finalStates;
00717 }
00718
00719 IState::TIStateNameList AutomatonImpl::getStateNameList() const
00720 {
00721 return m_stateMap.keys();
00722 }
00723
00724 StateImpl::TStateList AutomatonImpl::getPrivateStates() const
00725 {
00726 return m_stateMap.values();
00727 }
00728
00729 StateImpl::TStateList AutomatonImpl::getPrivateInitialStates() const
00730 {
00731 StateImpl::TStateList initialStates;
00732
00733 StateImpl::TStateList states = getPrivateStates();
00734 foreach(const QSharedPointer<StateImpl> &state, states)
00735 {
00736 if (state->isInitial())
00737 initialStates << state;
00738 }
00739
00740 return initialStates;
00741 }
00742
00743 StateImpl::TStateList AutomatonImpl::getPrivateFinalStates() const
00744 {
00745 StateImpl::TStateList finalStates;
00746
00747 StateImpl::TStateList states = getPrivateStates();
00748 foreach(const QSharedPointer<StateImpl> &state, states)
00749 {
00750 if (state->isFinal())
00751 finalStates << state;
00752 }
00753
00754 return finalStates;
00755 }
00756
00757 IAutomaton::TPositioningMap AutomatonImpl::getPositioningMap() const
00758 {
00759 return m_positioningMap;
00760 }
00761
00762 void AutomatonImpl::setPositioningMap(const IAutomaton::TPositioningMap &map)
00763 {
00764 m_positioningMap = map;
00765 }
00766
00767 ITransition::TITransitionList AutomatonImpl::getTransitions() const
00768 {
00769 return trSharedPointerListStaticCast<TransitionImpl, ITransition>(m_transitions);
00770 }
00771
00772 TransitionImpl::TTransitionList AutomatonImpl::getPrivateTransitions() const
00773 {
00774 return m_transitions;
00775 }
00776
00777 QSharedPointer<ITransitionTable> AutomatonImpl::getTransitionTable() const
00778 {
00779 QSharedPointer<ITransitionTable> trTable(new TransitionTableImpl());
00780
00781 QSharedPointer<ITTRow> ttRow;
00782
00783 IState::TIStateNameSet foundedStates;
00784 IState::TIStateList initialStates = getInitialStates();
00785
00786 IState::TIStateNameSet restStates = m_stateMap.uniqueKeys().toSet();
00787
00788 while (!restStates.isEmpty())
00789 {
00790 foreach(const QSharedPointer<IState> &state, initialStates)
00791 {
00792 if (foundedStates.contains(state->getName())) continue;
00793 foundedStates << state->getName();
00794
00795 QQueue<QSharedPointer<IState> > openedStates;
00796 openedStates.enqueue(state);
00797
00798 QSharedPointer<IState> currentState;
00799 while(!openedStates.empty())
00800 {
00801 currentState = openedStates.dequeue();
00802
00803 ttRow = QSharedPointer<ITTRow>(new TTRowImpl(QStringList(currentState->getName())));
00804 fillRowData(currentState, *ttRow);
00805 ttRow->setInitialFlag(currentState->isInitial());
00806 ttRow->setFinalFlag(currentState->isFinal());
00807 trTable->addRow(ttRow);
00808
00809 ITransition::TITransitionList currentTransitions = currentState->getTransitions();
00810 foreach(const QSharedPointer<ITransition> &tr, currentTransitions)
00811 {
00812 QString workState = tr->getDestinationState();
00813 if (foundedStates.contains(workState)) continue;
00814 foundedStates << workState;
00815
00816 openedStates << getState(workState);
00817 }
00818 }
00819 }
00820
00821 restStates -= foundedStates;
00822 initialStates.clear();
00823 foreach(const QString &stateName, restStates)
00824 {
00825 initialStates << getState(stateName);
00826 }
00827 }
00828
00829 return trTable;
00830 }
00831
00832 void AutomatonImpl::setAlphabet(const ITransition::TCharSet &alphabet)
00833 {
00834 m_alphabet = alphabet;
00835 }
00836
00837 void AutomatonImpl::setAlphabetSymbol(const QString &alphabetSymbol)
00838 {
00839 m_alphabetSymbol = alphabetSymbol;
00840 }
00841
00842 void AutomatonImpl::setEpsilonSymbol(const QString &epsilonSymbol)
00843 {
00844 m_epsilonSymbol = epsilonSymbol;
00845 }
00846
00847 ITransition::TCharSet AutomatonImpl::getAlphabet() const
00848 {
00849 return m_alphabet;
00850 }
00851
00852 QString AutomatonImpl::getAlphabetSymbol() const
00853 {
00854 return m_alphabetSymbol;
00855 }
00856
00857 QString AutomatonImpl::getEpsilonSymbol() const
00858 {
00859 return m_epsilonSymbol;
00860 }
00861
00862 bool AutomatonImpl::addState(const QSharedPointer<StateImpl> &state)
00863 {
00864 if (m_stateMap.contains(state->getName()))
00865 {
00866 Q_ASSERT(0 && "unexpected state, check logic of client code");
00867 return false;
00868 }
00869
00870 m_stateMap[state->getName()] = state;
00871 return true;
00872 }
00873
00874 QSharedPointer<StateImpl> AutomatonImpl::getPrivateState(const QString &name) const
00875 {
00876 if (!m_stateMap.contains(name))
00877 {
00878 Q_ASSERT(0 && "State doesn't exist!!!");
00879 return QSharedPointer<StateImpl>(NULL);
00880 }
00881 return m_stateMap[name];
00882 }
00883
00884 QSharedPointer<IState> AutomatonImpl::getState(const QString &name) const
00885 {
00886 return getPrivateState(name);
00887 }
00888
00889 bool AutomatonImpl::removeState(const QSharedPointer<IState> &state)
00890 {
00891 return removeState(state->getName());
00892 }
00893
00894 bool AutomatonImpl::removeState(const QString &stateName)
00895 {
00896 if (!m_stateMap.contains(stateName))
00897 {
00898 Q_ASSERT(0 && "unexpected state, check logic of client code");
00899 return false;
00900 }
00901
00902 QSharedPointer<StateImpl> state = m_stateMap[stateName];
00903 Q_ASSERT(state->getName() == stateName);
00904
00905
00906 TransitionImpl::TTransitionList transitions = state->getPrivateTransitions();
00907 foreach(const QSharedPointer<TransitionImpl> &tr, transitions)
00908 {
00909 removeTransition(tr);
00910 }
00911
00912 transitions = state->getPrivateTransitionsTo();
00913 foreach(const QSharedPointer<TransitionImpl> &tr, transitions)
00914 {
00915 removeTransition(tr);
00916 }
00917
00918 m_stateMap.remove(stateName);
00919
00920 return true;
00921 }
00922
00923 bool AutomatonImpl::renameState(const QSharedPointer<IState> &state,
00924 const QString &newName)
00925 {
00926 if (!m_stateMap.contains(state->getName()))
00927 {
00928 Q_ASSERT(0 && "unexpected state, check logic of client code");
00929 return false;
00930 }
00931
00932 QSharedPointer<StateImpl> stateImpl = getPrivateState(state->getName());
00933
00934 m_stateMap.remove(state->getName());
00935
00936 stateImpl->setName(newName);
00937 m_stateMap[newName] = stateImpl;
00938
00939 return true;
00940 }
00941
00942 bool AutomatonImpl::removeTransition(const QSharedPointer<TransitionImpl> &tr)
00943 {
00944 if (!m_stateMap.contains(tr->getSourceState()) ||
00945 !m_stateMap.contains(tr->getDestinationState()))
00946 {
00947 RELLOG("transition couldn't be in automaton, some of its states aren't here!");
00948 return false;
00949 }
00950
00951 m_stateMap[tr->getSourceState()]->removeTransition(tr);
00952 m_stateMap[tr->getDestinationState()]->removeTransitionTo(tr);
00953
00954 return m_transitions.removeOne(tr);
00955 }
00956
00957 bool AutomatonImpl::removeTransition(const QSharedPointer<ITransition> &tr)
00958 {
00959 Q_ASSERT(0 && "not implemented yet");
00960 Q_UNUSED(tr);
00961
00962
00963
00964 return false;
00965 }
00966
00967 bool AutomatonImpl::addTransition(const QSharedPointer<TransitionImpl> &tr)
00968 {
00969 if (!m_stateMap.contains(tr->getSourceState()) ||
00970 !m_stateMap.contains(tr->getDestinationState()))
00971 {
00972 Q_ASSERT(0 && "Some state doesn't exist, check logic of client code");
00973 return false;
00974 }
00975
00976 m_transitions << tr;
00977
00978 m_stateMap[tr->getSourceState()]->addTransition(tr);
00979 m_stateMap[tr->getDestinationState()]->addTransitionTo(tr);
00980
00981 return true;
00982 }
00983
00984 void AutomatonImpl::addLists(const StateImpl::TStateList &states,
00985 const TransitionImpl::TTransitionList &transitions)
00986 {
00987 foreach(const QSharedPointer<StateImpl> &state, states)
00988 {
00989 m_stateMap[state->getName()] = state;
00990 }
00991
00992 m_transitions << transitions;
00993 }
00994
00995 bool AutomatonImpl::hasMultipleInitials() const
00996 {
00997 return (getInitialStates().count() > 1);
00998 }
00999
01000 bool AutomatonImpl::hasEpsilonTransitions() const
01001 {
01002 foreach(const QSharedPointer<ITransition> &tr, m_transitions)
01003 {
01004 if (tr->getCharacters().contains(m_epsilonSymbol))
01005 return true;
01006 }
01007
01008 return false;
01009 }
01010
01011 bool AutomatonImpl::isDeterministic() const
01012 {
01013 if (hasMultipleInitials() || hasEpsilonTransitions()) return false;
01014
01015 for(StateImpl::TStateMap::ConstIterator stateIt = m_stateMap.begin();
01016 stateIt != m_stateMap.end();
01017 ++stateIt)
01018 {
01019 const QSharedPointer<IState> &state = stateIt.value();
01020 foreach(const QString &character, m_alphabet)
01021 {
01022 if (state->getStatesOn(character).count() > 1) return false;
01023 }
01024 }
01025
01026 return true;
01027 }
01028
01029 bool AutomatonImpl::hasState(const QString &name) const
01030 {
01031 return m_stateMap.contains(name);
01032 }
01033
01034 ITransition::TCharSet AutomatonImpl::getTransitionSymbols(const QString &source, const QString &dest) const
01035 {
01036 if (!hasState(source) || !hasState(dest)) return ITransition::TCharSet();
01037
01038 const QSharedPointer<IState> state = getState(source);
01039 ITransition::TITransitionList transitions = state->getTransitions();
01040
01041 ITransition::TCharSet result;
01042 foreach(const QSharedPointer<ITransition> &tr, transitions)
01043 {
01044 if (tr->getDestinationState() != dest) continue;
01045
01046 result |= tr->getCharacters();
01047 }
01048
01049 return result;
01050 }
01051
01052 void AutomatonImpl::setAllowRedundantTransitions(bool allow)
01053 {
01054 Q_ASSERT(m_transitions.isEmpty());
01055 if (!m_transitions.isEmpty())
01056 {
01057 RELLOG("automaton already contains transition, setting " <<
01058 DBGPAR(allow) << "has no effect!");
01059 return;
01060 }
01061 m_allowRenundancies = allow;
01062 }
01063
01064 void AutomatonImpl::reset()
01065 {
01066 m_activeStates = getPrivateInitialStates();
01067 m_processedString.clear();
01068 }
01069
01070 bool AutomatonImpl::processCharacter(const QString &character)
01071 {
01072 IState::TIStateNameSet names;
01073 StateImpl::TStateList newActiveStates;
01074 foreach(const QSharedPointer<StateImpl> &state, m_activeStates)
01075 {
01076 IState::TIStateNameSet nextStates = state->getStatesOn(character);
01077 foreach(const QString &stateName, nextStates)
01078 {
01079 if (names.contains(stateName)) continue;
01080 names << stateName;
01081 newActiveStates << getPrivateState(stateName);
01082 }
01083 }
01084
01085
01086 m_activeStates = newActiveStates;
01087 m_processedString << character;
01088
01089 return !names.empty();
01090 }
01091
01092 bool AutomatonImpl::isConfigurationAccepted() const
01093 {
01094 foreach(const QSharedPointer<StateImpl> &state, m_activeStates)
01095 {
01096 if (state->isFinal()) return true;
01097 }
01098
01099 return false;
01100 }
01101
01102 IState::TIStateList AutomatonImpl::getActiveStates() const
01103 {
01104 return trSharedPointerListStaticCast<StateImpl, IState>(getPrivateActiveStates());
01105 }
01106
01107 QStringList AutomatonImpl::getActiveStatesNames() const
01108 {
01109 QStringList result;
01110
01111 foreach(const QSharedPointer<StateImpl> &state, m_activeStates)
01112 {
01113 result << state->getName();
01114 }
01115
01116 return result;
01117 }
01118
01119 StateImpl::TStateList AutomatonImpl::getPrivateActiveStates() const
01120 {
01121 return m_activeStates;
01122 }
01123
01124 QStringList AutomatonImpl::getProcessedString() const
01125 {
01126 return m_processedString;
01127 }
01128
01129 IState::TIStateNameSet AutomatonImpl::processCharacterWithInfo
01130 (const QString &character, QList<QPainterPath> &paths)
01131 {
01132 IState::TIStateNameSet result;
01133
01134 StateImpl::TStateList activeStates = getPrivateActiveStates();
01135 StateImpl::TStateList newActiveStates;
01136 foreach(const QSharedPointer<StateImpl> &state, activeStates)
01137 {
01138 IState::TIStateNameSet nextStates = state->getStatesAndPathsOn(character, paths);
01139 foreach(const QString &stateName, nextStates)
01140 {
01141 if (result.contains(stateName)) continue;
01142 result << stateName;
01143 newActiveStates << getPrivateState(stateName);
01144 }
01145 }
01146
01147
01148 m_activeStates = newActiveStates;
01149 m_processedString << character;
01150
01151 return result;
01152 }
01153
01154 void AutomatonImpl::fillRowData(const QSharedPointer<IState> &state, ITTRow &row) const
01155 {
01156 QList<QString> usedCharacters;
01157 foreach(const QSharedPointer<ITransition> &tr, state->getTransitions())
01158 {
01159 foreach(const QString &character, tr->getCharacters())
01160 {
01161 if (usedCharacters.contains(character)) continue;
01162 usedCharacters << character;
01163
01164 row[character] = QStringList(state->getStatesOn(character).toList());
01165 }
01166 }
01167 }
01168
01169
01170
01171
01172
01173
01174
01175 QSharedPointer<AutomatonImpl> AutomataCreator::createPrivateAutomaton
01176 (const ITransition::TCharSet &alphabet,
01177 const QString &alphabetSymbol,
01178 const QString &epsilonSymbol)
01179 {
01180 return QSharedPointer<AutomatonImpl>(
01181 new AutomatonImpl(alphabet, alphabetSymbol, epsilonSymbol));
01182 }
01183
01184 QSharedPointer<StateImpl> AutomataCreator::createPrivateState
01185 (const QString &name, const QString &label, bool initial, bool final, State *graphicsState)
01186 {
01187 return QSharedPointer<StateImpl>(
01188 new StateImpl(name, label, initial, final, graphicsState));
01189 }
01190
01191 QSharedPointer<IAutomaton> AutomataCreator::createAutomaton(const ITransition::TCharSet &alphabet,
01192 const QString &alphabetSymbol,
01193 const QString &epsilonSymbol)
01194 {
01195 return QSharedPointer<IAutomaton>(new AutomatonImpl(alphabet, alphabetSymbol, epsilonSymbol));
01196 }