• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

C:/CVUT/diplomka/Automata_editor/sources/automataCreator.cpp

Go to the documentation of this file.
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 //<-- TTRowImpl -------------------------------------------------------
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     /*QStringList& headRef()
00053     {
00054         return m_head;
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 //------------------------------------------------------- TTRowImpl -->
00096 
00097 
00098 
00099 //<-- TransitionTableImpl ---------------------------------------------
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             //laTeXTable += "\\hline\n";
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 //--------------------------------------------- TransitionTableImpl -->
00251 
00252 
00253 
00254 
00255 //<-- TransitionImpl --------------------------------------------------
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 //-------------------------------------------------- TransitionImpl -->
00312 
00313 
00314 
00315 //<-- StateImpl -------------------------------------------------------
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 //------------------------------------------------------- StateImpl -->
00494 
00495 
00496 
00497 //<-- AutomatonImpl ---------------------------------------------------
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) // if created, add it to automaton, otherwise is already added, so just return
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) // it's epsilon transition, check if exists, otherwise create new
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 // it's transition on some characters, check if exists, otherwise create new
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); // implicit cast ...
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     // remove related transitions too
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     // TODO: implement this -> maybe use dynamic_cast and simply return false
00962     //       if it's impossible to cast ITransition to TransitionImpl
00963     //       and if it's ok, call overloaded removeTransition for TransitionImpl
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     // change current configuration
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     // change current configuration
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 //--------------------------------------------------- AutomatonImpl -->
01170 
01171 /*--------------------------------------------|
01172  * AutomataCreator functions                  |
01173  *--------------------------------------------V*/
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 }

Generated on Tue Jan 4 2011 03:03:22 for Autoamata editor by  doxygen 1.7.0