Elementa v8.0.0
Minimalistic library for any C++ application (C++11 and up)
Loading...
Searching...
No Matches
cfgrammars.h
Go to the documentation of this file.
1
3#include "elementa/license.inc"
4#include "elementa/checks.inc"
5
6#ifndef ELEMENTA_PARSING_CFGRAMMARS
7#define ELEMENTA_PARSING_CFGRAMMARS
8
9#include <vector>
10#include <map>
11#include <set>
12#include <utility>
13#include <type_traits>
14#include <iterator>
19#include "elementa/base/enums.h"
22
23namespace elementa
24{
25
26namespace parsing
27{
28
49/* **********************************************************************
50
51 Class: CFGrammar
52
53*************************************************************************/
54
56
71{
72 public:
73
78 {
79 MultipleEntry(const std::string & details):
80 elementa::base::Exc{"Multiple entry in LL(1) table" +
81 details} {}
82
84 };
85
93
98
100 using SetOfElements = std::set<CodeElement>;
101
103 using MapOfElements = std::map<CodeElement,SetOfElements>;
104
106 using VectorOfElements = std::vector<CodeElement>;
107
109
111
113 using RHSs = std::vector<RHS>;
114
116 using MapOfRules = std::map<CodeElement, RHSs>;
117
119 using Rule = std::pair<CodeElement,RHS>;
120
122
125 {
126 public:
127
129 using Category = std::bidirectional_iterator_tag;
130
132 using T = Rule;
133
135 using Distance = std::ptrdiff_t;
136
138 using Pointer = T*;
139
141 using Reference = T&;
142
143
147 ELE_CODE_TRACE({},"RuleIterator::dflt-constr. of " <<
149
151
155 RuleIterator(const CFGrammar & gr, bool beginorend = true);
156
157 RuleIterator(const RuleIterator & oth):Validatable{oth}
158 {ELE_CODE_TRACE_OFF; ELE_CODE_TRACE({},"RuleIterator::copy-const.");
159 copyFrom(oth); }
160
161 RuleIterator(RuleIterator && oth):Validatable{oth}
162 {ELE_CODE_TRACE_OFF; ELE_CODE_TRACE({},"RuleIterator::move-const.");
163 copyFrom(oth); }
164
165 RuleIterator & operator=(const RuleIterator & oth)
167 ELE_CODE_TRACE({},"RuleIterator::assign, oth!=this : " <<
168 (this != &oth));
169 if (this != &oth) { Validatable::operator=(oth); copyFrom(oth);}
170 return(*this); }
171 RuleIterator & operator=(RuleIterator && oth)
173 ELE_CODE_TRACE({},"RuleIterator::move-assign, oth!=this : " <<
174 (this != &oth));
175 if (this != &oth) { Validatable::operator=(oth); copyFrom(oth);}
176 return(*this); }
177
181 ELE_CODE_TRACE({},"RuleIterator::destructor of " <<
183
186
189
192
195
197 Rule operator*(void) const;
198
200 bool operator==(const RuleIterator & oth) const;
201
203 bool operator!=(const RuleIterator & oth) const
204 { return(!this->operator==(oth)); }
205
206 private:
207
208 std::pair<typename MapOfRules::const_iterator,
209 typename RHSs::size_type> pos_;
210 MapOfRules::const_iterator grbeg_, grend_;
211
212 void copyFrom(const RuleIterator & oth);
213 };
214
216 class LL1TableIndex: public std::pair<CodeElement,CodeElement>,
218 {
219 public:
220
221 using BaseClass = std::pair<CodeElement,CodeElement>;
222
224 LL1TableIndex(void) = default;
225
227 LL1TableIndex(const LL1TableIndex & oth):Validatable{oth},
228 BaseClass{oth} {}
229
231 LL1TableIndex(LL1TableIndex && oth):Validatable{std::move(oth)},
232 BaseClass{std::move(oth)} {}
233
236 { if (this != &oth) { Validatable::operator=(oth);
237 if (valid()) BaseClass::operator=(oth); }
238 return(*this); }
239
242 { if (this != &oth) { Validatable::operator=(std::move(oth));
243 if (valid())
244 BaseClass::operator=(std::move(oth)); }
245 return(*this); }
246
248 LL1TableIndex(CodeElement nt, CodeElement t):BaseClass{nt,t}
249 { if (!isNonTerminal(nt))
251 std::string{"First part of a LL1 table index is not a "} +
252 "non-terminal (code " + std::to_string(nt) +")");
253 if ((!isTerminal(t))&&(t != kCodeEnd)) // endofsentence is allowed
255 std::string{"Second part of a LL1 table index is not a "} +
256 "terminal or endofsentence (code " +std::to_string(t) +")");
257 setValid(); }
258
259 bool operator==(const LL1TableIndex & o) const
260 { return(valid() && o.valid() &&
261 (this->first == o.first) && (this->second == o.second)); }
262
263 bool operator!=(const LL1TableIndex & o) const
264 { return(!operator==(o)); }
265
266 bool operator<(const LL1TableIndex & oth) const
267 { return(valid() && oth.valid() &&
268 ( (first < oth.first) ||
269 ( (first == oth.first) && (second < oth.second) ))); }
270 };
271
273
278 class CatId: public std::pair<int,int>
279 {
280 public:
281
282 using Base = std::pair<int,int>;
283 using Base::Base;
284 };
285
287 using LL1Table = std::map<LL1TableIndex,RuleIterator>;
288
289 static const CodeElement kCodeEmpty;
290
291 static const CodeElement kCodeEnd;
292
293 static const std::string kEmptyName;
294
295 static const std::string kEndName;
296
304 static bool isNonTerminal(CodeElement c) noexcept
305 { return(c > kCodeEmpty);}
306
308
310 static bool isTerminal(CodeElement c, bool extended = false) noexcept
311 { return(extended ? (c <= kCodeEmpty) : (c < kCodeEnd)); }
312
314
317 static void checkRule(const Rule & r);
318
320
324 static bool isRuleHeader(const Rule & r,
325 CodeElement left, CodeElement firstright);
326
328
330 static bool hasRuleFirstRight(const Rule & r,
331 CodeElement firstright);
332
340 CFGrammar(void) { clear(); }
341
342 CFGrammar(const CFGrammar &) = delete;
343 CFGrammar(CFGrammar &&) = delete;
344 CFGrammar & operator=(const CFGrammar &) = delete;
345 CFGrammar & operator=(CFGrammar &&) = delete;
346
348 virtual ~CFGrammar(void) = default;
349
357 size_t sizeTerminals(void) const noexcept
358 { return(static_cast<size_t>(kCodeEnd - lastterm_)); }
359
361 size_t sizeNonTerminals(void) const noexcept
362 { return(static_cast<size_t>(lastnonterm_ - kCodeEmpty)); }
363
365
367 { if (!isTerminal(c)) return(false); return(lastterm_ <= c); }
368
370
372 { if (!isNonTerminal(c)) return(false); return(lastnonterm_ >= c); }
373
375 size_t sizeTerminals(int cat) const
376 { if (!existsTerminalCategory(cat))
377 ELE_CODE_INVARG("Invalid category number");
378 return(catsterms_[cat].size()); }
379
381 size_t sizeNonTerminals(int cat) const
382 { if (!existsTerminalCategory(cat))
383 ELE_CODE_INVARG("Invalid category number");
384 return(catsnonterms_[cat].size()); }
385
387
389 bool existsTerminalCategory(int cat) const
390 { return(static_cast<VectorOfCats::size_type>(cat) <
391 catsterms_.size()); }
392
394
396 bool existsNonTerminalCategory(int cat) const
397 { return(static_cast<VectorOfCats::size_type>(cat) <
398 catsnonterms_.size()); }
399
401
403 bool existsTerminalCatID(const CatId & catid) const
404 { return(existsTerminalCategory(catid.first) &&
405 (static_cast<VectorOfCatIDs::size_type>(catid.second) <
406 catsterms_[catid.first].size())); }
407
409
411 bool existsNonTerminalCatID(const CatId & catid) const
412 { return(existsTerminalCategory(catid.first) &&
413 (static_cast<VectorOfCatIDs::size_type>(catid.second) <
414 catsnonterms_[catid.first].size())); }
415
417
418 CodeElement codeOfTerminal(const CatId & catid) const
419 { if (!existsTerminalCatID(catid))
421 return(catsterms_[catid.first][catid.second]); }
422
424
426 { if (!existsNonTerminalCatID(catid))
428 return(catsnonterms_[catid.first][catid.second]); }
429
431
433 { if (!existsTerminal(c))
435 return(CatId{linkstotermcats_[-c].first,linkstotermcats_[-c].second});}
436
438
440 { if (!existsNonTerminal(c))
442 return(CatId{linkstonontermcats_[c].first,
443 linkstonontermcats_[c].second});}
444
446
448 { if (!existsTerminal(c))
450 return(linkstotermcats_[-c].first); }
451
453
455 { if (!existsNonTerminal(c))
457 return(linkstonontermcats_[c].first); }
458
460
462 const RHSs & rightsOf(CodeElement n) const;
463
465
469
471
475 std::string nameOfTerminal(CodeElement c) const;
476
478
482 std::string nameOfNonTerminal(CodeElement c) const;
483
491 RuleIterator begin(void) const { return(RuleIterator{*this,true}); }
492
494 RuleIterator end(void) const { return(RuleIterator{*this,false}); }
495
497
499 { return(sizeNonTerminals() == 0 ?
502
504
506 { return(sizeTerminals() == 0 ?
509 lastnonterm_+1}); }
510
512
515 static_cast<int>(catsterms_.size())}); }
516
518
521 static_cast<int>(catsnonterms_.size())}); }
522
524
526 { if (!existsTerminalCategory(cat))
529 static_cast<int>(catsterms_[cat].size())}); }
530
532
534 { if (!existsNonTerminalCategory(cat))
537 static_cast<int>(catsnonterms_[cat].size())}); }
538
546
551 CodeElement findNonTerminal(const std::string & name) const;
552
554
559 CodeElement findTerminal(const std::string & name) const;
560
568 std::string to_string(const SetOfElements & soe) const;
569
571 std::string to_string(const MapOfElements & moe) const;
572
574 std::string to_string(const RHS & rhs) const;
575
577 std::string to_string(const Rule & r) const;
578
580 std::string to_string(const LL1Table t) const;
581
589 void clear(void);
590
592
594
596
600
602
607 void addRule(const Rule & r);
608
610
613 void assignName(CodeElement c, const std::string & name);
614
616
622
624
630
638
641 void checkIntegrity(bool withnames = true) const;
642
644
647
649
651 bool leftRecursive(CodeElement & rec) const;
652
654
658 void calculateFirsts(MapOfElements & firsts) const;
659
661
662 void firstOfRHS(const RHS & rhs, const MapOfElements & firsts,
663 SetOfElements & f) const;
664
666
672 void calculateFollows(const MapOfElements & firsts,
673 MapOfElements & follows,
674 std::string * trace = nullptr) const;
675
677
681 SetOfElements & nts) const;
682
684
700 const MapOfElements & follows,
701 MapOfElements & nts) const;
702
704
707 bool isLL1(const MapOfElements & firsts,
708 const MapOfElements & follows,
709 SetOfElements & fifi, MapOfElements & fifo) const;
710
712
719 void fillLL1Table(const MapOfElements & firsts,
720 const MapOfElements & follows,
721 LL1Table & table) const;
722
726 private:
727
728 using MapOfNames = std::map<std::string,CodeElement>;
729 using MapOfNamesSearchRes = std::pair< MapOfNames::iterator,bool >;
730 using MapOfNamesItem = std::pair<std::string,CodeElement>;
731
732 using VectorOfCatIDs = std::vector<int>;
733 using VectorOfCats = std::vector< VectorOfCatIDs >;
734 using CatAndID = std::pair<int,int>;
735 using VectorOfCatAndIDs = std::vector<CatAndID>;
736
737 CodeElement lastnonterm_, lastterm_;
738 MapOfRules rules_;
739
740 std::vector<const std::string *> linkstotermnames_, linkstonontermnames_;
741 // pointers without ownership, just to link inside "names_"
742 MapOfNames namesterms_,namesnonterms_;
743 // we use map instead of unordered_map for better efficiency in typical
744 // sizes of grammars (see https://stackoverflow.com/a/51961807 )
745
746 VectorOfCats catsterms_,catsnonterms_;
747 VectorOfCatAndIDs linkstotermcats_, linkstonontermcats_;
748
749 RHSs * findRules(CodeElement n);
750 bool exploreLeftRecursive(CodeElement n, SetOfElements & hist,
751 CodeElement & res, size_t depth) const;
752
753
754 // Static asserts at the end because a bug in doxygen that stops generating
755 // code when this is found.
756
757 static_assert(std::is_same<TokenId,CFGrammar::CodeElement>::value,
758 "CFGrammar::CodeElement must equal TokenId");
759};
760
761
762/* **********************************************************************
763
764 Class: Szer_CFGrammarSpec
765
766*************************************************************************/
767
769
817{
818 public:
819
824 {
825 InvElement(const std::string & details):
826 SzerError{"Invalid element" + details} {}
827
829 };
830
832 {
833 InvCatList(const std::string & details):
834 SzerError{"Invalid list of categorized elements"
835 + details} {}
836
838 };
839
841 {
842 Repeated(const std::string & details):
843 SzerError{"Repeated in the specification"
844 + details} {}
845
847 };
848
850 {
851 Unused(const std::string & details):
852 SzerError{"Unused in the specification"
853 + details} {}
854
856 };
857
859 {
860 Unexpected(const std::string & details):
861 SzerError{"Unexpected element" + details} {}
862
864 };
865
869 static const std::string kTermsSect;
870
872 static const std::string kNonTermsSect;
873
875 static const std::string kRulesSect;
876
878 static const std::string kOpenSect;
879
881 static const std::string kCloseSect;
882
884 static const std::string kOpenCat;
885
887 static const std::string kCloseCat;
888
890 static const std::string kSideSep;
891
893 static const std::string kRHSSep;
894
896 static const std::string kRuleEndMark;
897
898
900 void ser(elementa::base::OutSerCh & chout, const CFGrammar & cfg);
901
904
905 private:
906
907 ELE_CLASS_ENUM(Section,
908 kTerms, // begin in 0 according to the standard
909 kNonterms,
910 kRules);
911
912 Section whichSection(const std::string & token) const noexcept;
913 std::string concatLoc(const std::string & str) const;
914 void throwUnexpected(const std::string & whatexp,
915 const std::string & whatfound,
916 const std::string & place = "") const;
917
918 std::string locstr_;
919
920};
921
922
923 // CFGrammars
925
926} // End parsing namespace
927
928} // End elementa namespace
929
930
931#endif
932
An id of an element of the grammar divided into category and index.
Definition: cfgrammars.h:279
An index in a LL(1) parsing table: non-terminal + terminal.
Definition: cfgrammars.h:218
LL1TableIndex(LL1TableIndex &&oth)
Move constructor.
Definition: cfgrammars.h:231
LL1TableIndex & operator=(LL1TableIndex &&oth)
Move assignment.
Definition: cfgrammars.h:241
LL1TableIndex(const LL1TableIndex &oth)
Copy constructor.
Definition: cfgrammars.h:227
LL1TableIndex(CodeElement nt, CodeElement t)
Constructor for a valid index.
Definition: cfgrammars.h:248
LL1TableIndex & operator=(const LL1TableIndex &oth)
Assignment.
Definition: cfgrammars.h:235
LL1TableIndex(void)=default
Default constructor: invalid index.
An index of a rule in the grammar, i.e., an iterator on the rules.
Definition: cfgrammars.h:125
bool operator==(const RuleIterator &oth) const
Equality comparison.
RuleIterator operator--(int)
Point to the previous rule if it can (postfix).
RuleIterator operator++(int)
Point to the next rule if it can (postfix).
Rule operator*(void) const
De-referencing operator: return a copy of the given rule.
bool operator!=(const RuleIterator &oth) const
Inequality.
Definition: cfgrammars.h:203
std::bidirectional_iterator_tag Category
Category of the iterator (for STL-compatibility)
Definition: cfgrammars.h:129
RuleIterator & operator++(void)
Point to the next rule if it can (prefix).
std::ptrdiff_t Distance
Distance between iterators (for STL-compatibility)
Definition: cfgrammars.h:135
Rule T
Iterated data (for STL-compatibility)
Definition: cfgrammars.h:132
T * Pointer
Pointer to data (for STL-compatibility)
Definition: cfgrammars.h:138
RuleIterator & operator--(void)
Point to the previous rule if it can (prefix).
RuleIterator(const CFGrammar &gr, bool beginorend=true)
Constructor: an index pointing to the first or end rule in grammar.
T & Reference
Reference to data (for STL-compatibility)
Definition: cfgrammars.h:141
RuleIterator(void)
Default constructor: invalid iterator.
Definition: cfgrammars.h:145
CFGrammar(void)
Default constructor: empty grammar.
Definition: cfgrammars.h:340
elementa::base::IotaView< int > nonTerminalCatRange(void) const noexcept
Return an IotaView to iterate on the current non-terminal categories.
Definition: cfgrammars.h:519
std::string to_string(const Rule &r) const
Return a string with the given rule expressed with its names.
std::string to_string(const RHS &rhs) const
Return a string with the sequence of elements in the given rhs.
int catOfNonTerminal(CodeElement c) const
Return the category only corresponding to a given non-terminal element.
Definition: cfgrammars.h:454
static const std::string kEndName
A name for the "end of source" elem.
Definition: cfgrammars.h:295
std::string to_string(const SetOfElements &soe) const
Return a string with the given set of alements (their names).
elementa::base::IotaView< CodeElement > terminalRange(void) const noexcept
Return an IotaView to iterate on the current terminals.
Definition: cfgrammars.h:498
static const std::string kOpenCat
Keyword to open any category list.
Definition: cfgrammars.h:884
int catOfTerminal(CodeElement c) const
Return the category only corresponding to a given terminal element.
Definition: cfgrammars.h:447
CodeElement codeOfNonTerminal(const CatId &catid) const
Return the code corresponding to the given category/index of a non-term.
Definition: cfgrammars.h:425
RuleIterator end(void) const
Return an iterator past the last rule in the grammar.
Definition: cfgrammars.h:494
static void checkRule(const Rule &r)
Check that the rule R is well constructed for any possible grammar.
std::pair< CodeElement, RHS > Rule
A rule in the grammar (only one alternative for the left side).
Definition: cfgrammars.h:119
std::map< LL1TableIndex, RuleIterator > LL1Table
An LL(1) parsing table (sparse).
Definition: cfgrammars.h:287
void deser(elementa::base::InSerCh &chin, CFGrammar &cfg)
Deserialize.
CatId catidOfNonTerminal(CodeElement c) const
Return the catid corresponding to a given non-terminal element.
Definition: cfgrammars.h:439
static const std::string kRuleEndMark
Text ending mark of a rule in a default-serialized rule.
Definition: cfgrammars.h:896
std::vector< CodeElement > VectorOfElements
Vector of elements.
Definition: cfgrammars.h:106
bool existsTerminalCatID(const CatId &catid) const
Return FALSE if the given terminal cat/id does not exists in the gr.
Definition: cfgrammars.h:403
void calculateFirsts(MapOfElements &firsts) const
Fill FIRSTS with the first sets of all non-terminals in the grammar.
RuleIterator begin(void) const
Return an iterator to the first rule in the grammar.
Definition: cfgrammars.h:491
static bool isTerminal(CodeElement c, bool extended=false) noexcept
Return TRUE if C is a valid terminal code for any grammar.
Definition: cfgrammars.h:310
CodeElement addNonTerminal()
Register a new non-terminal.
void calculateFollows(const MapOfElements &firsts, MapOfElements &follows, std::string *trace=nullptr) const
Fill FOLLOWS with the follow sets of all non-terminals in the grammar.
void ser(elementa::base::OutSerCh &chout, const CFGrammar &cfg)
Serialize.
void fillLL1Table(const MapOfElements &firsts, const MapOfElements &follows, LL1Table &table) const
Try to fill TABLE with the parsing table of the grammar.
void checkIntegrity(bool withnames=true) const
Check that the content of the grammar is properly filled.
TokenId CodeElement
Unique code of an element of the grammar, either terminal or non-term.
Definition: cfgrammars.h:97
std::string to_string(const LL1Table t) const
Return a string representation of an LL(1) table.
static const std::string kNonTermsSect
Keyword to enter the non-terminals section.
Definition: cfgrammars.h:872
bool existsTerminal(CodeElement c) const
Return TRUE if the given code is of a registered terminal.
Definition: cfgrammars.h:366
CodeElement addTerminal()
Register a new termninal.
static const std::string kRHSSep
Text separator between alternatives in a default-serialized rule.
Definition: cfgrammars.h:893
static const CodeElement kCodeEmpty
Code of the "empty" element.
Definition: cfgrammars.h:289
size_t sizeNonTerminals(void) const noexcept
Return the number of non-terminals in the grammar.
Definition: cfgrammars.h:361
static bool hasRuleFirstRight(const Rule &r, CodeElement firstright)
Check whether the given rule has as first right-side element FIRSTRIGHT.
bool existsNonTerminal(CodeElement c) const
Return TRUE if the given code is of a registered non-terminal.
Definition: cfgrammars.h:371
static const std::string kOpenSect
Keyword to open any section.
Definition: cfgrammars.h:878
virtual ~CFGrammar(void)=default
Destructor.
static const std::string kRulesSect
Keyword to enter the rules section.
Definition: cfgrammars.h:875
CodeElement findNonTerminal(const std::string &name) const
Return the code for non-terminal called NAME,or kCodeEmpty if not found.
size_t sizeNonTerminals(int cat) const
Return the number of non-terminals in a category.
Definition: cfgrammars.h:381
CodeElement starting(void) const
Return the code for the non-terminal that is the starting symbol.
elementa::base::IotaView< int > terminalCatRange(void) const noexcept
Return an IotaView to iterate on the current terminal categories.
Definition: cfgrammars.h:513
static const std::string kTermsSect
Keyword to enter the terminals section.
Definition: cfgrammars.h:869
elementa::base::IotaView< int > terminalCatIDRange(int cat) const
Return an IotaView to iterate on the current ids of a terminal category.
Definition: cfgrammars.h:525
bool existsNonTerminalCategory(int cat) const
Return FALSE if the given non-terminal category does not exists in gr.
Definition: cfgrammars.h:396
static const std::string kSideSep
Text separator of left and right hand side in a default-serialized rule.
Definition: cfgrammars.h:890
size_t sizeTerminals(void) const noexcept
Return the number of terminals in the grammar.
Definition: cfgrammars.h:357
bool isLL1(const MapOfElements &firsts, const MapOfElements &follows, SetOfElements &fifi, MapOfElements &fifo) const
Return TRUE if the grammar is LL(1).
int newNonTerminalCategory(void)
Create a new category where the next non-terminals will be placed.
VectorOfElements RHS
The right-hand side of a rule of the grammar.
Definition: cfgrammars.h:110
static const std::string kEmptyName
A name for the "empty" element.
Definition: cfgrammars.h:293
bool existsTerminalCategory(int cat) const
Return FALSE if the given terminal category does not exists in the gr.
Definition: cfgrammars.h:389
std::map< CodeElement, RHSs > MapOfRules
A mapping from left-side non-terminals to vectors of right sides.
Definition: cfgrammars.h:116
bool leftRecursive(CodeElement &rec) const
Check any left-recursivity, direct or not.
elementa::base::IotaView< int > nonTerminalCatIDRange(int cat) const
Return an IotaView to iterate on the current ids of a non-terminal cat.
Definition: cfgrammars.h:533
CatId catidOfTerminal(CodeElement c) const
Return the catid corresponding to a given terminal element.
Definition: cfgrammars.h:432
bool existsNonTerminalCatID(const CatId &catid) const
Return FALSE if the given non-terminal cat/id does not exists in gr.
Definition: cfgrammars.h:411
bool directlyLeftRecursive(Rule &r) const
Check direct left-recursivity in the grammar.
static const std::string kCloseSect
Keyword to close any section.
Definition: cfgrammars.h:881
static const CodeElement kCodeEnd
Code of the "end of source" el.
Definition: cfgrammars.h:291
void firstOfRHS(const RHS &rhs, const MapOfElements &firsts, SetOfElements &f) const
Fill F with the first set of the entire RHS, according to FIRSTS.
static bool isRuleHeader(const Rule &r, CodeElement left, CodeElement firstright)
Check whether R has LEFT at its left and FIRSTRIGHT at its first right.
CodeElement findTerminal(const std::string &name) const
Return the code for a terminal called NAME, or kCodeEmpty if not found.
CodeElement codeOfTerminal(const CatId &catid) const
Return the code corresponding to the given category and index of a term.
Definition: cfgrammars.h:418
static const std::string kCloseCat
Keyword to close any category list.
Definition: cfgrammars.h:887
std::map< CodeElement, SetOfElements > MapOfElements
Set of elements associated to another element.
Definition: cfgrammars.h:103
elementa::base::IotaView< CodeElement > nonTerminalRange(void) const noexcept
Return an IotaView to iterate on the current non-terminals.
Definition: cfgrammars.h:505
std::string nameOfTerminal(CodeElement c) const
Return a copy of the name associated to the terminal C.
int newTerminalCategory(void)
Create a new category where the next terminals will be placed.
std::string to_string(const MapOfElements &moe) const
Return a string with the given map of elements.
void firstFollowConflicts(const MapOfElements &firsts, const MapOfElements &follows, MapOfElements &nts) const
Fill in NTS with the terminals shared in firsts and follows of non-term.
void clear(void)
Delete all the current content of the grammar.
void assignName(CodeElement c, const std::string &name)
Assign a name to an element.
void firstFirstConflicts(const MapOfElements &firsts, SetOfElements &nts) const
Fill in NTS with the non-terminals that cause first-first conflicts.
std::string nameOfNonTerminal(CodeElement c) const
Return a copy of the name associated to the non-terminal C.
size_t sizeTerminals(int cat) const
Return the number of terminals in a category.
Definition: cfgrammars.h:375
std::vector< RHS > RHSs
A number of RHS (usually for the same left hand side non-terminal).
Definition: cfgrammars.h:113
void addRule(const Rule &r)
Add a new rule for a non-terminal.
std::set< CodeElement > SetOfElements
Set of elements.
Definition: cfgrammars.h:100
static bool isNonTerminal(CodeElement c) noexcept
Return TRUE if C is a valid non-terminal code for any grammar.
Definition: cfgrammars.h:304
const RHSs & rightsOf(CodeElement n) const
Return a reference to all the rules associated to a non-terminal N.
A context-free grammar.
Definition: cfgrammars.h:71
Serializations of CFGrammars specified in a certain textual language.
Definition: cfgrammars.h:817
#define ELE_CODE_TRACE_OFF
Place this inside local scope (e.g., routine) to deactivate traces there.
Definition: debugging.h:283
#define ELE_CODE_PLACE
Produces a std::string with the place of source where the macro is placed.
Definition: debugging.h:194
#define ELE_CLASS_ENUM(NameEnumClass,...)
Define an extended enum type.
Definition: enums.h:502
Base class for all errors / exceptions in Elementa. Just derive from it.
Definition: exceptions.h:113
Exception for indicating that some element has not been found in some place.
Definition: exceptions.h:250
#define ELE_CLASS_EXCOVERRIDE(C)
Shortening macro that must be used inside classes derived from Exc.
Definition: exceptions.h:64
#define ELE_CODE_INVARG(expl)
To throw an invalid-argument exception with an explanation.
Definition: exceptions.h:310
LongestUnsigned to_number(const void *p)
Convert a pointer address to a number.
A view that refers to a sequence of incrementable elements, bounded or not.
Definition: iterators.h:673
int TokenId
A unique identifier for a token.
Definition: lexer.h:135
std::istream InSerCh
"Base class" that represents any input serial channel in Elementa.
Definition: basics.h:334
std::ostream OutSerCh
"Base class" that represents any output serial channel in Elementa.
Definition: basics.h:247
Base abstract class / interface for any serializer.
Definition: serializers.h:189
Base class for all errors thrown by serializers.
Definition: serializers.h:83
#define ELE_CLASS_VALIDATABLE
Declare a class derived from Validatable.
Definition: validatable.h:82
Definition: cfgrammars.h:78