Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
CSG.h
Go to the documentation of this file.
1
6/*
7 * This file is part of Algorithms library toolkit.
8 * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)
9
10 * Algorithms library toolkit is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14
15 * Algorithms library toolkit is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19
20 * You should have received a copy of the GNU General Public License
21 * along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#pragma once
25
26
27#include <ext/algorithm>
28
29#include <alib/map>
30#include <alib/set>
31#include <alib/vector>
32
33#include <core/components.hpp>
34
36
38
39#include <core/normalize.hpp>
42
43namespace grammar {
44
45class TerminalAlphabet;
46class NonterminalAlphabet;
47class InitialSymbol;
48
63template < class SymbolType = DefaultSymbolType >
64class CSG final : public core::Components < CSG < SymbolType >, ext::set < SymbolType >, component::Set, std::tuple < TerminalAlphabet, NonterminalAlphabet >, SymbolType, component::Value, InitialSymbol > {
69
73 bool generatesEpsilon;
74
75public:
81 explicit CSG ( SymbolType initialSymbol );
82
90 explicit CSG ( ext::set < SymbolType > nonterminalAlphabet, ext::set < SymbolType > terminalAlphabet, SymbolType initialSymbol );
91
104 bool addRule ( ext::vector < SymbolType > lContext, SymbolType leftHandSide, ext::vector < SymbolType > rContext, ext::vector < SymbolType > rightHandSide );
105
116 void addRules ( ext::vector < SymbolType > lContext, SymbolType leftHandSide, ext::vector < SymbolType > rContext, ext::set < ext::vector < SymbolType > > rightHandSide );
117
124
131
142 bool removeRule ( const ext::vector < SymbolType > & lContext, const SymbolType & leftHandSide, const ext::vector < SymbolType > & rContext, const ext::vector < SymbolType > & rightHandSide );
143
149 const SymbolType & getInitialSymbol ( ) const & {
150 return this->template accessComponent < InitialSymbol > ( ).get ( );
151 }
152
159 return std::move ( this->template accessComponent < InitialSymbol > ( ).get ( ) );
160 }
161
169 bool setInitialSymbol ( SymbolType symbol ) {
170 return this->template accessComponent < InitialSymbol > ( ).set ( std::move ( symbol ) );
171 }
172
179 return this->template accessComponent < NonterminalAlphabet > ( ).get ( );
180 }
181
188 return std::move ( this->template accessComponent < NonterminalAlphabet > ( ).get ( ) );
189 }
190
199 return this->template accessComponent < NonterminalAlphabet > ( ).add ( std::move ( symbol ) );
200 }
201
208 this->template accessComponent < NonterminalAlphabet > ( ).set ( std::move ( symbols ) );
209 }
210
217 return this->template accessComponent < TerminalAlphabet > ( ).get ( );
218 }
219
226 return std::move ( this->template accessComponent < TerminalAlphabet > ( ).get ( ) );
227 }
228
237 return this->template accessComponent < TerminalAlphabet > ( ).add ( std::move ( symbol ) );
238 }
239
246 this->template accessComponent < TerminalAlphabet > ( ).set ( std::move ( symbols ) );
247 }
248
254 void setGeneratesEpsilon ( bool genEps );
255
261 bool getGeneratesEpsilon ( ) const;
262
270 auto operator <=> ( const CSG & other ) const {
271 return std::tie ( getTerminalAlphabet ( ), getNonterminalAlphabet ( ), getInitialSymbol ( ), rules ) <=> std::tie ( other.getTerminalAlphabet ( ), other.getNonterminalAlphabet ( ), other.getInitialSymbol ( ), other.rules );
272 }
273
281 bool operator == ( const CSG & other ) const {
282 return std::tie ( getTerminalAlphabet ( ), getNonterminalAlphabet ( ), getInitialSymbol ( ), rules ) == std::tie ( other.getTerminalAlphabet ( ), other.getNonterminalAlphabet ( ), other.getInitialSymbol ( ), other.rules );
283 }
284
293 friend ext::ostream & operator << ( ext::ostream & out, const CSG & instance ) {
294 return out << "(CSG"
295 << " nonterminalAlphabet = " << instance.getNonterminalAlphabet ( )
296 << " terminalAlphabet = " << instance.getTerminalAlphabet ( )
297 << " initialSymbol = " << instance.getInitialSymbol ( )
298 << " rules = " << instance.getRules ( )
299 << " generatesEpsilon = " << instance.getGeneratesEpsilon ( )
300 << ")";
301 }
302};
303
304template < class SymbolType >
305CSG < SymbolType >::CSG ( SymbolType initialSymbol ) : CSG ( ext::set < SymbolType > { initialSymbol }, ext::set < SymbolType > ( ), initialSymbol ) {
306}
307
308template < class SymbolType >
309CSG < SymbolType >::CSG ( ext::set < SymbolType > nonterminalAlphabet, ext::set < SymbolType > terminalAlphabet, SymbolType initialSymbol ) : core::Components < CSG, ext::set < SymbolType >, component::Set, std::tuple < TerminalAlphabet, NonterminalAlphabet >, SymbolType, component::Value, InitialSymbol > ( std::move ( terminalAlphabet), std::move ( nonterminalAlphabet ), std::move ( initialSymbol ) ), generatesEpsilon ( false ) {
310}
311
312template < class SymbolType >
314 for ( const SymbolType & symbol : lContext )
315 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
316 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
317
318 if ( !getNonterminalAlphabet ( ).count ( leftHandSide ) )
319 throw GrammarException ( "Rule must rewrite nonterminal symbol" );
320
321 for ( const SymbolType & symbol : rContext )
322 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
323 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
324
325 if ( rightHandSide.empty ( ) ) {
326 throw GrammarException ( "Epsilon rule is not allowed" );
327 } else {
328 for ( const SymbolType & symbol : rightHandSide )
329 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
330 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
331 }
332
333 return rules [ ext::make_tuple ( std::move ( lContext ), std::move ( leftHandSide ), std::move ( rContext ) ) ].insert ( std::move ( rightHandSide ) ).second;
334}
335
336template < class SymbolType >
338 for ( const SymbolType & symbol : lContext )
339 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
340 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
341
342 if ( !getNonterminalAlphabet ( ).count ( leftHandSide ) )
343 throw GrammarException ( "Rule must rewrite nonterminal symbol" );
344
345 for ( const SymbolType & symbol : rContext )
346 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
347 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
348
349 for ( const ext::vector < SymbolType > & rhs : rightHandSide ) {
350 if ( rhs.empty ( ) ) {
351 throw GrammarException ( "Epsilon rule is not allowed" );
352 } else {
353 for ( const SymbolType & symbol : rhs )
354 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
355 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
356 }
357 }
358
359 rules [ ext::make_tuple ( std::move ( lContext ), std::move ( leftHandSide ), std::move ( rContext ) ) ].insert ( ext::make_mover ( rightHandSide ).begin ( ), ext::make_mover ( rightHandSide ).end ( ) );
360}
361
362template < class SymbolType >
364 return rules;
365}
366
367template < class SymbolType >
369 return std::move ( rules );
370}
371
372template < class SymbolType >
373bool CSG < SymbolType >::removeRule ( const ext::vector < SymbolType > & lContext, const SymbolType & leftHandSide, const ext::vector < SymbolType > & rContext, const ext::vector < SymbolType > & rightHandSide ) {
374 return rules [ ext::make_tuple ( lContext, leftHandSide, rContext ) ].erase ( rightHandSide );
375}
376
377template < class SymbolType >
379 generatesEpsilon = genEps;
380}
381
382template < class SymbolType >
384 return generatesEpsilon;
385}
386
387} /* namespace grammar */
388
389namespace core {
390
396template < class SymbolType >
397class SetConstraint< grammar::CSG < SymbolType >, SymbolType, grammar::TerminalAlphabet > {
398public:
407 static bool used ( const grammar::CSG < SymbolType > & grammar, const SymbolType & symbol ) {
408 for ( const std::pair < const ext::tuple < ext::vector < SymbolType >, SymbolType, ext::vector < SymbolType > >, ext::set < ext::vector < SymbolType > > > & rule : grammar.getRules ( ) ) {
409 for ( const SymbolType & lCont : std::get < 0 > ( rule.first ) )
410 if ( lCont == symbol )
411 return false;
412
413 for ( const SymbolType & rCont : std::get < 2 > ( rule.first ) )
414 if ( rCont == symbol )
415 return false;
416
417 for ( const ext::vector < SymbolType > & rhs : rule.second )
418 if ( std::find ( rhs.begin ( ), rhs.end ( ), symbol ) != rhs.end ( ) )
419 return false;
420
421 }
422
423 return false;
424 }
425
434 static bool available ( const grammar::CSG < SymbolType > &, const SymbolType & ) {
435 return true;
436 }
437
446 static void valid ( const grammar::CSG < SymbolType > & grammar, const SymbolType & symbol ) {
447 if ( grammar.template accessComponent < grammar::NonterminalAlphabet > ( ).get ( ).count ( symbol ) )
448 throw grammar::GrammarException ( "Symbol " + ext::to_string ( symbol ) + " cannot be in the terminal alphabet since it is already in the nonterminal alphabet." );
449 }
450};
451
457template < class SymbolType >
458class SetConstraint< grammar::CSG < SymbolType >, SymbolType, grammar::NonterminalAlphabet > {
459public:
468 static bool used ( const grammar::CSG < SymbolType > & grammar, const SymbolType & symbol ) {
469 for ( const std::pair < const ext::tuple < ext::vector < SymbolType >, SymbolType, ext::vector < SymbolType > >, ext::set < ext::vector < SymbolType > > > & rule : grammar.getRules ( ) ) {
470 for ( const SymbolType & lCont : std::get < 0 > ( rule.first ) )
471 if ( lCont == symbol )
472 return true;
473
474 if ( std::get < 1 > ( rule.first ) == symbol )
475 return true;
476
477 for ( const SymbolType & rCont : std::get < 2 > ( rule.first ) )
478 if ( rCont == symbol )
479 return true;
480
481 for ( const ext::vector < SymbolType > & rhs : rule.second )
482 if ( std::find ( rhs.begin ( ), rhs.end ( ), symbol ) != rhs.end ( ) )
483 return true;
484
485 }
486
487 return grammar.template accessComponent < grammar::InitialSymbol > ( ).get ( ) == symbol;
488 }
489
498 static bool available ( const grammar::CSG < SymbolType > &, const SymbolType & ) {
499 return true;
500 }
501
510 static void valid ( const grammar::CSG < SymbolType > & grammar, const SymbolType & symbol ) {
511 if ( grammar.template accessComponent < grammar::TerminalAlphabet > ( ).get ( ).count ( symbol ) )
512 throw grammar::GrammarException ( "Symbol " + ext::to_string ( symbol ) + " cannot be in the nonterminal alphabet since it is already in the terminal alphabet." );
513 }
514};
515
521template < class SymbolType >
522class ElementConstraint< grammar::CSG < SymbolType >, SymbolType, grammar::InitialSymbol > {
523public:
532 static bool available ( const grammar::CSG < SymbolType > & grammar, const SymbolType & symbol ) {
533 return grammar.template accessComponent < grammar::NonterminalAlphabet > ( ).get ( ).count ( symbol );
534 }
535
542 static void valid ( const grammar::CSG < SymbolType > &, const SymbolType & ) {
543 }
544};
545
551template < class SymbolType >
552struct normalize < grammar::CSG < SymbolType > > {
554 ext::set < DefaultSymbolType > nonterminals = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getNonterminalAlphabet ( ) );
555 ext::set < DefaultSymbolType > terminals = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getTerminalAlphabet ( ) );
556 DefaultSymbolType initialSymbol = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( value ).getInitialSymbol ( ) );
557
558 grammar::CSG < > res ( std::move ( nonterminals ), std::move ( terminals ), std::move ( initialSymbol ) );
559
560 for ( std::pair < ext::tuple < ext::vector < SymbolType >, SymbolType, ext::vector < SymbolType > >, ext::set < ext::vector < SymbolType > > > && rule : ext::make_mover ( std::move ( value ).getRules ( ) ) ) {
561
563 for ( ext::vector < SymbolType > && target : ext::make_mover ( rule.second ) )
564 rhs.insert ( alphabet::SymbolNormalize::normalizeSymbols ( std::move ( target ) ) );
565
566 ext::vector < DefaultSymbolType > lContext = alphabet::SymbolNormalize::normalizeSymbols ( std::move ( std::get < 0 > ( rule.first ) ) );
567 DefaultSymbolType lhs = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( std::get < 1 > ( rule.first ) ) );
568 ext::vector < DefaultSymbolType > rContext = alphabet::SymbolNormalize::normalizeSymbols ( std::move ( std::get < 2 > ( rule.first ) ) );
569
570 res.addRules ( std::move ( lContext ), std::move ( lhs ), std::move ( rContext ), std::move ( rhs ) );
571 }
572
573 res.setGeneratesEpsilon ( value.getGeneratesEpsilon ( ) );
574
575 return res;
576 }
577};
578
579} /* namespace core */
580
581extern template class grammar::CSG < >;
582
static ext::set< DefaultSymbolType > normalizeAlphabet(ext::set< SymbolType > &&symbols)
Definition: SymbolNormalize.h:50
static ext::vector< DefaultSymbolType > normalizeSymbols(ext::vector< SymbolType > &&symbols)
Definition: SymbolNormalize.h:86
static DefaultSymbolType normalizeSymbol(SymbolType &&symbol)
Definition: SymbolNormalize.h:68
Definition: components.hpp:181
static bool available(const grammar::CSG< SymbolType > &grammar, const SymbolType &symbol)
Definition: CSG.h:532
static void valid(const grammar::CSG< SymbolType > &, const SymbolType &)
Definition: CSG.h:542
Definition: components.hpp:25
static bool available(const grammar::CSG< SymbolType > &, const SymbolType &)
Definition: CSG.h:498
static bool used(const grammar::CSG< SymbolType > &grammar, const SymbolType &symbol)
Definition: CSG.h:468
static void valid(const grammar::CSG< SymbolType > &grammar, const SymbolType &symbol)
Definition: CSG.h:510
static void valid(const grammar::CSG< SymbolType > &grammar, const SymbolType &symbol)
Definition: CSG.h:446
static bool available(const grammar::CSG< SymbolType > &, const SymbolType &)
Definition: CSG.h:434
static bool used(const grammar::CSG< SymbolType > &grammar, const SymbolType &symbol)
Definition: CSG.h:407
Definition: setComponents.hpp:26
Class extending the map class from the standard library. Original reason is to allow printing of the ...
Definition: map.hpp:48
Definition: ostream.h:14
Definition: set.hpp:44
Class extending the tuple class from the standard library. Original reason is to allow printing of th...
Definition: tuple.hpp:42
Class extending the vector class from the standard library. Original reason is to allow printing of t...
Definition: vector.hpp:45
auto begin() &
Inherited behavior of begin for non-const instance.
Definition: vector.hpp:125
auto end() &
Inherited behavior of end for non-const instance.
Definition: vector.hpp:155
Context sensitive grammar in Chomsky hierarchy or type 1 in Chomsky hierarchy. Generates context sens...
Definition: CSG.h:64
const ext::set< SymbolType > & getNonterminalAlphabet() const &
Definition: CSG.h:178
const ext::set< SymbolType > & getTerminalAlphabet() const &
Definition: CSG.h:216
CSG(SymbolType initialSymbol)
Creates a new instance of the grammar with a concrete initial symbol.
Definition: CSG.h:305
void addRules(ext::vector< SymbolType > lContext, SymbolType leftHandSide, ext::vector< SymbolType > rContext, ext::set< ext::vector< SymbolType > > rightHandSide)
Add new rules of a grammar.
Definition: CSG.h:337
bool operator==(const CSG &other) const
Definition: CSG.h:281
bool addRule(ext::vector< SymbolType > lContext, SymbolType leftHandSide, ext::vector< SymbolType > rContext, ext::vector< SymbolType > rightHandSide)
Add a new rule of a grammar.
Definition: CSG.h:313
void setTerminalAlphabet(ext::set< SymbolType > symbols)
Definition: CSG.h:245
bool addTerminalSymbol(SymbolType symbol)
Definition: CSG.h:236
void setGeneratesEpsilon(bool genEps)
Definition: CSG.h:378
bool removeRule(const ext::vector< SymbolType > &lContext, const SymbolType &leftHandSide, const ext::vector< SymbolType > &rContext, const ext::vector< SymbolType > &rightHandSide)
Definition: CSG.h:373
bool setInitialSymbol(SymbolType symbol)
Definition: CSG.h:169
ext::set< SymbolType > && getNonterminalAlphabet() &&
Definition: CSG.h:187
SymbolType && getInitialSymbol() &&
Definition: CSG.h:158
ext::set< SymbolType > && getTerminalAlphabet() &&
Definition: CSG.h:225
bool addNonterminalSymbol(SymbolType symbol)
Definition: CSG.h:198
auto operator<=>(const CSG &other) const
Definition: CSG.h:270
void setNonterminalAlphabet(ext::set< SymbolType > symbols)
Definition: CSG.h:207
const SymbolType & getInitialSymbol() const &
Definition: CSG.h:149
friend ext::ostream & operator<<(ext::ostream &out, const CSG &instance)
Definition: CSG.h:293
bool getGeneratesEpsilon() const
Definition: CSG.h:383
const ext::map< ext::tuple< ext::vector< SymbolType >, SymbolType, ext::vector< SymbolType > >, ext::set< ext::vector< SymbolType > > > & getRules() const &
Definition: CSG.h:363
Definition: GrammarException.h:15
Definition: Object.h:16
typename T::SymbolType SymbolType
Definition: ReachableStates.h:176
return res
Definition: MinimizeByPartitioning.h:145
Definition: normalize.hpp:10
constexpr tuple< Elements &... > tie(Elements &... args) noexcept
Helper of extended tuple of references construction. The tuple is constructed to reffer to values in ...
Definition: tuple.hpp:218
reference_mover< T > make_mover(T &param)
Move adaptor construction function specialized to lvalue reference parameter.
Definition: iterator.hpp:468
std::string to_string(const T &value)
To string method designated for objects that can be casted to string.
Definition: string.hpp:131
constexpr auto make_tuple(Elements &&... args)
Helper of extended tuple construction. The tuple is constructed from values pack, types are deduced.
Definition: tuple.hpp:203
auto begin(Container &&cont) -> decltype(std::forward(cont).begin())
Definition: iterator.hpp:900
Definition: ToAutomaton.h:24
void end()
Definition: measurements.cpp:19
auto & get(ext::ptr_array< Type, N > &tpl)
Specialisation of get function for pointer arrays.
Definition: ptr_array.hpp:693
static grammar::CSG< > eval(grammar::CSG< SymbolType > &&value)
Definition: CSG.h:553
Definition: normalize.hpp:13