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

Constructs NFAs step by step. More...

#include <nfa.h>

Classes

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

Public Member Functions

 builder ()
 Constructs a blank builder object. More...
 
 builder (nfa const &nfa)
 Constructs a builder object with exactly the same states, symbols, transitions, initial state and accept states as a given NFA. 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 (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= (builder const &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 NFA's alphabet. More...
 
builderaddSymbol (std::string const &utf8Symbol)
 Same as above for 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 NFA. More...
 
buildermakeInitial (std::string const &state)
 Resets the initial state for the prospective NFA. More...
 
builderaddTransition (std::string const &from, std::string const &to, char32_t symbol)
 Adds a transition for the prospective NFA. More...
 
builderaddTransition (std::string const &from, std::string const &to, std::string const &utf8Symbol)
 Same as above for a UTF-8-encoded symbol. More...
 
builderunite (nfa const &other)
 Makes the prospective NFA also accept every word of another NFA's language. More...
 
builderintersect (nfa const &other)
 Makes the prospective NFA accept only words accepted also by another NFA. More...
 
buildernormalizeStateNames (std::string const &prefix)
 Reduces the prospective NFA's state names to consecutive numbers, prefixed with a given string. More...
 
nfa build ()
 Builds the NFA, as defined by previous operations. More...
 

Detailed Description

Constructs NFAs 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 88 of file nfa.h.

Constructor & Destructor Documentation

◆ builder() [1/5]

reg::nfa::builder::builder ( )

Constructs a blank builder object.

Definition at line 682 of file nfa.cpp.

682 : p(new pImpl) {}

◆ builder() [2/5]

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

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

Definition at line 685 of file nfa.cpp.

685  : p(new pImpl) {
686  makeInitial(nfa.getLabelOf(0));
687  for (char32_t symbol : nfa.getAlphabet()) {
688  addSymbol(symbol);
689  }
690  for (size_t qi = 0; qi < nfa.p->labels.size(); ++qi) {
691  string const& qLabel = nfa.getLabelOf(qi);
692  for (char32_t symbol : p->alphabet) {
693  valarray<bool> ps = nfa.delta(qi, symbol);
694  size_t pi(0);
695  for (bool pb : ps) {
696  if (pb) {
697  addTransition(qLabel, nfa.getLabelOf(pi), symbol);
698  }
699  pi++;
700  }
701  }
702  if (nfa.isAccepting(qi)) {
703  setAccepting(qLabel, true);
704  }
705  }
706 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective NFA's alphabet.
Definition: nfa.cpp:757
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective NFA.
Definition: nfa.cpp:773
builder & makeInitial(std::string const &state)
Resets the initial state for the prospective NFA.
Definition: nfa.cpp:791
nfa()
Constructs an NFA accepting the empty language ∅.
Definition: nfa.cpp:80
builder & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
Definition: nfa.cpp:804

◆ builder() [3/5]

reg::nfa::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.

Transition destinations will be converted to singleton sets of the respective reached states.

Definition at line 710 of file nfa.cpp.

710  {
711  string initial(dfa.getLabelOf(0));
712  unordered_set<string> acceptingStates;
713  unordered_set<char32_t> alphabet(dfa.getAlphabet().begin(), dfa.getAlphabet().end());
714  Ntransitionmap transitions;
715  transitions[initial];
716  for (size_t q(0); q < dfa.getNumberOfStates(); q++) {
717  for (char32_t symbol : alphabet) {
718  transitions[dfa.getLabelOf(q)][symbol].insert(dfa.getLabelOf(dfa.delta(q, symbol)));
719  }
720  if (dfa.isAccepting(q)) {
721  acceptingStates.insert(dfa.getLabelOf(q));
722  }
723  }
724  p = make_unique<pImpl>(initial, acceptingStates, alphabet, transitions);
725 }
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:654

◆ builder() [4/5]

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

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

Definition at line 728 of file nfa.cpp.

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

◆ builder() [5/5]

reg::nfa::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 732 of file nfa.cpp.

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

Member Function Documentation

◆ addSymbol() [1/2]

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

Adds a symbol to the prospective NFA's alphabet.

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

Definition at line 757 of file nfa.cpp.

757  {
758  p->alphabet.insert(symbol);
759  return *this;
760 }

◆ addSymbol() [2/2]

nfa::builder & reg::nfa::builder::addSymbol ( 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 763 of file nfa.cpp.

763  {
764  return addSymbol(converter.from_bytes(utf8Symbol)[0]);
765 }
std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: dfa.cpp:1088
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective NFA's alphabet.
Definition: nfa.cpp:757

◆ addTransition() [1/2]

nfa::builder & reg::nfa::builder::addTransition ( std::string const &  from,
std::string const &  to,
char32_t  symbol 
)

Adds a transition for the prospective NFA.

Parameters
fromthe starting state for the transition
tothe destination state for the transition
symbolthe symbol triggering the transition or \0 for an ε-transition
Returns
reference to this object, for chaining operations

Definition at line 804 of file nfa.cpp.

804  {
805  if (p->transitions.empty()) {
806  p->initial = from;
807  }
808  p->transitions[to];
809  p->transitions[from][symbol].insert(to);
810  addSymbol(symbol);
811  return *this;
812 }
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective NFA's alphabet.
Definition: nfa.cpp:757

◆ addTransition() [2/2]

nfa::builder & reg::nfa::builder::addTransition ( 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 815 of file nfa.cpp.

815  {
816  return addTransition(from, to, converter.from_bytes(utf8Symbol)[0]);
817 }
std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
Definition: dfa.cpp:1088
builder & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
Definition: nfa.cpp:804

◆ build()

nfa reg::nfa::builder::build ( )

Builds the NFA, as defined by previous operations.

Returns
an NFA object with exactly the states, alphabet and transitions that were defined

Definition at line 999 of file nfa.cpp.

999  {
1000  p->transitions[p->initial];
1001  p->alphabet.insert(U'\0');
1002  vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
1003  std::sort(alphabetV.begin(), alphabetV.end());
1004  vector<string> labelV(p->transitions.size());
1005  labelV[0] = p->initial;
1006  valarray<bool> acceptingV(p->transitions.size());
1007  acceptingV[0] = (p->acceptingStates.find(p->initial) != p->acceptingStates.end());
1008  size_t i(1);
1009  for (auto entry : p->transitions) {
1010  if (entry.first == p->initial) {
1011  continue;
1012  }
1013  labelV[i] = entry.first;
1014  acceptingV[i++] = (
1015  p->acceptingStates.find(entry.first) != p->acceptingStates.end()
1016  );
1017  }
1018  vector<vector<valarray<bool>>> transitionV(
1019  p->transitions.size(),
1021  p->alphabet.size()+1,
1022  valarray<bool>(labelV.size())
1023  )
1024  );
1025  unordered_set<string> emptySet;
1026  size_t qi(0);
1027  for (auto const& q : labelV) {
1028  unordered_map<char32_t,unordered_set<string>> const& fromQ = p->transitions[q];
1029  size_t si(0);
1030  for (char32_t symbol : alphabetV) {
1031  auto to = fromQ.find(symbol);
1032  unordered_set<string> const& viaSymbol(to != fromQ.end() ? to->second : emptySet);
1033  i = 0;
1034  for (auto const& p : labelV) {
1035  transitionV[qi][si][i++] = (viaSymbol.count(p) != 0);
1036  }
1037  si++;
1038  }
1039  qi++;
1040  }
1041  return {alphabetV, transitionV, labelV, acceptingV};
1042 }

◆ intersect()

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

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

Concatenates the names of states defined so far with the other NFA'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 922 of file nfa.cpp.

922  {
923  if (!p->transitions.empty()) {
924  vector<string> stateNames;
925  stateNames.reserve(p->transitions.size());
926  stateNames.push_back(p->initial);
927  for (auto const& fromTo : p->transitions) {
928  if (fromTo.first != p->initial) {
929  stateNames.push_back(fromTo.first);
930  }
931  }
932  auto const& oAlph = other.getAlphabet();
933  size_t commonSymbols = 0;
934  for (char32_t symbol : p->alphabet) {
935  if (index_of(oAlph, symbol) < oAlph.size()) {
936  commonSymbols++;
937  } else {
938  for (auto & fromVia : p->transitions) {
939  fromVia.second.erase(symbol);
940  }
941  }
942  }
943  p->alphabet.insert(oAlph.begin(), oAlph.end());
944  Ntransitionmap newTr(stateNames.size() * other.getNumberOfStates());
945  unordered_set<string> newAcc(stateNames.size() * other.getNumberOfStates());
946  unordered_map<size_t, unordered_map<size_t, string const*>> pairToName(stateNames.size() * other.getNumberOfStates());
947  for (size_t q = 0; q < stateNames.size(); q++) {
948  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
949  string potentialName = stateNames[q] + other.getLabelOf(qq);
950  for (auto nameIt = newTr.find(potentialName); nameIt != newTr.end(); nameIt = newTr.find(potentialName)) {
951  potentialName.append("_");
952  }
953  auto nameIt = newTr.emplace(potentialName, commonSymbols);
954  pairToName.emplace(q, 1).first->second.emplace(qq, &(nameIt.first->first));
955  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end() && other.isAccepting(qq)) {
956  newAcc.insert(potentialName);
957  }
958  }
959  p->transitions[stateNames[q]][U'\0'].insert(stateNames[q]);
960  // Needed due to the equivalence of standing still to “taking” an ε-transition.
961  }
962  for (size_t q = 0; q < stateNames.size(); q++) {
963  auto const& qLabel = stateNames[q];
964  auto const& viaTos = p->transitions[qLabel];
965  for (auto const& viaTo : viaTos) {
966  for (size_t qq = 0; qq < other.getNumberOfStates(); qq++) {
967  valarray<bool> const& reached = other.delta(qq, viaTo.first);
968  for (auto const& to : viaTo.second) {
969  size_t p = index_of(stateNames, to);
970  for (size_t pp = 0; pp < reached.size(); pp++) {
971  if (reached[pp] || (pp == qq && viaTo.first == U'\0')) {
972  // Needed due to the equivalence of standing still to “taking” an ε-transition.
973  newTr[*(pairToName[q][qq])][viaTo.first].insert(*(pairToName[p][pp]));
974  }
975  }
976  }
977  }
978  }
979  }
980  for (auto & fromVia : newTr) {
981  auto const& from = fromVia.first;
982  auto to = fromVia.second.find(U'\0');
983  to->second.erase(from);
984  if (to->second.empty()) {
985  fromVia.second.erase(to);
986  }
987  }
988  p->transitions = newTr;
989  p->acceptingStates = newAcc;
990  p->initial = *(pairToName[0][0]);
991  }
992  return *this;
993 }
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:1080
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:654

◆ makeInitial()

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

Resets the initial state for the prospective NFA.

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

Definition at line 791 of file nfa.cpp.

791  {
792  p->initial = state;
793  p->transitions[state];
794  return *this;
795 }

◆ normalizeStateNames()

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

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

Definition at line 820 of file nfa.cpp.

820  {
821  if (!p->transitions.empty()) {
822  vector<string> stateNames;
823  stateNames.reserve(p->transitions.size());
824  stateNames.push_back(p->initial);
825  for (auto const& fromTo : p->transitions) {
826  if (fromTo.first != p->initial) {
827  stateNames.push_back(fromTo.first);
828  }
829  }
830  Ntransitionmap newTr(p->transitions.size());
831  unordered_set<string> newAcc(p->acceptingStates.size());
832  for (size_t q = 0; q < stateNames.size(); q++) {
833  auto const& vias = p->transitions[stateNames[q]];
834  unordered_map<char32_t,unordered_set<string>> newVias(vias.size());
835  for (auto const& viaTo : vias) {
836  unordered_set<string> newTos(viaTo.second.size());
837  for (size_t p = 0; p < stateNames.size(); p++) {
838  if (viaTo.second.find(stateNames[p]) != viaTo.second.cend()) {
839  newTos.insert(string(prefix).append(std::to_string(p)));
840  }
841  }
842  newVias.insert(make_pair(viaTo.first, newTos));
843  }
844  newTr.insert(make_pair(string(prefix).append(std::to_string(q)), newVias));
845  if (p->acceptingStates.find(stateNames[q]) != p->acceptingStates.end()) {
846  newAcc.insert(string(prefix).append(std::to_string(q)));
847  }
848  }
849  p->initial = string(string(prefix).append("0"));
850  p->transitions = newTr;
851  p->acceptingStates = newAcc;
852  }
853  return *this;
854 }
T make_pair(T... args)
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:654

◆ operator=() [1/2]

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

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

Definition at line 735 of file nfa.cpp.

735  {
736  if (this != &b) {
737  p.reset(new pImpl(*(b.p)));
738  }
739  return *this;
740 }

◆ operator=() [2/2]

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

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

The other builder will be blank afterwards.

Definition at line 744 of file nfa.cpp.

744  {
745  if (this != &b) {
746  p.reset(new pImpl);
747  p.swap(b.p);
748  }
749  return *this;
750 }

◆ setAccepting()

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

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

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 773 of file nfa.cpp.

773  {
774  if (p->transitions.empty()) {
775  p->initial = state;
776  }
777  p->transitions[state];
778  if (accept) {
779  p->acceptingStates.insert(state);
780  } else {
781  p->acceptingStates.erase(state);
782  }
783  return *this;
784 }

◆ unite()

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

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

Prepends the names of states defined so far with a single 1 and the other NFA's state names with a single 2 and adds a new initial state with an ε transition to each of the other initial states.

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

Definition at line 864 of file nfa.cpp.

864  {
865  string newInitial("q0");
866  if (!p->transitions.empty()) {
867  Ntransitionmap tempTr(p->transitions.size());
868  for (auto const& fromVia : p->transitions) {
869  unordered_map<char32_t,unordered_set<string>> tempVia(fromVia.second.size());
870  for (auto const& viaTo : fromVia.second) {
871  unordered_set<string> tempTo(viaTo.second.size());
872  for (auto const& to : viaTo.second) {
873  tempTo.insert(string(to.length() + 1, '1').replace(1, string::npos, to));
874  }
875  tempVia.insert(make_pair(viaTo.first, tempTo));
876  }
877  tempTr.insert(make_pair(string(fromVia.first.length() + 1, '1').replace(1, string::npos, fromVia.first), tempVia));
878  }
879  p->transitions = tempTr;
880  unordered_set<string> tempAcc(p->acceptingStates.size());
881  for (auto const& acc : p->acceptingStates) {
882  tempAcc.insert(string(acc.length() + 1, '1').replace(1, string::npos, acc));
883  }
884  p->acceptingStates = tempAcc;
885  p->initial = string(p->initial.length() + 1, '1').replace(1, string::npos, p->initial);
886  addTransition(newInitial, p->initial, U'\0');
887  }
888  makeInitial(newInitial);
889  auto & oAlphabet = other.getAlphabet();
890  p->alphabet.insert(oAlphabet.cbegin(), oAlphabet.cend());
891  for (size_t q = 0; q < other.getNumberOfStates(); q++) {
892  auto & qLabel = other.getLabelOf(q);
893  string newQLabel = string(qLabel.length() + 1, '2').replace(1, string::npos, qLabel);
894  unordered_map<char32_t,unordered_set<string>> tempVia(oAlphabet.size() + 1);
895  for (char32_t symbol : oAlphabet) {
896  valarray<bool> const& to = other.delta(q, symbol);
897  unordered_set<string> tempTo(other.getNumberOfStates());
898  for (size_t p = 0; p < other.getNumberOfStates(); p++) { if (to[p]) {
899  auto & pLabel = other.getLabelOf(p);
900  tempTo.insert(string(pLabel.length() + 1, '2').replace(1, string::npos, pLabel));
901  }}
902  tempVia.insert(make_pair(symbol, tempTo));
903  }
904  p->transitions.insert(make_pair(newQLabel, tempVia));
905  if (other.isAccepting(q)) {
906  p->acceptingStates.insert(newQLabel);
907  }
908  if (q == 0) {
909  addTransition(newInitial, newQLabel, U'\0');
910  }
911  }
912  return *this;
913 }
T replace(T... args)
T make_pair(T... args)
builder & makeInitial(std::string const &state)
Resets the initial state for the prospective NFA.
Definition: nfa.cpp:791
unordered_map< string, unordered_map< char32_t, unordered_set< string > >> Ntransitionmap
Shorthand for the map from state name and transition symbol to set of target states.
Definition: nfa.cpp:654
builder & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
Definition: nfa.cpp:804

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