12 #include <unordered_set> 13 using std::unordered_set;
15 #include <unordered_map> 16 using std::unordered_map;
52 vector<string>&
labels, valarray<bool>& acceptingStates) :
58 for (char32_t symbol : this->alphabet) {
59 if (symbol == U
'\0') {
85 nfa::nfa(vector<char32_t>& alphabet, vector<vector<valarray<bool>>>& transitions,
86 vector<string>& labels, valarray<bool>& acceptingStates) :
87 p(new pImpl(alphabet, transitions, labels, acceptingStates)) {}
91 return p->getEquivalentDfa(
this) == n.p->getEquivalentDfa(&n);
96 return p->getEquivalentDfa(
this) != n.p->getEquivalentDfa(&n);
106 valarray<bool>
const&
nfa::delta(
size_t q, char32_t symbol)
const {
109 find(p->alphabet.begin(), p->alphabet.end(), symbol)
111 if (i >= p->alphabet.size()) {
113 throw std::domain_error(
114 string(u8
"δ is not defined for symbol ").append(1, symbol)
118 if (q >= p->labels.size()) {
120 throw std::out_of_range(
121 string(
"There is no state with index ").append(std::to_string(q))
125 return p->transitions[q][i];
129 valarray<bool>
const&
nfa::delta(
size_t q,
string const& utf8Symbol)
const {
141 valarray<bool> qs(p->labels.size());
158 valarray<bool>
nfa::deltaHat(valarray<bool>
const& qs, std::u32string
const& word)
const {
160 for (char32_t symbol : word) {
161 valarray<bool> reached(p->labels.size());
175 valarray<bool>
nfa::deltaHat(valarray<bool>
const& qs,
string const& utf8Word)
const {
186 if (p->epsClosures[q].size() == 0) {
187 p->epsClosures[q].resize(p->labels.size());
188 p->epsClosures[q][q] =
true;
192 valarray<bool> old(p->epsClosures[q]);
194 for (
bool qb : old) {
197 for (
bool pb : p->transitions[qi][0]) {
199 if (!p->epsClosures[q][pi]) {
201 p->epsClosures[q][pi] =
true;
211 return p->epsClosures[q];
221 valarray<bool> closure(p->labels.size());
251 label = label.append(1, label.length() == 0 ?
'{' :
',');
252 label = label.append(p->labels[qi]);
256 if (label.length() == 0) {
259 return label.append(1,
'}');
278 return p->utf8Alphabet;
287 return p->labels.size();
297 return p->accepting[q];
310 p.reset(
new pImpl(*(n.p)));
325 nfa::~nfa() =
default;
332 unordered_map<string,unordered_map<char32_t,unordered_set<string>>>
transitions;
344 unordered_map<
string,unordered_map<char32_t,unordered_set<string>>>&
transitions 361 for (
size_t qi = 0; qi <
nfa.p->labels.size(); ++qi) {
363 for (char32_t symbol : p->alphabet) {
364 valarray<bool> ps =
nfa.
delta(qi, symbol);
383 unordered_set<string> acceptingStates;
385 unordered_map<string,unordered_map<char32_t,unordered_set<string>>> transitions;
387 for (char32_t symbol : alphabet) {
391 p = unique_ptr<pImpl>(
new pImpl(initial, acceptingStates, alphabet, transitions));
404 p.reset(
new pImpl(*(b.p)));
426 p->alphabet.insert(symbol);
443 if (p->transitions.empty()) {
446 p->transitions[state];
448 p->acceptingStates.insert(state);
450 p->acceptingStates.erase(state);
463 p->transitions[state];
476 if (p->transitions.empty()) {
480 p->transitions[from][symbol].insert(to);
496 p->alphabet.insert(U
'\0');
497 vector<char32_t> alphabetV(p->alphabet.begin(), p->alphabet.end());
498 sort(alphabetV.begin(), alphabetV.end());
499 vector<string> labelV(p->transitions.size());
500 labelV[0] = p->initial;
501 valarray<bool> acceptingV(p->transitions.size());
502 acceptingV[0] = (p->acceptingStates.find(p->initial) != p->acceptingStates.end());
504 for (
auto entry : p->transitions) {
505 if (entry.first == p->initial) {
508 labelV[i] = entry.first;
510 p->acceptingStates.find(entry.first) != p->acceptingStates.end()
513 vector<vector<valarray<bool>>> transitionV(
514 p->transitions.size(),
515 vector<valarray<bool>>(
516 p->alphabet.size()+1,
517 valarray<bool>(labelV.size())
520 unordered_set<string> emptySet;
522 for (
auto const& q : labelV) {
523 unordered_map<char32_t,unordered_set<string>>
const& fromQ = p->transitions[q];
525 for (char32_t symbol : alphabetV) {
526 auto to = fromQ.find(symbol);
527 unordered_set<string>
const& viaSymbol(to != fromQ.end() ? to->second : emptySet);
529 for (
auto const& p : labelV) {
530 transitionV[qi][si][i++] = (viaSymbol.count(p) != 0);
536 return {alphabetV, transitionV, labelV, acceptingV};
539 nfa::builder::~builder() =
default;
static std::unique_ptr< std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > > const converter
Converts between UTF-8-encoded and UTF-32-encoded strings.
nfa build()
Builds the NFA, as defined by previous operations.
size_t delta(size_t q, char32_t symbol) const
Computes this DFA's transition function for a state and a symbol.
dfa()
Constructs a DFA accepting the empty language ∅.
Represents nondeterministic finite automata with ε-moves.
std::vector< char32_t > const & getAlphabet() const
Fetches this NFA's set of processable symbols.
std::string const & getLabelOf(size_t q) const
Puts a name to an index.
Represents deterministic finite automata.
std::vector< std::string > const & getUtf8Alphabet() const
Fetches this NFA's set of processable symbols as UTF-8-encoded strings.
vector< vector< valarray< bool > > > transitions
Stores the transition function as a table viz state index × symbol index → list of bools with true a...
std::valarray< bool > deltaHat(size_t q, std::u32string const &word) const
Computes this NFA's transition function recursively for a string of symbols, starting in a specified ...
Constructs NFAs step by step.
bool operator==(nfa const &n) const
Tests whether this NFA accepts exactly the same language as another one.
pImpl()
Constructs private implementation object for an NFA accepting the empty language ∅.
vector< string > labels
Stores the names of states.
bool isAccepting(size_t q) const
Tests whether a state is an accept state within this NFA.
builder & purge()
Purges the prospective DFA of unreachable and non-producing states, allowing for minimization.
nfa & operator=(nfa const &n)
Copy-assigns this NFA by copying another one's private implementation object.
std::vector< char32_t > const & getAlphabet() const
Fetches this DFA's set of processable symbols.
string initial
Name of the prospective NFA's initial state.
pImpl(string &initial, unordered_set< string > &acceptingStates, unordered_set< char32_t > &alphabet, unordered_map< string, unordered_map< char32_t, unordered_set< string >>> &transitions)
Constructs private implementation object with provided members.
bool operator!=(nfa const &n) const
Tests whether this NFA doesn't accept the same language as another one.
builder & addSymbol(char32_t symbol)
Adds a symbol to the prospective NFA's alphabet.
builder & setAccepting(std::string const &state, bool accept)
Sets whether or not a state will be accepting within the prospective NFA.
Contains the reg::nfa class definition.
valarray< bool > accepting
A true value marks an index as belonging to an accept state.
Contains the reg::expression class defintion.
vector< char32_t > alphabet
Represents the set of processable symbols.
Private implementation details of NFAs.
builder & merge()
Merges the prospective DFA's indistinguishable states, allowing for minimization. ...
unordered_set< char32_t > alphabet
Set of symbols processable by the prospective NFA.
Constructs DFAs step by step.
vector< valarray< bool > > epsClosures
Cache for every state's ε-closures.
size_t getNumberOfStates() const
Counts this DFA's states.
builder & makeInitial(std::string const &state)
Resets the initial state for the prospective NFA.
vector< string > utf8Alphabet
Represents the set of processable symbols as UTF-8-encoded strings.
Private implementation details of NFA builders.
size_t getNumberOfStates() const
Counts this NFA's states.
pImpl(vector< char32_t > &alphabet, vector< vector< valarray< bool >>> &transitions, vector< string > &labels, valarray< bool > &acceptingStates)
Constructs private implementation object with provided members and empty ε-closure cache...
dfa const & getEquivalentDfa(nfa const *owner)
Returns the equivalent DFA safely, constructing it if it wasn't already.
nfa()
Constructs an NFA accepting the empty language ∅.
builder & operator=(builder const &b)
Copy-assigns a builder by copying another one's private implementation object.
unordered_set< string > acceptingStates
Set of names of the prospective NFA's accept states.
builder & addTransition(std::string const &from, std::string const &to, char32_t symbol)
Adds a transition for the prospective NFA.
std::string const & getLabelOf(size_t q) const
Puts a name to an index.
std::valarray< bool > const & delta(size_t q, char32_t symbol) const
Computes this NFA's transition function for a state and a symbol.
unordered_map< string, unordered_map< char32_t, unordered_set< string > > > transitions
Transition function (state × symbol → set of states) of the prospective NFA.
pImpl()=default
Constructs empty private implementation object.
std::valarray< bool > const & epsilonClosure(size_t q) const
Computes a state's ε-closure.
Contains the reg::dfa class definition.
shared_ptr< dfa const > equivalent
Stores a minimal DFA accepting the same language as this object's NFA.
builder()
Constructs a blank builder object.