Algorithms Library Toolkit
A toolkit for algorithms, especially for algorithms on formal languages
NonContractingGrammar.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 NonContractingGrammar final : public core::Components < NonContractingGrammar < SymbolType >, ext::set < SymbolType >, component::Set, std::tuple < TerminalAlphabet, NonterminalAlphabet >, SymbolType, component::Value, InitialSymbol > {
69
73 bool generatesEpsilon;
74
75public:
81 explicit NonContractingGrammar ( SymbolType initialSymbol );
82
90 explicit NonContractingGrammar ( ext::set < SymbolType > nonterminalAlphabet, ext::set < SymbolType > terminalAlphabet, SymbolType initialSymbol );
91
102 bool addRule ( ext::vector < SymbolType > leftHandSide, ext::vector < SymbolType > rightHandSide );
103
112 void addRules ( ext::vector < SymbolType > leftHandSide, ext::set < ext::vector < SymbolType > > rightHandSide );
113
120
127
136 bool removeRule ( const ext::vector < SymbolType > & leftHandSide, const ext::vector < SymbolType > & rightHandSide );
137
143 const SymbolType & getInitialSymbol ( ) const & {
144 return this->template accessComponent < InitialSymbol > ( ).get ( );
145 }
146
153 return std::move ( this->template accessComponent < InitialSymbol > ( ).get ( ) );
154 }
155
163 bool setInitialSymbol ( SymbolType symbol ) {
164 return this->template accessComponent < InitialSymbol > ( ).set ( std::move ( symbol ) );
165 }
166
173 return this->template accessComponent < NonterminalAlphabet > ( ).get ( );
174 }
175
182 return std::move ( this->template accessComponent < NonterminalAlphabet > ( ).get ( ) );
183 }
184
193 return this->template accessComponent < NonterminalAlphabet > ( ).add ( std::move ( symbol ) );
194 }
195
202 this->template accessComponent < NonterminalAlphabet > ( ).set ( std::move ( symbols ) );
203 }
204
211 return this->template accessComponent < TerminalAlphabet > ( ).get ( );
212 }
213
220 return std::move ( this->template accessComponent < TerminalAlphabet > ( ).get ( ) );
221 }
222
231 return this->template accessComponent < TerminalAlphabet > ( ).add ( std::move ( symbol ) );
232 }
233
240 this->template accessComponent < TerminalAlphabet > ( ).set ( std::move ( symbols ) );
241 }
242
248 void setGeneratesEpsilon ( bool genEps );
249
255 bool getGeneratesEpsilon ( ) const;
256
264 auto operator <=> ( const NonContractingGrammar & other ) const {
265 return std::tie ( getTerminalAlphabet ( ), getNonterminalAlphabet ( ), getInitialSymbol ( ), rules ) <=> std::tie ( other.getTerminalAlphabet ( ), other.getNonterminalAlphabet ( ), other.getInitialSymbol ( ), other.rules );
266 }
267
275 bool operator == ( const NonContractingGrammar & other ) const {
276 return std::tie ( getTerminalAlphabet ( ), getNonterminalAlphabet ( ), getInitialSymbol ( ), rules ) == std::tie ( other.getTerminalAlphabet ( ), other.getNonterminalAlphabet ( ), other.getInitialSymbol ( ), other.rules );
277 }
278
287 friend ext::ostream & operator << ( ext::ostream & out, const NonContractingGrammar & instance ) {
288 return out << "(NonContractingGrammar"
289 << " nonterminalAlphabet = " << instance.getNonterminalAlphabet ( )
290 << " terminalAlphabet = " << instance.getTerminalAlphabet ( )
291 << " initialSymbol = " << instance.getInitialSymbol ( )
292 << " rules = " << instance.getRules ( )
293 << " generatesEpsilon = " << instance.getGeneratesEpsilon ( )
294 << ")";
295 }
296};
297
298template < class SymbolType >
300}
301
302template < class SymbolType >
303NonContractingGrammar < SymbolType >::NonContractingGrammar ( ext::set < SymbolType > nonterminalAlphabet, ext::set < SymbolType > terminalAlphabet, SymbolType initialSymbol ) : core::Components < NonContractingGrammar, ext::set < SymbolType >, component::Set, std::tuple < TerminalAlphabet, NonterminalAlphabet >, SymbolType, component::Value, InitialSymbol > ( std::move ( terminalAlphabet), std::move ( nonterminalAlphabet ), std::move ( initialSymbol ) ), generatesEpsilon ( false ) {
304}
305
306template < class SymbolType >
308 int lSize = leftHandSide.size ( );
309
310 if ( std::all_of ( leftHandSide.begin ( ), leftHandSide.end ( ), [this] ( const SymbolType symbol ) {
311 return !getNonterminalAlphabet ( ).count ( symbol );
312 } ) )
313 throw GrammarException ( "Rule must rewrite nonterminal symbol" );
314
315 for ( const SymbolType & symbol : leftHandSide )
316 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
317 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
318
319 int rSize = rightHandSide.size ( );
320
321 if ( lSize > rSize )
322 throw GrammarException ( "Invalid size of right hand side of a rule" );
323
324 for ( const SymbolType & symbol : rightHandSide )
325 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
326 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
327
328 return rules[std::move ( leftHandSide )].insert ( std::move ( rightHandSide ) ).second;
329}
330
331template < class SymbolType >
333 int lSize = leftHandSide.size ( );
334
335 if ( std::all_of ( leftHandSide.begin ( ), leftHandSide.end ( ), [this] ( const SymbolType symbol ) {
336 return !getNonterminalAlphabet ( ).count ( symbol );
337 } ) )
338 throw GrammarException ( "Rule must rewrite nonterminal symbol" );
339
340 for ( const SymbolType & symbol : leftHandSide )
341 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
342 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
343
344 for ( const ext::vector < SymbolType > & rhs : rightHandSide ) {
345
346 int rSize = rightHandSide.size ( );
347
348 if ( lSize > rSize )
349 throw GrammarException ( "Invalid size of right hand side of a rule" );
350
351 for ( const SymbolType & symbol : rhs )
352 if ( !getTerminalAlphabet ( ).count ( symbol ) && !getNonterminalAlphabet ( ).count ( symbol ) )
353 throw GrammarException ( "Symbol \"" + ext::to_string ( symbol ) + "\" is not neither terminal nor nonterminal symbol" );
354 }
355
356 rules [ std::move ( leftHandSide ) ].insert ( ext::make_mover ( rightHandSide ).begin ( ), ext::make_mover ( rightHandSide ).end ( ) );
357}
358
359template < class SymbolType >
361 return rules;
362}
363
364template < class SymbolType >
366 return std::move ( rules );
367}
368
369template < class SymbolType >
371 return rules[leftHandSide].erase ( rightHandSide );
372}
373
374template < class SymbolType >
376 generatesEpsilon = genEps;
377}
378
379template < class SymbolType >
381 return generatesEpsilon;
382}
383
384} /* namespace grammar */
385
386namespace core {
387
393template < class SymbolType >
394class SetConstraint< grammar::NonContractingGrammar < SymbolType >, SymbolType, grammar::TerminalAlphabet > {
395public:
405 for ( const std::pair < const ext::vector < SymbolType >, ext::set < ext::vector < SymbolType > > > & rule : grammar.getRules ( ) ) {
406 if ( std::find ( rule.first.begin ( ), rule.first.end ( ), symbol ) != rule.first.end ( ) )
407 return true;
408
409 for ( const ext::vector < SymbolType > & rhs : rule.second )
410 if ( std::find ( rhs.begin ( ), rhs.end ( ), symbol ) != rhs.end ( ) )
411 return true;
412
413 }
414
415 return false;
416 }
417
427 return true;
428 }
429
439 if ( grammar.template accessComponent < grammar::NonterminalAlphabet > ( ).get ( ).count ( symbol ) )
440 throw grammar::GrammarException ( "Symbol " + ext::to_string ( symbol ) + " cannot be in the terminal alphabet since it is already in the nonterminal alphabet." );
441 }
442};
443
449template < class SymbolType >
450class SetConstraint< grammar::NonContractingGrammar < SymbolType >, SymbolType, grammar::NonterminalAlphabet > {
451public:
461 for ( const std::pair < const ext::vector < SymbolType >, ext::set < ext::vector < SymbolType > > > & rule : grammar.getRules ( ) ) {
462 if ( std::find ( rule.first.begin ( ), rule.first.end ( ), symbol ) != rule.first.end ( ) )
463 return true;
464
465 for ( const ext::vector < SymbolType > & rhs : rule.second )
466 if ( std::find ( rhs.begin ( ), rhs.end ( ), symbol ) != rhs.end ( ) )
467 return true;
468
469 }
470
471 return grammar.template accessComponent < grammar::InitialSymbol > ( ).get ( ) == symbol;
472 }
473
483 return true;
484 }
485
495 if ( grammar.template accessComponent < grammar::TerminalAlphabet > ( ).get ( ).count ( symbol ) )
496 throw grammar::GrammarException ( "Symbol " + ext::to_string ( symbol ) + " cannot be in the nonterminal alphabet since it is already in the terminal alphabet." );
497 }
498};
499
505template < class SymbolType >
506class ElementConstraint< grammar::NonContractingGrammar < SymbolType >, SymbolType, grammar::InitialSymbol > {
507public:
517 return grammar.template accessComponent < grammar::NonterminalAlphabet > ( ).get ( ).count ( symbol );
518 }
519
527 }
528};
529
535template < class SymbolType >
536struct normalize < grammar::NonContractingGrammar < SymbolType > > {
538 ext::set < DefaultSymbolType > nonterminals = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getNonterminalAlphabet ( ) );
539 ext::set < DefaultSymbolType > terminals = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getTerminalAlphabet ( ) );
540 DefaultSymbolType initialSymbol = alphabet::SymbolNormalize::normalizeSymbol ( std::move ( value ).getInitialSymbol ( ) );
541
542 grammar::NonContractingGrammar < > res ( std::move ( nonterminals ), std::move ( terminals ), std::move ( initialSymbol ) );
543
544 for ( std::pair < ext::vector < SymbolType >, ext::set < ext::vector < SymbolType > > > && rule : ext::make_mover ( std::move ( value ).getRules ( ) ) ) {
545
547 for ( ext::vector < SymbolType > && target : ext::make_mover ( rule.second ) )
548 rhs.insert ( alphabet::SymbolNormalize::normalizeSymbols ( std::move ( target ) ) );
549
551
552 res.addRules ( std::move ( lhs ), std::move ( rhs ) );
553 }
554
555 res.setGeneratesEpsilon ( value.getGeneratesEpsilon ( ) );
556
557 return res;
558 }
559};
560
561} /* namespace core */
562
563extern template class grammar::NonContractingGrammar < >;
564
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 void valid(const grammar::NonContractingGrammar< SymbolType > &, const SymbolType &)
Definition: NonContractingGrammar.h:526
static bool available(const grammar::NonContractingGrammar< SymbolType > &grammar, const SymbolType &symbol)
Definition: NonContractingGrammar.h:516
Definition: components.hpp:25
static bool available(const grammar::NonContractingGrammar< SymbolType > &, const SymbolType &)
Definition: NonContractingGrammar.h:482
static void valid(const grammar::NonContractingGrammar< SymbolType > &grammar, const SymbolType &symbol)
Definition: NonContractingGrammar.h:494
static bool used(const grammar::NonContractingGrammar< SymbolType > &grammar, const SymbolType &symbol)
Definition: NonContractingGrammar.h:460
static void valid(const grammar::NonContractingGrammar< SymbolType > &grammar, const SymbolType &symbol)
Definition: NonContractingGrammar.h:438
static bool used(const grammar::NonContractingGrammar< SymbolType > &grammar, const SymbolType &symbol)
Definition: NonContractingGrammar.h:404
static bool available(const grammar::NonContractingGrammar< SymbolType > &, const SymbolType &)
Definition: NonContractingGrammar.h:426
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 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
Definition: GrammarException.h:15
Noncontracting grammar in Chomsky hierarchy or type 1 in Chomsky hierarchy. Generates context sensiti...
Definition: NonContractingGrammar.h:64
bool addNonterminalSymbol(SymbolType symbol)
Definition: NonContractingGrammar.h:192
const ext::set< SymbolType > & getTerminalAlphabet() const &
Definition: NonContractingGrammar.h:210
bool addTerminalSymbol(SymbolType symbol)
Definition: NonContractingGrammar.h:230
void setNonterminalAlphabet(ext::set< SymbolType > symbols)
Definition: NonContractingGrammar.h:201
void setTerminalAlphabet(ext::set< SymbolType > symbols)
Definition: NonContractingGrammar.h:239
void addRules(ext::vector< SymbolType > leftHandSide, ext::set< ext::vector< SymbolType > > rightHandSide)
Add new rules of a grammar.
Definition: NonContractingGrammar.h:332
ext::set< SymbolType > && getNonterminalAlphabet() &&
Definition: NonContractingGrammar.h:181
const ext::set< SymbolType > & getNonterminalAlphabet() const &
Definition: NonContractingGrammar.h:172
void setGeneratesEpsilon(bool genEps)
Definition: NonContractingGrammar.h:375
bool operator==(const NonContractingGrammar &other) const
Definition: NonContractingGrammar.h:275
bool removeRule(const ext::vector< SymbolType > &leftHandSide, const ext::vector< SymbolType > &rightHandSide)
Definition: NonContractingGrammar.h:370
bool getGeneratesEpsilon() const
Definition: NonContractingGrammar.h:380
friend ext::ostream & operator<<(ext::ostream &out, const NonContractingGrammar &instance)
Definition: NonContractingGrammar.h:287
const ext::map< ext::vector< SymbolType >, ext::set< ext::vector< SymbolType > > > & getRules() const &
Definition: NonContractingGrammar.h:360
SymbolType && getInitialSymbol() &&
Definition: NonContractingGrammar.h:152
auto operator<=>(const NonContractingGrammar &other) const
Definition: NonContractingGrammar.h:264
const SymbolType & getInitialSymbol() const &
Definition: NonContractingGrammar.h:143
bool setInitialSymbol(SymbolType symbol)
Definition: NonContractingGrammar.h:163
ext::set< SymbolType > && getTerminalAlphabet() &&
Definition: NonContractingGrammar.h:219
NonContractingGrammar(SymbolType initialSymbol)
Creates a new instance of the grammar with a concrete initial symbol.
Definition: NonContractingGrammar.h:299
bool addRule(ext::vector< SymbolType > leftHandSide, ext::vector< SymbolType > rightHandSide)
Add a new rule of a grammar.
Definition: NonContractingGrammar.h:307
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
all_of(T &&...) -> all_of< T... >
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::NonContractingGrammar< > eval(grammar::NonContractingGrammar< SymbolType > &&value)
Definition: NonContractingGrammar.h:537
Definition: normalize.hpp:13