bux API Reference 1.11.0
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
Loading...
Searching...
No Matches
FA.h
Go to the documentation of this file.
1#pragma once
2
3// FA stands for Finite Automoton
4
5#include "XException.h" // RUNTIME_ERROR()
6#include <algorithm> // std::set_difference()
7#include <concepts> // std::convertible_to<>, std::invocable<>
8#include <iterator> // std::inserter()
9#include <list> // std::list<>
10#include <map> // std::map<>
11#include <set> // std::set<>
12#include <vector> // std::vector<>
13
14namespace bux {
15
16//
17// Types
18//
22{
23public:
24
25 // Nonvirtuals
26 C_NfaState();
27 C_NfaState(const C_NfaState &a) = default;
28 C_NfaState &operator=(const C_NfaState &a) = default;
29 auto operator<=>(const C_NfaState &a) const { return id <=> a.id; }
30 bool operator==(const C_NfaState &a) const { return id == a.id; }
31
32private:
33
34 // Data
35 unsigned id;
36 static unsigned nextId;
37};
38
39enum
40{
43};
44
45template<class T_Inputs>
47{
48 // Class Methods
49 static bool equalInput(const T_Inputs &a, const T_Inputs &b);
50 static void inputDifference(T_Inputs &dst, const T_Inputs &src);
51 static void inputIntersection(T_Inputs &dst, const T_Inputs &src);
52 static void inputUnion(T_Inputs &dst, const T_Inputs &src);
53 static bool isEmptyInput(const T_Inputs &src);
54};
55
56template<class T_Inputs, class T_Action, class C_Traits> class C_DFA;
57
58template<class T_Inputs, class T_Action, class C_Traits = C_FA_Traits<T_Inputs>>
59class C_NFA
66{
67public:
68
69 // Nonvirtuals
70 C_NFA() = default;
71 C_NFA(const C_NFA &a);
73 C_NFA(const T_Inputs &inputs);
74 void operator=(const C_NFA &a);
75 void operator=(C_NFA &&a);
76 void operator|=(const C_NFA &a);
77 void operator+=(const C_NFA &a) { (void)append(a); }
78 void operator+=(const T_Inputs &inputs) { (void)append(inputs); }
79 C_NFA &append(const C_NFA &a);
80 C_NFA &append(const T_Inputs &inputs);
81 C_NFA &changeTo(int options);
82 template<class T> void setAction(T &&action);
83 size_t totalFinalStates() const { return F.size(); }
84
85private:
86
87 // Types
88 struct C_FinalState: C_NfaState
89 {
90 // Data
91 T_Action m_Tag;
92
93 // Nonvirtuals
94 C_FinalState() = default;
95 C_FinalState(const C_NfaState &a, const T_Action &tag): C_NfaState(a), m_Tag(tag) {}
96 };
97 typedef std::vector<C_FinalState> C_FinalStates;
98
99 struct C_NfaInputSet
100 {
101 // Data
102 T_Inputs m_UserInputs;
103 bool m_Epsilon;
104
105 // Ctor
106 C_NfaInputSet(bool epsilon = false): m_Epsilon(epsilon) {}
107 };
108 typedef std::map<C_NfaState,C_NfaInputSet> C_Transitions;
109 typedef std::map<C_NfaState,C_Transitions> C_TransitionMap;
110
111 // Data
112 C_NfaState q0; // starting point index of Q
113 C_FinalStates F; // final states of Q
114 C_TransitionMap delta; // transition relation
115
116 // Nonvirtuals
117 void gatherStates(std::set<C_NfaState> &usedStates) const;
118 const C_NFA &checkReuse(const std::set<C_NfaState> &usedStates, C_NFA &replacement) const;
119
120 friend class C_DFA<T_Inputs,T_Action,C_Traits>;
121};
122
123template<class T_Inputs, class T_Action, class C_Traits = C_FA_Traits<T_Inputs>>
124class C_DFA
131{
132public:
133
134 // Types
135 typedef std::set<T_Action> C_Conflict;
136
137 // Nonvirtuals
138 template<class F_PickAction>
139 C_DFA(const C_NFA<T_Inputs,T_Action,C_Traits> &nfa, F_PickAction pickAction) requires
140 requires (int tag, const C_Conflict &conflict) {
141 { pickAction(tag, conflict) }->std::convertible_to<T_Action>;
142 }
143 {
144 C_FinalMap Fraw;
145 C_TransitionMap deltaRaw;
146 auto n = nfa2dfa(nfa, Fraw, deltaRaw, pickAction);
147 minDfa(Fraw, deltaRaw, n, F, delta);
148 }
149 template<class F_Get>
150 void eachFinalState(F_Get get) const requires std::invocable<F_Get,int,const T_Action&>
151 {
152 for (const auto &i: F)
153 get(i.first, i.second);
154 }
155 template<class F_Get>
156 void eachTransition(F_Get get) const requires std::invocable<F_Get,int,const T_Inputs&,int>
157 {
158 for (const auto &i: delta)
159 for (const auto &j: i.second)
160 get(i.first, j.second, j.first);
161 }
162 bool isFinal(int state, T_Action &action) const;
163 // Return true and assign action if state is final; return false otherwise
164 static int startingState() { return 0; }
165 size_t totalFinalStates() const { return F.size(); }
166
167private:
168
169 // Types
170 typedef std::set<C_NfaState> C_NfaClosure;
171
172 struct C_TaggedNfaClosure
173 {
174 C_NfaClosure m_Closure;
175 int m_Tag;
176
177 C_TaggedNfaClosure(const C_NfaClosure &closure):
178 m_Closure(closure), m_Tag(0)
179 {}
180 };
181
182 typedef typename C_NFA<T_Inputs,T_Action,C_Traits>::C_TransitionMap C_SourceDelta;
183 typedef std::map<int,T_Action> C_FinalMap;
184 typedef std::map<int,T_Inputs> C_State2Inputs;
185 typedef std::map<int,C_State2Inputs> C_TransitionMap;
186
187 typedef std::set<int> C_DfaClosure;
188 struct C_TaggedDfaClosure
189 {
190 C_DfaClosure m_Closure;
191 int m_Tag;
192
193 C_TaggedDfaClosure()
194 {}
195 C_TaggedDfaClosure(const C_DfaClosure& closure): m_Closure(closure)
196 {}
197 };
198 typedef std::list<C_TaggedDfaClosure> C_DfaClosures;
199 typedef std::map<T_Action,C_DfaClosure> C_Action2Closure;
200
201 //Data
202 C_FinalMap F;
203 C_TransitionMap delta;
204
205 // Nonvirtuals
206 static void buildA2C(const C_FinalMap &Ffat, const C_DfaClosure &closure,
207 C_Action2Closure &a2c);
208 static void createClosure(C_NfaClosure &c, const C_SourceDelta &delta);
209 static typename C_DfaClosures::const_iterator findDfaClosure(const C_DfaClosures &Q, int state);
210 static void minDfa(const C_FinalMap &Ffat, const C_TransitionMap &deltaFat,
211 int totalFatStates, C_FinalMap &Fmin, C_TransitionMap &deltaMin);
212 template<class F_PickAction>
213 static int nfa2dfa(const C_NFA<T_Inputs,T_Action,C_Traits> &nfa, C_FinalMap &F,
214 C_TransitionMap &delta, F_PickAction pickAction);
215 // Return total of the resulting DFA states
216};
217
218//
219// Class Template Implementations
220//
221template<class T_Inputs, class T_Action, class C_Traits>
223 q0(a.q0), F(a.F), delta(a.delta)
224{
225}
226
227template<class T_Inputs, class T_Action, class C_Traits>
229{
230 F.swap(a.F);
231 delta.swap(a.delta);
232}
233
234template<class T_Inputs, class T_Action, class C_Traits>
236{
237 C_FinalState f;
238 delta[q0][f].m_UserInputs = inputs;
239 F.emplace_back(f);
240}
241
242template<class T_Inputs, class T_Action, class C_Traits>
244{
245 q0 = a.q0;
246 F = a.F;
247 delta = a.delta;
248}
249
250template<class T_Inputs, class T_Action, class C_Traits>
252{
253 q0 = a.q0;
254 F.swap(a.F);
255 delta.swap(a.delta);
256}
257
258template<class T_Inputs, class T_Action, class C_Traits>
260{
261 if (F.empty())
262 *this = _a;
263 else
264 {
265 std::set<C_NfaState> usedStates;
266 gatherStates(usedStates);
267 C_NFA _;
268 const C_NFA &a = _a.checkReuse(usedStates, _);
269 F.insert(F.end(), a.F.begin(), a.F.end());
270 delta.insert(a.delta.begin(), a.delta.end());
271 delta[q0][a.q0].m_Epsilon =true;
272 }
273}
274
275template<class T_Inputs, class T_Action, class C_Traits>
277{
278 if (F.empty())
279 *this = _a;
280 else
281 {
282 std::set<C_NfaState> usedStates;
283 gatherStates(usedStates);
284 C_NFA _;
285 const C_NFA &a = _a.checkReuse(usedStates, _);
286 delta.insert(a.delta.begin(), a.delta.end());
287 for (const auto &i: F)
288 delta[i][a.q0].m_Epsilon = true;
289 F = a.F;
290 }
291 return *this;
292}
293
294template<class T_Inputs, class T_Action, class C_Traits>
296{
297 C_FinalState f;
298 if (F.empty())
299 delta[q0][f].m_UserInputs = inputs;
300 else
301 {
302 for (const auto &i: F)
303 delta[i][f].m_UserInputs = inputs;
304
305 F.clear();
306 }
307 F.push_back(f);
308 return *this;
309}
310
311template<class T_Inputs, class T_Action, class C_Traits>
313{
314 for (const auto &i: F)
315 {
316 if (FA_REPEATABLE &options)
317 delta[i][q0].m_Epsilon = true;
318 if (FA_OPTIONAL &options)
319 delta[q0][i].m_Epsilon = true;
320 }
321 return *this;
322}
323
324template<class T_Inputs, class T_Action, class C_Traits>
325const C_NFA<T_Inputs,T_Action,C_Traits> &C_NFA<T_Inputs,T_Action,C_Traits>::checkReuse(
326 const std::set<C_NfaState> &usedStates,
327 C_NFA<T_Inputs,T_Action,C_Traits> &replacement ) const
328{
329 typedef std::map<C_NfaState,C_NfaState> C_Map;
330 C_Map map;
331 for (const auto &i: delta)
332 {
333 if (usedStates.find(i.first) != usedStates.end())
334 map[i.first];
335
336 for (const auto &j: i.second)
337 if (usedStates.find(j.first) != usedStates.end())
338 map[j.first];
339 }
340 if (map.empty())
341 // No conflict
342 return *this;
343
344 C_Map::const_iterator found = map.find(q0);
345 replacement.q0 = found != map.end()? found->second: q0;
346
347 for (const auto &i: F)
348 {
349 found = map.find(i);
350 replacement.F.emplace_back(found != map.end()? found->second: i, i.m_Tag);
351 }
352
353 for (const auto &i: delta)
354 {
355 found = map.find(i.first);
356 auto &t =replacement.delta[found != map.end()? found->second: i.first];
357 for (const auto &j: i.second)
358 {
359 found = map.find(j.first);
360 t[found != map.end()? found->second: j.first] =j.second;
361 }
362 }
363 return replacement;
364}
365
366template<class T_Inputs, class T_Action, class C_Traits>
367void C_NFA<T_Inputs,T_Action,C_Traits>::gatherStates(std::set<C_NfaState> &usedStates) const
368{
369 for (const auto &i: delta)
370 {
371 usedStates.insert(i.first);
372 for (const auto &j: i.second)
373 usedStates.insert(j.first);
374 }
375}
376
377template<class T_Inputs, class T_Action, class C_Traits>
378template<class T>
380{
381 for (auto &i: F)
382 i.m_Tag = std::forward<T>(action);
383}
384
385template<class T_Inputs, class T_Action, class C_Traits>
386void C_DFA<T_Inputs,T_Action,C_Traits>::buildA2C(
387 const C_FinalMap &Ffat,
388 const C_DfaClosure &closure,
389 C_Action2Closure &a2c )
390{
391 for (const auto &i: Ffat)
392 {
393 if (closure.find(i.first) != closure.end())
394 a2c[i.second].insert(i.first);
395 }
396}
397
398template<class T_Inputs, class T_Action, class C_Traits>
399void C_DFA<T_Inputs,T_Action,C_Traits>::createClosure(C_NfaClosure &c, const C_SourceDelta &delta)
400{
401 C_NfaClosure test(c);
402 while (true)
403 {
404 C_NfaClosure add;
405 for (const auto &i: test)
406 {
407 const auto found = delta.find(i);
408 if (found != delta.end())
409 {
410 for (const auto &j: found->second)
411 if (j.second.m_Epsilon && c.find(j.first) == c.end())
412 add.insert(j.first);
413 }
414 }
415 if (add.empty())
416 break;
417
418 c.insert(add.begin(), add.end());
419 test.swap(add);
420 }
421}
422
423template<class T_Inputs, class T_Action, class C_Traits>
424auto C_DFA<T_Inputs,T_Action,C_Traits>::findDfaClosure(const C_DfaClosures &Q, int state) -> typename C_DfaClosures::const_iterator
425{
426 for (auto i = Q.begin(), end = Q.end(); i != end; ++i)
427 {
428 if (i->m_Closure.find(state) != i->m_Closure.end())
429 // Found
430 return i;
431 }
432 RUNTIME_ERROR("State {} not found", state);
433}
434
435template<class T_Inputs, class T_Action, class C_Traits>
436bool C_DFA<T_Inputs,T_Action,C_Traits>::isFinal(int state, T_Action &action) const
437{
438 const auto i =F.find(state);
439 if (i != F.end())
440 {
441 action = i->second;
442 return true;
443 }
444 return false;
445}
446
447template<class T_Inputs, class T_Action, class C_Traits>
448void C_DFA<T_Inputs,T_Action,C_Traits>::minDfa(
449 const C_FinalMap &Ffat,
450 const C_TransitionMap &deltaFat,
451 int totalFatStates,
452 C_FinalMap &Fmin,
453 C_TransitionMap &deltaMin )
454{
455 // Figure 7.7: Algorithm MinDFA
456 C_DfaClosures Qfat;
457 Qfat.emplace_back();
458 Qfat.emplace_back();
459 auto &part0 = Qfat.front().m_Closure;
460 auto &part1 = Qfat.back().m_Closure;
461 int tag =0;
462 for (const auto &i: Ffat)
463 {
464 part0.insert(i.first);
465 while (tag < i.first)
466 part1.insert(tag++);
467
468 ++tag;
469 }
470 while (tag < totalFatStates)
471 part1.insert(tag++);
472
473 bool changed;
474 do
475 {
476 changed = false;
477 C_DfaClosures Qmin;
478 for (const auto &i: Qfat)
479 {
480 auto fat = i.m_Closure;
481 while (!fat.empty())
482 {
483 C_DfaClosure slim;
484 auto j = fat.begin();
485 slim.insert(*j);
486 typedef std::map<const C_DfaClosure*,T_Inputs> C_CmpMap;
487 C_CmpMap cmpmap;
488 auto k = deltaFat.find(*j);
489 if (k != deltaFat.end())
490 for (const auto &m: k->second)
491 cmpmap[&findDfaClosure(Qfat, m.first)->m_Closure] = m.second;
492
493 while (++j != fat.end())
494 {
495 C_CmpMap map;
496 bool deal = true;
497 k = deltaFat.find(*j);
498 if (k != deltaFat.end())
499 for (const auto &m: k->second)
500 {
501 const auto *t = &findDfaClosure(Qfat, m.first)->m_Closure;
502 auto found = cmpmap.find(t);
503 if (found != cmpmap.end() &&
504 C_Traits::equalInput(m.second, found->second))
505 {
506 map[t] = m.second;
507 continue;
508 }
509 deal = false;
510 break;
511 }
512 if (deal)
513 {
514 auto i_map = map.begin();
515 for (auto &j_cmp: cmpmap)
516 {
517 if (i_map == map.end() ||
518 i_map->first != j_cmp.first ||
519 !C_Traits::equalInput(i_map->second, j_cmp.second))
520 {
521 deal = false;
522 break;
523 }
524 ++i_map;
525 }
526 if (deal && i_map == map.end())
527 slim.insert(*j);
528 }
529 }
530 Qmin.emplace_back(slim);
531 C_DfaClosure temp;
532 std::set_difference(fat.begin(), fat.end(),
533 slim.begin(), slim.end(), std::inserter(temp, temp.begin()));
534 fat.swap(temp);
535 }
536 }
537 if (Qmin.size() == Qfat.size())
538 {
539 for (auto i =Qmin.begin(), end =Qmin.end(); i != end; ++i)
540 {
541 C_Action2Closure a2c;
542 buildA2C(Ffat, i->m_Closure, a2c);
543 if (a2c.size() > 1)
544 {
545 // Solve conflict
546 auto j = a2c.begin();
547 i->m_Closure.swap(j->second); // overwrite the superset
548 auto next = i;
549 ++next;
550 while (++j != a2c.end())
551 i = Qmin.insert(next, j->second);
552 }
553 }
554 }
555 if (Qmin.size() != Qfat.size())
556 {
557 Qfat.swap(Qmin);
558 changed =true;
559 }
560 } while (changed);
561
562 // Tagging
563 tag =0;
564 for (auto i = Qfat.begin(), end = Qfat.end(); i != end; ++i, ++tag)
565 {
566 if (tag && i->m_Closure.find(0) != i->m_Closure.end())
567 // Q0 is always tagged 0
568 {
569 i->m_Tag = 0;
570 Qfat.front().m_Tag = tag;
571 auto t = Fmin.find(0);
572 if (t != Fmin.end())
573 {
574 const auto a = t->second;
575 Fmin.erase(t);
576 Fmin[tag] = a;
577 }
578 }
579 else
580 i->m_Tag = tag;
581
582 C_Action2Closure a2c;
583 buildA2C(Ffat, i->m_Closure, a2c);
584 if (!a2c.empty())
585 {
586 Fmin[i->m_Tag] = a2c.begin()->first;
587 if (a2c.size() > 1)
588 // Impossible
589 RUNTIME_ERROR("a2c.size() == ()", a2c.size());
590 }
591 }
592 for (const auto &i: deltaFat)
593 {
594 auto &dst_i = deltaMin[findDfaClosure(Qfat,i.first)->m_Tag];
595 for (const auto &j: i.second)
596 {
597 const auto value = findDfaClosure(Qfat,j.first)->m_Tag;
598 for (const auto &dst_j: dst_i)
599 {
600 if (C_Traits::equalInput(dst_j.second, j.second))
601 {
602 if (dst_j.first == value)
603 // Aleady added
604 goto PostInsertion;
605
606 RUNTIME_ERROR("Contradicted mapping");
607 }
608 }
609 C_Traits::inputUnion(dst_i[value], j.second);
610 PostInsertion:;
611 }
612 }
613}
614
615template<class T_Inputs, class T_Action, class C_Traits>
616template<class F_PickAction>
617int C_DFA<T_Inputs,T_Action,C_Traits>::nfa2dfa(const C_NFA<T_Inputs,T_Action,C_Traits> &nfa,
618 C_FinalMap &F, C_TransitionMap &delta, F_PickAction pickAction)
619{
620 // Figure 7.5 (p245): Algorithm NFA->DFA
621 std::list<C_TaggedNfaClosure> Q; // collector of all states
622 Q.emplace_back(C_NfaClosure{});
623 auto *const q0 = &Q.front().m_Closure; // starting point index of Q
624 q0->insert(nfa.q0);
625 createClosure(*q0, nfa.delta);
626
627 typedef std::pair<T_Inputs, const C_TaggedNfaClosure*> C_InputClosurePair;
628 typedef std::vector<C_InputClosurePair> C_Input2Closure;
629 std::map<const C_TaggedNfaClosure*, C_Input2Closure,
630 bool (*)(const C_TaggedNfaClosure*,const C_TaggedNfaClosure*)>
631 deltaNfa([](const C_TaggedNfaClosure *a, const C_TaggedNfaClosure *b)->bool {
632 return a->m_Closure < b->m_Closure;
633 }); // transition relation
634 bool changed;
635 do
636 {
637 changed =false;
638 for (auto &q: Q)
639 {
640 if (q.m_Tag)
641 continue;
642
643 typedef std::map<C_NfaClosure,T_Inputs> C_ShiftMap;
644 C_ShiftMap map;
645 q.m_Tag = true;
646 for (const auto &j: q.m_Closure)
647 {
648 auto found = nfa.delta.find(j);
649 if (found != nfa.delta.end())
650 for (const auto &k: found->second)
651 {
652 if (!C_Traits::isEmptyInput(k.second.m_UserInputs))
653 {
654 C_NfaClosure key;
655 key.insert(k.first);
656 C_Traits::inputUnion(map[key], k.second.m_UserInputs);
657 }
658 }
659 }
660 // Here map is already created with keys of state singletons and values without epsilon
661 C_ShiftMap partitionedMap;
662 MergeAgain:
663 switch (map.size())
664 {
665 case 1:
666 partitionedMap.insert(*map.begin());
667 break;
668 case 0:
669 break;
670 default: // > 1
671 for (auto i = map.begin(), end = map.end(); i != end; ++i)
672 for (auto j = i; ++j != end;)
673 {
674 // Emptyness of (i - j)
675 T_Inputs insetsect(i->second);
676 C_Traits::inputIntersection(insetsect, j->second);
677 if (C_Traits::isEmptyInput(insetsect))
678 continue;
679
680 if (map.begin() != i)
681 // Move away the disjointed part first
682 {
683 partitionedMap.insert(map.begin(), i);
684 map.erase(map.begin(), i);
685 }
686 C_NfaClosure key(i->first);
687 key.insert(j->first.begin(), j->first.end());
688
689 T_Inputs t(i->second);
690 C_Traits::inputDifference(t, insetsect);
691 if (C_Traits::isEmptyInput(t))
692 map.erase(i);
693 else
694 i->second = t;
695
696 t = j->second;
697 C_Traits::inputDifference(t, insetsect);
698 if (C_Traits::isEmptyInput(t))
699 map.erase(j);
700 else
701 j->second = t;
702
703 map[key] =insetsect;
704 goto MergeAgain;
705 }
706 partitionedMap.insert(map.begin(), map.end());
707 } // switch (map.size())
708 map.swap(partitionedMap);
709 /* Here map is with
710 * keys union of which equals to union of original keys
711 * and
712 * values which together partition the union of all original values except episilon.
713 */
714 for (const auto &j: map)
715 {
716 C_TaggedNfaClosure t(j.first);
717 createClosure(t.m_Closure, nfa.delta);
718 const C_TaggedNfaClosure *next;
719 for (const auto &k: Q)
720 if (t.m_Closure == k.m_Closure)
721 {
722 next = &k;
723 goto postAddClosure;
724 }
725 Q.emplace_back(t); // new state t
726 next = &Q.back();
727 postAddClosure:
728 deltaNfa[&q].emplace_back(j.second, next);
729 changed =true;
730 }
731 }
732 } while (changed);
733
734 int tag = 0;
735 for (auto &i: Q)
736 {
737 i.m_Tag = tag++;
738 C_Conflict conflict;
739 for (const auto &j: nfa.F)
740 {
741 if (i.m_Closure.find(j) != i.m_Closure.end())
742 conflict.insert(j.m_Tag);
743 }
744 if (!conflict.empty())
745 {
746 if (conflict.size() > 1)
747 // Solve conflict
748 {
749 auto action = pickAction(i.m_Tag, conflict);
750 if (action == T_Action())
751 RUNTIME_ERROR("Interrupted");
752
753 F[i.m_Tag] = action;
754 }
755 else
756 F[i.m_Tag] = *conflict.begin();
757 }
758 }
759
760 for (const auto &i: deltaNfa)
761 {
762 auto &dstMap = delta[i.first->m_Tag];
763 for (const auto &j: i.second)
764 C_Traits::inputUnion(dstMap[j.second->m_Tag], j.first);
765 }
766 return tag;
767}
768
769} // namespace bux
#define RUNTIME_ERROR(fmtStr,...)
Wrap FILE(DATE)#__LINE__ FUNCTION: msg into std::runtime_error.
Definition XException.h:32
static int startingState()
Definition FA.h:164
void eachFinalState(F_Get get) const
Definition FA.h:150
std::set< T_Action > C_Conflict
Definition FA.h:135
size_t totalFinalStates() const
Definition FA.h:165
C_DFA(const C_NFA< T_Inputs, T_Action, C_Traits > &nfa, F_PickAction pickAction)
Definition FA.h:139
bool isFinal(int state, T_Action &action) const
Definition FA.h:436
void eachTransition(F_Get get) const
Definition FA.h:156
void operator|=(const C_NFA &a)
Definition FA.h:259
void operator=(C_NFA &&a)
Definition FA.h:251
C_NFA & append(const C_NFA &a)
Definition FA.h:276
void operator+=(const T_Inputs &inputs)
Definition FA.h:78
void operator+=(const C_NFA &a)
Definition FA.h:77
C_NFA(const C_NFA &a)
Definition FA.h:222
C_NFA & changeTo(int options)
Definition FA.h:312
C_NFA(C_NFA &&a)
Definition FA.h:228
size_t totalFinalStates() const
Definition FA.h:83
void setAction(T &&action)
Definition FA.h:379
C_NFA()=default
C_NFA(const T_Inputs &inputs)
Definition FA.h:235
void operator=(const C_NFA &a)
Definition FA.h:243
C_NFA & append(const T_Inputs &inputs)
Definition FA.h:295
C_NfaState(const C_NfaState &a)=default
bool operator==(const C_NfaState &a) const
Definition FA.h:30
auto operator<=>(const C_NfaState &a) const
Definition FA.h:29
C_NfaState & operator=(const C_NfaState &a)=default
THE common namespace of bux library.
Definition AtomiX.cpp:3
@ FA_OPTIONAL
Definition FA.h:41
@ FA_REPEATABLE
Definition FA.h:42
static void inputUnion(T_Inputs &dst, const T_Inputs &src)
static bool isEmptyInput(const T_Inputs &src)
static void inputDifference(T_Inputs &dst, const T_Inputs &src)
static bool equalInput(const T_Inputs &a, const T_Inputs &b)
static void inputIntersection(T_Inputs &dst, const T_Inputs &src)