Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
LatexConverter.h
Go to the documentation of this file.
1
6#pragma once
7
8#include <ext/ostream>
9#include <ext/sstream>
10
11#include <string/String.h>
12
13#include <automaton/FSM/DFA.h>
14#include <automaton/FSM/NFA.h>
18
21
23
26
27namespace convert {
28
30public:
31 template < class FiniteAutomatonType >
32 static void convertFSM ( ext::ostream & out, const FiniteAutomatonType & automaton, bool wideTable = false );
33
34 template < class FiniteAutomatonType >
35 static std::string convertFSM ( const FiniteAutomatonType & automaton ) {
36 return convertFSM ( automaton, false );
37 }
38
39 template < class FiniteAutomatonType >
40 static std::string convertFSM ( const FiniteAutomatonType & automaton, bool wideTable ) {
42 convertFSM ( ss, automaton, wideTable );
43 return ss.str ( );
44 }
45
46 /* --------------------------------------------------------------------- */
47
48 template < class TerminalSymbolType, class NonterminalSymbolType >
50
51 template < class TerminalSymbolType, class NonterminalSymbolType >
53
54 template < class GrammarType >
55 static void convertGrammar ( ext::ostream & out, const GrammarType & grammar );
56
57 template < class GrammarType >
58 static std::string convertGrammar ( const GrammarType & grammar ) {
60 convertGrammar ( ss, grammar );
61 return ss.str ( );
62 }
63
64private:
65 template < class SymbolType, class StateType >
66 static constexpr const char* automatonType ( const automaton::DFA < SymbolType, StateType > & ) {
67 return "DFA";
68 }
69
70 template < class SymbolType, class StateType >
71 static constexpr const char* automatonType ( const automaton::NFA < SymbolType, StateType > & ) {
72 return "NFA";
73 }
74
75 template < class SymbolType, class StateType >
76 static constexpr const char* automatonType ( const automaton::EpsilonNFA < SymbolType, StateType > & ) {
77 return "$\\varepsilon$-NFA";
78 }
79
80 template < class SymbolType, class StateType >
81 static constexpr const char* automatonType ( const automaton::MultiInitialStateNFA < SymbolType, StateType > & ) {
82 return "NFA";
83 }
84
85 template < class SymbolType, class StateType >
86 static constexpr const char* automatonType ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, StateType > & ) {
87 return "$\\varepsilon$-NFA";
88 }
89
90 /* --------------------------------------------------------------------- */
91
92 template < class FiniteAutomatonType, class StateType >
93 requires automaton::isMultiInitialStateNFA < FiniteAutomatonType > || automaton::isMultiInitialStateEpsilonNFA < FiniteAutomatonType >
94 static inline bool isInitialState ( const FiniteAutomatonType & automaton, const StateType & state ) {
95 return automaton.getInitialStates ( ).count ( state );
96 }
97
98 template < class FiniteAutomatonType, class StateType >
99 requires automaton::isDFA < FiniteAutomatonType > || automaton::isNFA < FiniteAutomatonType > || automaton::isEpsilonNFA < FiniteAutomatonType >
100 static inline bool isInitialState ( const FiniteAutomatonType & automaton, const StateType & state ) {
101 return automaton.getInitialState ( ) == state;
102 }
103
104 /* --------------------------------------------------------------------- */
105
106 template < class FiniteAutomatonType, class StateType >
107 requires automaton::isDFA < FiniteAutomatonType >
108 static void transitionsRow ( ext::ostream & out, const FiniteAutomatonType & automaton, const StateType & state ) {
109 for ( const auto & symbol : automaton.getInputAlphabet ( ) ) {
110 out << " & ";
111
112 auto transition = automaton.getTransitions ( ).find ( ext::make_pair ( state, symbol ) );
113 if ( transition == automaton.getTransitions ( ).end ( ) )
114 out << "-";
115 else
116 out << replace ( factory::StringDataFactory::toString ( transition -> second ), "\"", "\\\"" );
117 }
118 }
119
120 template < class FiniteAutomatonType, class StateType >
121 requires automaton::isNFA < FiniteAutomatonType > || automaton::isMultiInitialStateNFA < FiniteAutomatonType >
122 static void transitionsRow ( ext::ostream & out, const FiniteAutomatonType & automaton, const StateType & state ) {
123 for ( const auto & symbol : automaton.getInputAlphabet ( ) ) {
124 out << " & ";
125
126 auto transitions = automaton.getTransitions ( ).equal_range ( ext::make_pair ( state, symbol ) );
127
128 for ( auto it = transitions.begin ( ); it != transitions.end ( ); ++ it ) {
129 if ( it != transitions.begin ( ) )
130 out << ",";
131 out << replace ( factory::StringDataFactory::toString ( it->second ), "\"", "\\\"" );
132 }
133
134 if ( transitions.empty ( ) )
135 out << "-";
136 }
137 }
138
139 template < class FiniteAutomatonType, class StateType >
140 requires automaton::isEpsilonNFA < FiniteAutomatonType > || automaton::isMultiInitialStateEpsilonNFA < FiniteAutomatonType >
141 static void transitionsRow ( ext::ostream & out, const FiniteAutomatonType & automaton, const StateType & state ) {
142 const auto symTransitions = automaton.getSymbolTransitions ( );
143 const auto epsTransitions = automaton.getEpsilonTransitions ( );
144
145 /* columns for symbols */
146 for ( const auto & symbol : automaton.getInputAlphabet ( ) ) {
147 out << " & ";
148
149 auto tr = symTransitions.equal_range ( ext::make_pair ( state, symbol ) );
150
151 if ( tr.empty ( ) )
152 out << "-";
153
154 for ( auto it = tr.begin ( ); it != tr.end ( ); ++ it ) {
155 if ( it != tr.begin ( ) )
156 out << ",";
157 out << replace ( factory::StringDataFactory::toString ( it -> second ), "\"", "\\\"" );
158 }
159 }
160
161 /* column for epsilon */
162 out << " & ";
163 auto tr = epsTransitions.equal_range ( state );
164
165 if ( tr.empty ( ) )
166 out << "-";
167
168 for ( auto it = tr.begin ( ); it != tr.end ( ); ++ it ) {
169 if ( it != tr.begin ( ) )
170 out << ",";
171 out << replace ( factory::StringDataFactory::toString ( it->second ), "\"", "\\\"" );
172 }
173 }
174
175};
176
177template < class FiniteAutomatonType >
178void LatexConverter::convertFSM ( ext::ostream & out, const FiniteAutomatonType & automaton, bool wideTable ) {
179 constexpr bool isEpsilonType = automaton::isMultiInitialStateEpsilonNFA < FiniteAutomatonType > || automaton::isEpsilonNFA < FiniteAutomatonType >;
180
181 if( wideTable )
182 out << "\\begin{tabular*}{\\textwidth}{|rl||";
183 else
184 out << "\\begin{tabular}{|rl||";
185
186 for ( size_t i = 0; i < automaton.getInputAlphabet ( ).size ( ) + isEpsilonType ; ++ i )
187 out << "c|";
188 out << "}" << std::endl;
189
190 out << "\\hline" << std::endl;
191 out << "\\multicolumn{2}{|c||}{" << automatonType ( automaton ) << "}";
192
193 for ( const auto & symbol : automaton.getInputAlphabet ( ) )
194 out << " & " << replace ( factory::StringDataFactory::toString ( symbol ), "\"", "\\\"" );
195
196 if constexpr ( isEpsilonType )
197 out << " & $\\varepsilon$";
198
199 // out << "\\hspace*{14cm}\\\\" << std::endl;
200 out << "\\\\\\hline" << std::endl;
201
202 for ( const auto & state : automaton.getStates ( ) ) {
203 if ( automaton.getFinalStates ( ).count ( state ) && isInitialState ( automaton, state ) )
204 out << "$\\leftrightarrow$ & ";
205 else if ( automaton.getFinalStates ( ).count ( state ) )
206 out << "$\\leftarrow$ & ";
207 else if ( isInitialState ( automaton, state ) )
208 out << "$\\rightarrow$ & ";
209 else
210 out << " & ";
211
212 out << replace ( factory::StringDataFactory::toString ( state ), "\"", "\\\"" );
213 transitionsRow ( out, automaton, state );
214 out << " \\\\\\hline" << std::endl;
215 }
216
217 if ( wideTable )
218 out << "\\end{tabular*}" << std::endl;
219 else
220 out << "\\end{tabular}" << std::endl;
221}
222
223/* ----------------------------------------------------------------------------------------------------------------- */
224
225template < class TerminalSymbolType, class NonterminalSymbolType >
227 for ( const auto & kv : grammar.getRules ( ) ) {
228 const auto & lhs = kv.first;
229
230 if ( ! kv.second.empty ( ) )
231 out << replace ( factory::StringDataFactory::toString ( lhs ), "\"", "\\\"" ) << " & \\rightarrow & ";
232
233 for ( auto itRhs = kv.second.begin ( ); itRhs != kv.second.end ( ); ++ itRhs ) {
234 if ( itRhs != kv.second.begin ( ) )
235 out << " \\mid ";
236
237 for ( const auto & symb : *itRhs )
238 out << replace ( factory::StringDataFactory::toString ( symb ), "\"", "\\\"" ) << " ";
239
240 if ( itRhs -> empty ( ) )
241 out << "\\varepsilon";
242 }
243 out << "\\\\" << std::endl;
244 }
245}
246
247template < class TerminalSymbolType, class NonterminalSymbolType >
249 for ( const auto & kv : grammar.getRules ( ) ) {
250 const NonterminalSymbolType & lhs = kv.first;
251
252 if ( ! kv.second.empty ( ) )
253 out << replace ( factory::StringDataFactory::toString ( lhs ), "\"", "\\\"" ) << " & \\rightarrow & ";
254
255 for ( auto itRhs = kv.second.begin ( ); itRhs != kv.second.end ( ); ++ itRhs ) {
256 if ( itRhs != kv.second.begin ( ) )
257 out << " \\mid ";
258
259 if ( itRhs -> template is < TerminalSymbolType > ( ) )
260 out << replace ( factory::StringDataFactory::toString ( itRhs -> template get < TerminalSymbolType > ( ) ), "\"", "\\\"" ) << " ";
261 else {
262 const ext::pair < TerminalSymbolType, NonterminalSymbolType > & rhs = itRhs -> template get < ext::pair < TerminalSymbolType, NonterminalSymbolType > > ( );
263 out << replace ( factory::StringDataFactory::toString ( rhs.first ), "\"", "\\\"" ) << " ";
264 out << replace ( factory::StringDataFactory::toString ( rhs.second ), "\"", "\\\"" ) << " ";
265 }
266 }
267 if ( lhs == grammar.getInitialSymbol ( ) && grammar.getGeneratesEpsilon ( ) )
268 out << " \\mid \\varepsilon";
269 out << "\\\\" << std::endl;
270 }
271}
272
273template < class GrammarType >
274void LatexConverter::convertGrammar ( ext::ostream & out, const GrammarType & grammar ) {
275 out << "";
276 out << "$$G = (\\{";
277 for ( auto it = grammar.getNonterminalAlphabet ( ).begin ( ); it != grammar.getNonterminalAlphabet ( ).end ( ); ++ it ) {
278 if ( it != grammar.getNonterminalAlphabet ( ).begin ( ) )
279 out << ", ";
280 out << replace ( factory::StringDataFactory::toString ( *it ), "\"", "\\\"" );
281 }
282 out << "\\}, \\{";
283 for ( auto it = grammar.getTerminalAlphabet ( ).begin ( ); it != grammar.getTerminalAlphabet ( ).end ( ); ++ it ) {
284 if ( it != grammar.getTerminalAlphabet ( ).begin ( ) )
285 out << ", ";
286 out << replace ( factory::StringDataFactory::toString ( *it ), "\"", "\\\"" );
287 }
288 out << "\\}, P, ";
289 out << replace ( factory::StringDataFactory::toString ( grammar.getInitialSymbol ( ) ), "\"", "\\\"");
290 out << ")$$" << std::endl << std::endl;
291
292 out << "\\begin{eqnarray*}" << std::endl;
293 rules ( out, grammar );
294 out << "\\end{eqnarray*}" << std::endl;
295}
296
297} /* namespace convert */
298
Deterministic finite automaton. Accepts regular languages.
Definition: DFA.h:71
Epsilon nondeterministic finite automaton. Accepts regular languages.
Definition: EpsilonNFA.h:74
Epsilon nondeterministic finite automaton. Accepts regular languages.
Definition: MultiInitialStateEpsilonNFA.h:75
Nondeterministic finite automaton with multiple initial states. Accepts regular languages.
Definition: MultiInitialStateNFA.h:69
Nondeterministic finite automaton. Accepts regular languages.
Definition: NFA.h:66
Definition: LatexConverter.h:29
static std::string convertFSM(const FiniteAutomatonType &automaton, bool wideTable)
Definition: LatexConverter.h:40
static std::string convertFSM(const FiniteAutomatonType &automaton)
Definition: LatexConverter.h:35
static std::string convertGrammar(const GrammarType &grammar)
Definition: LatexConverter.h:58
static void rules(ext::ostream &out, const grammar::CFG< TerminalSymbolType, NonterminalSymbolType > &grammar)
Definition: LatexConverter.h:226
static void convertFSM(ext::ostream &out, const FiniteAutomatonType &automaton, bool wideTable=false)
Definition: LatexConverter.h:178
static void convertGrammar(ext::ostream &out, const GrammarType &grammar)
Definition: LatexConverter.h:274
Definition: ostream.h:14
Definition: sstream.h:15
std::string str() const &
Definition: sstream.cpp:29
Class extending the pair class from the standard library. Original reason is to allow printing of the...
Definition: pair.hpp:43
static std::string toString(const T &data)
Definition: StringDataFactory.hpp:89
Context free grammar in Chomsky hierarchy or type 2 in Chomsky hierarchy. Generates context free lang...
Definition: CFG.h:67
Right regular grammar in Chomsky hierarchy or type 3 in Chomsky hierarchy. Generates regular language...
Definition: RightRG.h:70
typename T::StateType StateType
Definition: ToGrammarLeftRG.h:64
p second
Definition: ToRegExpAlgebraic.h:126
int i
Definition: AllEpsilonClosure.h:118
Definition: ToGrammar.h:31
Definition: converterCommon.hpp:8
auto replace
Definition: converterCommon.hpp:19
constexpr auto make_pair(T1 &&x, T2 &&y)
Definition: pair.hpp:79
Definition: ToAutomaton.h:24