reglibcpp  1.3.0
(Naïve) C++ implementation of models for regular languages
Classes | Public Member Functions | List of all members
reg::dfa::builder Class Reference

Constructs DFAs step by step. More...

#include <dfa.h>

Classes

struct  pImpl
 Private implementation details of DFA builders. More...
 

Public Member Functions

 builder ()
 Constructs a blank builder object. More...
 
 builder (dfa const &dfa)
 Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a given DFA. More...
 
 builder (nfa const &nfa)
 Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a DFA resulting from a powerset construction. More...
 
 builder (builder const &b)
 Copy-constructs a builder by copying another one's private implementation object. More...
 
 builder (builder &&b)
 Move-constructs a builder by stealing another one's private implementation object. More...
 
builderoperator= (const builder &b)
 Copy-assigns a builder by copying another one's private implementation object. More...
 
builderoperator= (builder &&b)
 Move-assigns a builder by stealing another one's private implementation object. More...
 
builderaddSymbol (char32_t symbol)
 Adds a symbol to the prospective DFA's alphabet. More...
 
builderaddSymbol (std::string const &utf8Symbol)
 Same as above for a a UTF-8-encoded symbol. More...
 
buildersetAccepting (std::string const &state, bool accept)
 Sets whether or not a state will be accepting within the prospective DFA. More...
 
buildermakeInitial (std::string const &state)
 Resets the initial state for the prospective DFA. More...
 
builderdefineTransition (std::string const &from, std::string const &to, char32_t symbol)
 (Re-)Defines a transition for the prospective DFA. More...
 
builderdefineTransition (std::string const &from, std::string const &to, std::string const &utf8Symbol)
 Same as above for a UTF-8-encoded symbol. More...
 
buildermerge ()
 Merges the prospective DFA's indistinguishable states, allowing for minimization. More...
 
builderpurge ()
 Purges the prospective DFA of unreachable and non-producing states, allowing for minimization. More...
 
builderminimize ()
 Convenience method for chaining purge and merge to achieve proper minimization. More...
 
builderunite (dfa const &other)
 Makes the prospective DFA also accept every word of another DFA's language. More...
 
builderintersect (dfa const &other)
 Makes the prospective DFA accept only words accepted also by another DFA. More...
 
buildercomplement ()
 Inverts the prospective DFA's language with respect to all possible strings over its alphabet. More...
 
buildernormalizeStateNames (std::string const &prefix)
 Reduces the prospective NFA's state names to consecutive numbers, prefixed with a given string. More...
 
dfa build ()
 Builds the DFA, as defined by previous operations, including completion. More...
 

Detailed Description

Constructs DFAs step by step.

Any mention of a symbol or state will add them to the alphabet/set of states. The first state mentioned will be designated initial state.

Definition at line 60 of file dfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

reg::dfa::builder::builder ( )

Constructs a blank builder object.

Definition at line 500 of file dfa.cpp.

500 : p(new pImpl) {}

◆ builder() [2/5]

reg::dfa::builder::builder ( dfa const &  dfa)

Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a given DFA.

Definition at line 503 of file dfa.cpp.

503  {
504  auto initial = dfa.getLabelOf(0);
505  auto alphabet = unordered_set<char32_t>(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
506  auto labels = unordered_set<string>(dfa.getNumberOfStates());
507  auto transitions = Dtransitionmap(dfa.getNumberOfStates());
508  p = make_unique<pImpl>(initial, alphabet, labels, transitions);
509  for (size_t q = 0; q < dfa.getNumberOfStates(); ++q) {
510  for (char32_t symbol : dfa.getAlphabet()) {
511  defineTransition(dfa.getLabelOf(q), dfa.getLabelOf(dfa.delta(q, symbol)), symbol);
512  }
513  setAccepting(dfa.getLabelOf(q), dfa.isAccepting(q));
514  }
515 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:603
dfa()
Constructs a DFA accepting the empty language ∅.
Definition: dfa.cpp:104
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:637

◆ builder() [3/5]

reg::dfa::builder::builder ( nfa const &  nfa)

Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a DFA resulting from a powerset construction.

Definition at line 518 of file dfa.cpp.

518  {
519  unordered_set<valarray<bool>, pImpl::ValarrayBoolHasher, pImpl::ValarrayBoolEqual> done;
520  forward_list<valarray<bool>> stack(1, nfa.epsilonClosure(0));
521  size_t stackSize(1);
522  auto initial = nfa.getLabelOf(stack.front());
523  auto alphabet = nfa.getAlphabet();
524  alphabet.erase(alphabet.begin());
525  unordered_set<char32_t> alphabetS(alphabet.begin(), alphabet.end());
526  unordered_set<string> acceptingStates;
527  Dtransitionmap transitions;
528  transitions[initial];
529  p = make_unique<pImpl>(initial, alphabetS, acceptingStates, transitions);
530  while (stackSize != 0) {
531  valarray<bool> current(move(stack.front()));
532  stack.pop_front();
533  stackSize--;
534  for (char32_t symbol : p->alphabet) {
535  valarray<bool> next(nfa.deltaHat(current, u32string(1, symbol)));
536  defineTransition(nfa.getLabelOf(current), nfa.getLabelOf(next), symbol);
537  pImpl::ValarrayBoolEqualTo equalToNext(next);
538  if (!equalToNext(current) &&
539  none_of(stack.begin(), stack.end(), equalToNext) &&
540  none_of(done.begin(), done.end(), equalToNext)) {
541  stack.push_front(next);
542  stackSize++;
543  }
544  }
545  for (size_t qi(0); qi < current.size(); qi++) {
546  if (current[qi] && nfa.isAccepting(qi)) {
547  setAccepting(nfa.getLabelOf(current), true);
548  break;
549  }
550  }
551  done.insert(current);
552  }
553 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:603
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:637

◆ builder() [4/5]

reg::dfa::builder::builder ( builder const &  b)

Copy-constructs a builder by copying another one's private implementation object.

Definition at line 556 of file dfa.cpp.

556 : p(new pImpl(*(b.p))) {}

◆ builder() [5/5]

reg::dfa::builder::builder ( builder &&  b)

Move-constructs a builder by stealing another one's private implementation object.

The other builder will be blank afterwards.

Definition at line 560 of file dfa.cpp.

560 : p(new pImpl) {p.swap(b.p);}

Member Function Documentation

◆ addSymbol() [1/2]

dfa::builder & reg::dfa::builder::addSymbol ( char32_t  symbol)

Adds a symbol to the prospective DFA's alphabet.

Parameters
symbolthe symbol to add
Returns
reference to this object, for chaining operations

Definition at line 587 of file dfa.cpp.

587  {
588  p->alphabet.insert(symbol);
589  return *this;
590 }

◆ addSymbol() [2/2]

dfa::builder & reg::dfa::builder::addSymbol ( std::string const &  utf8Symbol)

Same as above for a a UTF-8-encoded symbol.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Definition at line 593 of file dfa.cpp.

593  {
594  return addSymbol(converter.from_bytes(utf8Symbol)[0]);
595 }
std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: dfa.cpp:1001
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:587

◆ build()

dfa reg::dfa::builder::build ( )

Builds the DFA, as defined by previous operations, including completion.

Returns
a DFA object with exactly the states, alphabet and transitions that were defined and a trash state if needed

Definition at line 964 of file dfa.cpp.

964  {
965  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
966  std::sort(alphabetV.begin(), alphabetV.end());
967  p->complete();
968  vector<string> labelV;
969  labelV.reserve(p->transitions.size());
970  labelV.push_back(p->initial);
971  for (auto const& tr : p->transitions) {
972  if (tr.first == p->initial) {
973  continue;
974  }
975  labelV.push_back(tr.first);
976  }
977  valarray<bool> acceptingV(false, labelV.size());
978  vector<vector<size_t>> transitionV(labelV.size(), vector<size_t>(alphabetV.size()));
979  for (size_t q(0); q < labelV.size(); q++) {
980  string const& qLabel = labelV[q];
981  acceptingV[q] = (p->acceptingStates.find(qLabel) != p->acceptingStates.end());
982  for (size_t s(0); s < alphabetV.size(); s++) {
983  transitionV[q][s] = index_of(labelV, p->transitions[qLabel][alphabetV[s]]);
984  }
985  }
986  return {alphabetV, transitionV, labelV, acceptingV};
987 }
size_t index_of(vector< T > const &vec, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.cpp:995

◆ complement()

dfa::builder & reg::dfa::builder::complement ( )

Inverts the prospective DFA's language with respect to all possible strings over its alphabet.

Definition at line 919 of file dfa.cpp.

919  {
920  p->complete();
921  for (auto const& fromVia : p->transitions) {
922  if (!p->acceptingStates.erase(fromVia.first)) {
923  p->acceptingStates.insert(fromVia.first);
924  }
925  }
926  return *this;
927 }

◆ defineTransition() [1/2]

dfa::builder & reg::dfa::builder::defineTransition ( std::string const &  from,
std::string const &  to,
char32_t  symbol 
)

(Re-)Defines a transition for the prospective DFA.

If there's already a transition defined from from to to, it will be redefined with the new symbol.

Parameters
fromthe starting state for the transition
tothe destination state for the transition
symbolthe symbol triggering the transition
Returns
reference to this object, for chaining operations

Definition at line 637 of file dfa.cpp.

637  {
638  if (p->transitions.empty()) {
639  p->initial = from;
640  }
641  p->transitions[to];
642  p->transitions[from][symbol] = to;
643  addSymbol(symbol);
644  return *this;
645 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:587

◆ defineTransition() [2/2]

dfa::builder & reg::dfa::builder::defineTransition ( std::string const &  from,
std::string const &  to,
std::string const &  utf8Symbol 
)

Same as above for a UTF-8-encoded symbol.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Definition at line 648 of file dfa.cpp.

648  {
649  return defineTransition(from, to, converter.from_bytes(utf8Symbol)[0]);
650 }
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:637
std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: dfa.cpp:1001

◆ intersect()

dfa::builder & reg::dfa::builder::intersect ( dfa const &  other)

Makes the prospective DFA accept only words accepted also by another DFA.

Concatenates the names of states defined so far with the other DFA's state names and resolves conflicts by appending _.

Parameters
otherthe NFA whose language should also be accepted
Returns
reference to this object, for chaining operations

Definition at line 862 of file dfa.cpp.

862  {
863  if (!p->transitions.empty()) {
864  vector<string> stateNames;
865  stateNames.reserve(p->transitions.size());
866  stateNames.push_back(p->initial);
867  for (auto const& fromTo : p->transitions) {
868  if (fromTo.first != p->initial) {
869  stateNames.push_back(fromTo.first);
870  }
871  }
872  auto const& oAlph = other.getAlphabet();
873  size_t commonSymbols = 0;
874  for (char32_t symbol : p->alphabet) {
875  if (index_of(oAlph, symbol) < oAlph.size()) {
876  commonSymbols++;
877  } else {
878  for (auto & fromVia : p->transitions) {
879  fromVia.second.erase(symbol);
880  }
881  }
882  }
883  p->alphabet.insert(oAlph.begin(), oAlph.end());
884  Dtransitionmap newTr(stateNames.size() * other.getNumberOfStates());
885  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
886  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
887  for (size_t q = 0; q < stateNames.size(); q++) {
888  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
889  string potentialName = stateNames[q] + other.getLabelOf(qq);
890  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
891  potentialName.append("_");
892  }
893  auto nameIt = newTr.emplace(potentialName, commonSymbols);
894  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
895  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() && other.isAccepting(qq)) {
896  newAcc.insert(potentialName);
897  }
898  }
899  }
900  for (size_t q = 0; q < stateNames.size(); q++) {
901  auto const& qLabel = stateNames[q];
902  auto const& viaTos = p->transitions[qLabel];
903  for (auto const& viaTo : viaTos) {
904  size_t p = index_of(stateNames, viaTo.second);
905  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
906  size_t pp = other.delta(qq, viaTo.first);
907  newTr[*(pairToName[q][qq])][viaTo.first] = *(pairToName[p][pp]);
908  }
909  }
910  }
911  p->transitions = newTr;
912  p->acceptingStates = newAcc;
913  p->initial = *(pairToName[0][0]);
914  }
915  return *this;
916 }
size_t index_of(vector< T > const &vec, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.cpp:995

◆ makeInitial()

dfa::builder & reg::dfa::builder::makeInitial ( std::string const &  state)

Resets the initial state for the prospective DFA.

Parameters
statethe new initial state
Returns
reference to this object, for chaining operations

Definition at line 621 of file dfa.cpp.

621  {
622  p->initial = state;
623  p->transitions[state];
624  return *this;
625 }

◆ merge()

dfa::builder & reg::dfa::builder::merge ( )

Merges the prospective DFA's indistinguishable states, allowing for minimization.

This method doesn't change the prospective DFA's accepted language, but it will be built with the minimum of reachable states to fulfill that purpose. Unreachable states will be merged since they are indistinguishable, but they won't be removed, hence preventing true minimization; that's what purge is for.

Returns
reference to this object, for chaining operations

Definition at line 662 of file dfa.cpp.

662  {
663  p->complete();
664  vector<vector<size_t>> tTable(p->transitions.size());
665  valarray<bool> accepting(false, p->transitions.size());
666  vector<char32_t> sortedAlphabet(p->alphabet.begin(), p->alphabet.end());
667  std::sort(sortedAlphabet.begin(), sortedAlphabet.end());
668  vector<string> orderedStates;
669  orderedStates.reserve(p->transitions.size());
670  orderedStates.push_back(p->initial);
671  for (auto const& entry : p->transitions) {
672  if (entry.first != p->initial) {
673  orderedStates.push_back(entry.first);
674  }
675  }
676  for (size_t q(0); q < orderedStates.size(); q++) {
677  string const& qLabel(orderedStates[q]);
678  if (p->acceptingStates.find(qLabel) != p->acceptingStates.end()) {
679  accepting[q] = true;
680  }
681  for (size_t s(0); s < sortedAlphabet.size(); s++) {
682  tTable[q].push_back(index_of(orderedStates, p->transitions[qLabel][sortedAlphabet[s]]));
683  }
684  }
685  vector<valarray<bool>> equivalences(dfa::pImpl::indistinguishableStates(tTable, accepting));
686  for (size_t q(0); q < orderedStates.size(); q++) {
687  for (size_t first(0); first < equivalences[q].size(); first++) {
688  if (equivalences[q][first] && q > first) {
689  string const& superfluous(orderedStates[q]);
690  string const& remaining(orderedStates[first]);
691  p->acceptingStates.erase(superfluous);
692  p->transitions.erase(superfluous);
693  for (auto& from : p->transitions) {
694  for (auto& via : from.second) {
695  if (via.second == superfluous) {
696  via.second = remaining;
697  }
698  }
699  }
700  break;
701  }
702  }
703  }
704  return *this;
705 }
static vector< valarray< bool > > indistinguishableStates(vector< vector< size_t >> const &transitions, valarray< bool > const &accepting)
Builds the table of indistinguishable states w.r.t. a transition function.
Definition: dfa.cpp:61
size_t index_of(vector< T > const &vec, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.cpp:995

◆ minimize()

dfa::builder & reg::dfa::builder::minimize ( )

Convenience method for chaining purge and merge to achieve proper minimization.

Definition at line 773 of file dfa.cpp.

773  {
774  return purge().merge();
775 }
builder & purge()
Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.
Definition: dfa.cpp:714
builder & merge()
Merges the prospective DFA's indistinguishable states, allowing for minimization. ...
Definition: dfa.cpp:662

◆ normalizeStateNames()

dfa::builder & reg::dfa::builder::normalizeStateNames ( std::string const &  prefix)

Reduces the prospective NFA's state names to consecutive numbers, prefixed with a given string.

Definition at line 930 of file dfa.cpp.

930  {
931  if (!p->transitions.empty()) {
932  vector<string> stateNames;
933  stateNames.reserve(p->transitions.size());
934  stateNames.push_back(p->initial);
935  for (auto const& fromTo : p->transitions) {
936  if (fromTo.first != p->initial) {
937  stateNames.push_back(fromTo.first);
938  }
939  }
940  Dtransitionmap newTr(p->transitions.size());
941  unordered_set<string> newAcc(p->acceptingStates.size());
942  for (size_t q = 0; q < stateNames.size(); q++) {
943  auto const& vias = p->transitions[stateNames[q]];
944  unordered_map<char32_t,string> newVias(vias.size());
945  for (auto const& viaTo : vias) {
946  newVias.insert(make_pair(viaTo.first, string(prefix).append(std::to_string(index_of(stateNames, viaTo.second)))));
947  }
948  newTr.insert(make_pair(string(prefix).append(std::to_string(q)), newVias));
949  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end()) {
950  newAcc.insert(string(prefix).append(std::to_string(q)));
951  }
952  }
953  p->initial = string(string(prefix).append("0"));
954  p->transitions = newTr;
955  p->acceptingStates = newAcc;
956  }
957  return *this;
958 }
size_t index_of(vector< T > const &vec, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.cpp:995

◆ operator=() [1/2]

dfa::builder & reg::dfa::builder::operator= ( const builder b)

Copy-assigns a builder by copying another one's private implementation object.

Definition at line 563 of file dfa.cpp.

563  {
564  if (this != &b) {
565  p.reset(new pImpl(*(b.p)));
566  }
567  return *this;
568 }

◆ operator=() [2/2]

dfa::builder & reg::dfa::builder::operator= ( dfa::builder &&  b)

Move-assigns a builder by stealing another one's private implementation object.

The other builder will be blank afterwards.

Definition at line 572 of file dfa.cpp.

572  {
573  if (this != &b) {
574  p.reset(new pImpl);
575  p.swap(b.p);
576  }
577  return *this;
578 }

◆ purge()

dfa::builder & reg::dfa::builder::purge ( )

Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.

This method doesn't change the prospective DFA's accepted language, but it will be built without states that will never be reached.

Returns
reference to this object, for chaining operations

Definition at line 714 of file dfa.cpp.

714  {
715  unordered_set<string> reachable(&(p->initial), &(p->initial)+1);
716  unordered_set<string> newReachable(reachable);
717  while (newReachable.size() > 0) {
718  unordered_set<string> oldReachable(move(newReachable));
719  newReachable.clear();
720  for (string const& reachableState : oldReachable) {
721  for (auto const& reachedState : p->transitions[reachableState]) {
722  if (reachable.insert(reachedState.second).second) {
723  newReachable.insert(reachedState.second);
724  }
725  }
726  }
727  }
728  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
729  if (reachable.find(it->first) == reachable.end()) {
730  p->acceptingStates.erase(it->first);
731  it = p->transitions.erase(it);
732  } else {
733  it++;
734  }
735  }
736  unordered_set<string> producing(p->acceptingStates);
737  unordered_set<string> newProducing(producing);
738  while (newProducing.size() > 0) {
739  unordered_set<string> oldProducing(move(newProducing));
740  newProducing.clear();
741  for (auto const& from : p->transitions) {
742  for (auto const& via : from.second) {
743  if (producing.find(via.second) != producing.end()) {
744  if (producing.insert(from.first).second) {
745  newProducing.insert(from.first);
746  }
747  break;
748  }
749  }
750  }
751  }
752  for (auto it = p->transitions.begin(); it != p->transitions.end(); ) {
753  if (producing.find(it->first) == producing.end() && it->first != p->initial) {
754  p->acceptingStates.erase(it->first);
755  for (auto& via : p->transitions) {
756  for (auto itv = via.second.begin(); itv != via.second.end(); ) {
757  if (itv->second == it->first) {
758  itv = via.second.erase(itv);
759  } else {
760  itv++;
761  }
762  }
763  }
764  it = p->transitions.erase(it);
765  } else {
766  it++;
767  }
768  }
769  return *this;
770 }

◆ setAccepting()

dfa::builder & reg::dfa::builder::setAccepting ( std::string const &  state,
bool  accept 
)

Sets whether or not a state will be accepting within the prospective DFA.

Parameters
statethe state's name
accepttrue if the state should be an accept state afterwards, false else
Returns
reference to this object, for chaining operations

Definition at line 603 of file dfa.cpp.

603  {
604  if (p->transitions.empty()) {
605  p->initial = state;
606  }
607  p->transitions[state];
608  if (accept) {
609  p->acceptingStates.insert(state);
610  } else {
611  p->acceptingStates.erase(state);
612  }
613  return *this;
614 }

◆ unite()

dfa::builder & reg::dfa::builder::unite ( dfa const &  other)

Makes the prospective DFA also accept every word of another DFA's language.

Concatenates the names of states defined so far with the other DFA's state names and resolves conflicts by appending _.

Parameters
otherthe DFA whose language should also be accepted
Returns
reference to this object, for chaining operations

Definition at line 784 of file dfa.cpp.

784  {
785  if (!p->transitions.empty()) {
786  auto const& oAlph = other.getAlphabet();
787  for (char32_t symbol : oAlph) {
788  addSymbol(symbol);
789  }
790  size_t trash = other.getNumberOfStates() * !!(p->alphabet.size() - oAlph.size());
791  p->complete();
792  vector<string> stateNames;
793  stateNames.reserve(p->transitions.size());
794  stateNames.push_back(p->initial);
795  for (auto const& fromVia : p->transitions) {
796  if (fromVia.first != p->initial) {
797  stateNames.push_back(fromVia.first);
798  }
799  }
800  Dtransitionmap newTr(stateNames.size() * other.getNumberOfStates());
801  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
802  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
803  for (size_t q = 0; q < stateNames.size(); q++) {
804  for (size_t qq = 0; qq < other.getNumberOfStates() + !!trash; qq++) {
805  string potentialName = stateNames[q];
806  try {
807  potentialName.append(other.getLabelOf(qq));
808  } catch (std::out_of_range e) {
809  // We hit the trash state.
810  }
811  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
812  potentialName.append("_");
813  }
814  auto nameIt = newTr.emplace(potentialName, p->alphabet.size());
815  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
816  try {
817  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() || other.isAccepting(qq)) {
818  newAcc.insert(potentialName);
819  }
820  } catch (std::out_of_range e) {
821  // We hit the trash state AND q is not accepting.
822  }
823  }
824  }
825  for (size_t q = 0; q < stateNames.size(); q++) {
826  auto const& qLabel = stateNames[q];
827  auto const& viaTos = p->transitions[qLabel];
828  for (auto const& viaTo : viaTos) {
829  size_t p = index_of(stateNames, viaTo.second);
830  for (size_t qq = 0; qq < other.getNumberOfStates() + !!trash; qq++) {
831  size_t pp;
832  try {
833  pp = other.delta(qq, viaTo.first);
834  } catch (std::logic_error e) {
835  pp = trash;
836  }
837  newTr[*(pairToName[q][qq])][viaTo.first] = *(pairToName[p][pp]);
838  }
839  }
840  }
841  p->transitions = newTr;
842  p->acceptingStates = newAcc;
843  p->initial = *(pairToName[0][0]);
844  } else {
845  for (size_t q = 0; q < other.getNumberOfStates(); ++q) {
846  for (char32_t symbol : other.getAlphabet()) {
847  defineTransition(other.getLabelOf(q), other.getLabelOf(other.delta(q, symbol)), symbol);
848  }
849  setAccepting(other.getLabelOf(q), other.isAccepting(q));
850  }
851  }
852  return *this;
853 }
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective DFA.
Definition: dfa.cpp:603
size_t index_of(vector< T > const &vec, T const &element)
Basically Java&#39;s List interface&#39;s indexOf, but as a non-member function and returning the container&#39;s...
Definition: dfa.cpp:995
builder & defineTransition(std::string const &from, std::string const &to, char32_t symbol)
(Re-)Defines a transition for the prospective DFA.
Definition: dfa.cpp:637
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective DFA's alphabet.
Definition: dfa.cpp:587

The documentation for this class was generated from the following files: