Elementa v8.0.0
Minimalistic library for any C++ application (C++11 and up)
Loading...
Searching...
No Matches
fsms.h
Go to the documentation of this file.
1
3#include "elementa/license.inc"
4#include "elementa/checks.inc"
5
6#ifndef ELEMENTA_ADTS_FSM_H
7#define ELEMENTA_ADTS_FSM_H
8
9/*
10#define ELE_PRE_TRACED
11#include "elementa/base/debugging.h"
12*/
13
14#include <memory>
15#include <type_traits>
16#include <cstring>
17#include <string>
18#include <vector>
19#include <list>
20#include <utility>
21#include <locale>
24
25
26namespace elementa
27{
28
29namespace adts
30{
31
51/* ***************************************************************************
52
53 Virtual base class: BaseFSM
54
55*******************************************************************************/
56
58
67{
68 public:
69
74 using Num = size_t;
75
83 virtual ~BaseFSM(void) = default;
84
92
96 virtual bool atEnd(void) const = 0;
97
99
103 virtual void reset(void) = 0;
104
106
107 void resetCheck(void)
108 { reset();
109 if (atEnd()) ELE_CODE_INVSTATE("FSM [" + to_string() +
110 "] at ending state right after reset, "
111 "before consuming anything"); }
112
114 virtual std::string to_string(void) const
115 {
116 return(std::string{"FSM ("} +
117 std::to_string(elementa::base::to_number(this)) +
118 "). atEnd: " + elementa::base::kYesNoCString(atEnd())); }
119
122};
123
124
125/* ***************************************************************************
126
127 Template virtual base class: FSM
128 Alias: BaseTextFSM
129
130*******************************************************************************/
131
133
136template <typename Obs = char>
137class FSM: public BaseFSM
138{
139 public:
140
142 using Ptr = std::shared_ptr<FSM>;
143
144
146
150 virtual bool consume(Obs o) = 0;
151
152 private:
153
154static_assert(std::is_scalar<Obs>::value, "Obs must be a scalar type in a FSM");
155};
156
157
159class BaseTextFSM: public FSM<>
160{
161 public:
162
164
167 BaseTextFSM(bool casesensitive = true): casesensitive_{casesensitive} {}
168
169
170 protected:
171
172 char caseChar(char c)
173 { return(casesensitive_ ? c : std::toupper(c,std::locale())); }
174
175 bool casesensitive_;
176};
177
178
179/* ===========================================================================
180
181 SOME COMMON FSMS
182
183============================================================================= */
184
185/* ***************************************************************************
186
187 Class: CharFSM
188
189*******************************************************************************/
190
192class CharFSM: public BaseTextFSM
193{
194 public:
195
197
198 CharFSM(char c):c_{c} { reset(); }
199
200 void reset(void) { end_ = false; }
201 bool atEnd(void) const { return(end_); }
202
203 bool consume(char o)
204 { if (o == c_) { end_ = true; return(true); } else return(false); }
205
207 char character(void) const noexcept { return(c_); }
208
209 std::string to_string(void) const
210 { return("Char" + BaseTextFSM::to_string()); }
211
212
213 private:
214
215 char c_;
216 bool end_;
217};
218
219
220/* ***************************************************************************
221
222 Class: SeparatorsFSM
223
224*******************************************************************************/
225
227
231{
232 public:
233
235
236 SeparatorsFSM(const std::string & seps = "\n\t \f\r\v\x00"):seps_{seps}
237 { reset(); }
238
239 void reset(void) { end_ = false; }
240 bool atEnd(void) const { return(end_); }
241
242 bool consume(char o)
243 { if (seps_.find_first_of(o) != std::string::npos)
244 { end_ = true; return(true); }
245 else return(false); }
246
248 const std::string & separators(void) const noexcept
249 { return(seps_); }
250
251 std::string to_string(void) const
252 { return("Separators" + BaseTextFSM::to_string()); }
253
254
255 private:
256
257 const std::string seps_;
258 bool end_;
259};
260
261
262/* ***************************************************************************
263
264 Class: IdentifierFSM
265
266*******************************************************************************/
267
269
276{
277 public:
278
280 IdentifierFSM(void) { reset(); }
281
282 bool atEnd(void) const { return(end_); }
283 bool consume(char o);
284 void reset(void) { init_ = true; end_ = false; }
285
286 std::string to_string(void) const
287 { return("Identifier" + BaseTextFSM::to_string()); }
288
289
290 private:
291
292 bool init_,end_;
293
294 static constexpr bool kIsDigit(char c)
295 { return((c >= '0')&&(c <= '9')); }
296
297 static constexpr bool kIsCharOfIdentifier(char c)
298 { return( (c=='_') ||
299 ( (c>='a') && (c<='z') ) ||
300 ( (c>='A') && (c<='Z') ) ); }
301
302};
303
304
305/* ***************************************************************************
306
307 Class: KeywordFSM
308
309*******************************************************************************/
310
312
317{
318 public:
319
321
322 KeywordFSM(const std::string & word, bool casesens = true);
323
324 KeywordFSM(const KeywordFSM & o):word_{nullptr} { copyFrom(o); }
325 KeywordFSM & operator=(const KeywordFSM & o)
326 { copyFrom(o); return(*this); }
327 KeywordFSM(KeywordFSM && o) = delete;
328 KeywordFSM & operator=(KeywordFSM && o) = delete;
329
331 ~KeywordFSM(void) { delete [] word_; }
332
334 std::string word(void) const { return(rdstr()); }
335
336 bool atEnd(void) const { return(rdpos() >= rdlen()); }
337 bool consume(char o)
338 { if ((rdpos() >= rdlen()) ||
339 (caseChar(o) != caseChar(rd()))) return(false);
340 inc(); return(true); }
341 void reset(void) { wrpos(0); }
342
343 std::string to_string(void) const
344 { return("Keyword[" + word() + "]" + BaseTextFSM::to_string()); }
345
346 private:
347
348 char * word_; // stores position, length and string
349
350 void copyFrom(const KeywordFSM & o);
351 size_t rdlen(void) const
352 { return(static_cast<size_t>(static_cast<uint8_t>(word_[1]))); }
353 uint8_t rdpos(void) const { return(static_cast<uint8_t>(word_[0])); }
354 void wrlen(size_t l) { word_[1] = static_cast<char>(l); }
355 void wrpos(uint8_t p) { word_[0] = static_cast<char>(p); }
356 void inc(void) { ++word_[0]; }
357 void wrstr(const std::string & s)
358 { if (!s.empty()) std::memcpy(word_+2,s.c_str(),s.size()); }
359 std::string rdstr(void) const
360 { return(rdlen() == 0 ? std::string{} : std::string{word_+2,rdlen()}); }
361 char rd(void) const { return(word_[rdpos()+2]); }
362};
363
364
365/* ***************************************************************************
366
367 Class: CommentsFSM
368
369*******************************************************************************/
370
372
376{
377 public:
378
380
382 CommentsFSM(const std::string & commstart = "/*",
383 const std::string & commend = "*/");
384
385 CommentsFSM(const CommentsFSM &) = delete;
386 CommentsFSM(CommentsFSM &&) = delete;
387 CommentsFSM & operator=(const CommentsFSM &) = delete;
388 CommentsFSM & operator=(CommentsFSM &&) = delete;
389
390 ~CommentsFSM(void) { delete cstart_; delete cend_; }
391
392 void reset(void) { st_ = State::kInit; cstart_->reset(); cend_->reset(); }
393 bool atEnd(void) const { return(st_ == State::kFinished); }
394
395 bool consume(char o);
396
398 std::string beginText(void) const
399 { return(cstart_->word()); }
400
402 std::string endText(void) const
403 { return(cend_->word()); }
404
405 std::string to_string(void) const
406 { return("Comments" + BaseTextFSM::to_string()); }
407
408
409 private:
410
411 enum State { kInit, kStart, kBody, kEnd, kFinished };
412
413 State st_;
414 KeywordFSM * cstart_, * cend_;
415};
416
417
418/* ***************************************************************************
419
420 Class: IntegerTextFSM
421
422*******************************************************************************/
423
425
430{
431 public:
432
435 kDec, // no preffix
436 kHex, // '0x' preffix
437 kOct, // '0' preffix
438 kBin); // '0b' preffix
439
441
443 IntegerTextFSM(Kind kind = Kind::kDec,
444 bool withsign = true):kind_{kind},withsign_{withsign}
445 { reset(); }
446
447 IntegerTextFSM(const IntegerTextFSM & o) { copyFrom(o); }
448 IntegerTextFSM(IntegerTextFSM && o) { copyFrom(o); }
449 IntegerTextFSM & operator=(const IntegerTextFSM & o)
450 { copyFrom(o); return(*this); }
451 IntegerTextFSM & operator=(IntegerTextFSM && o)
452 { copyFrom(o); return(*this); }
453
454 bool atEnd(void) const { return(atend_); }
455 bool consume(char o);
456 void reset(void);
457
458 std::string to_string(void) const
459 { return("IntegerText[" + KindEnum::IdName(kind_) +
460 (withsign_ ? ", with sign" : "") + "]" +
462
463 private:
464
465 enum :uint8_t { kStInit, kAfterSign };
466
467 Kind kind_;
468 bool withsign_,alreadysign_;
469 size_t len_;
470 uint8_t st_;
471 bool atend_;
472
473 void copyFrom(const IntegerTextFSM & o);
474 bool recognizeAfterSign(char c);
475};
476
477
478/* ***************************************************************************
479
480 Class: NumberTextFSM
481
482*******************************************************************************/
483
485
491{
492 public:
493
495 NumberTextFSM(void) { reset(); }
496
497 NumberTextFSM(const NumberTextFSM & o) { copyFrom(o); }
498 NumberTextFSM(NumberTextFSM && o) { copyFrom(o); }
499 NumberTextFSM & operator=(const NumberTextFSM & o)
500 { copyFrom(o); return(*this); }
501 NumberTextFSM & operator=(NumberTextFSM && o)
502 { copyFrom(o); return(*this); }
503
504 bool atEnd(void) const { return(atend_); }
505 bool consume(char o);
506 void reset(void);
507
508 std::string to_string(void) const
509 { return("NumberText" + BaseTextFSM::to_string()); }
510
511 private:
512
513 enum :uint8_t { kStInit, kStMantissa, kStMantissaDigit,
514 kStExponentInit, kStExponent };
515
516 uint8_t st_;
517 bool alreadysign_,alreadydot_;
518 bool atend_;
519
520 void copyFrom(const NumberTextFSM & o);
521};
522
523
524 // FSM
526
527
528} // end adts namespace
529
530} // end elementa namespace
531
532
533#endif
534
constexpr const char * kYesNoCString(bool b)
User-friendly yes/no output.
Definition: definitions.h:85
#define ELE_CODE_INVSTATE(expl)
To throw an invalid-state exception with an explanation.
Definition: exceptions.h:306
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:454
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
Definition: fsms.h:284
BaseTextFSM(bool casesensitive=true)
Constructor.
Definition: fsms.h:167
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
Definition: fsms.h:392
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:393
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:282
KeywordFSM(const std::string &word, bool casesens=true)
Constructor from the word. That word is copied inside.
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:336
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
Definition: fsms.h:200
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:508
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:286
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
virtual std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:114
std::string endText(void) const
Return the end text for comments.
Definition: fsms.h:402
ELE_CLASS_ENUM(Kind, kDec, kHex, kOct, kBin)
Kinds of number that can be recognized.
~KeywordFSM(void)
Destructor.
Definition: fsms.h:331
std::string beginText(void) const
Return the start text for comments.
Definition: fsms.h:398
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:209
std::string word(void) const
Getter for the word.
Definition: fsms.h:334
char character(void) const noexcept
Return the character this fsm is able to recognize.
Definition: fsms.h:207
void resetCheck(void)
Reset checking the post-condition that the FSM does not go to an ending.
Definition: fsms.h:107
size_t Num
To represent a number of FSMs.
Definition: fsms.h:74
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:251
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:458
IdentifierFSM(void)
Constructor. *‍/.
Definition: fsms.h:280
CharFSM(char c)
Constructor.
Definition: fsms.h:198
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
virtual ~BaseFSM(void)=default
Just for polymorphic deletions.
IntegerTextFSM(Kind kind=Kind::kDec, bool withsign=true)
Constructor.
Definition: fsms.h:443
SeparatorsFSM(const std::string &seps="\n\t \f\r\v\x00")
Constructor.
Definition: fsms.h:236
virtual bool atEnd(void) const =0
Must return TRUE if the current state is an absorbing/final one.
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:240
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:343
const std::string & separators(void) const noexcept
Return a reference to the separators this fsm is able to recognize.
Definition: fsms.h:248
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:201
NumberTextFSM(void)
Constructor.
Definition: fsms.h:495
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
Definition: fsms.h:239
CommentsFSM(const std::string &commstart="/*", const std::string &commend="*/")
Constructor.
std::shared_ptr< FSM > Ptr
Pointer to a FSM that consumes observations of type Obs.
Definition: fsms.h:142
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
Definition: fsms.h:504
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
Definition: fsms.h:341
virtual void reset(void)=0
Must set the FSM to a preliminary state when it has not been fed yet.
virtual bool consume(Obs o)=0
Must consume the given observation and change state if necessary.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
Definition: fsms.h:405
Common functionality for any FSM.
Definition: fsms.h:67
Shortcut for FSMs that work with chars.
Definition: fsms.h:160
A FSM that recognizes only a given character.
Definition: fsms.h:193
A FSM that recognizes uni- or multi-line comments.
Definition: fsms.h:376
Base interface for FSMs with a given observation type.
Definition: fsms.h:138
A FSM that recognizes a standard identifier in text.
Definition: fsms.h:276
A FSM that recognizes an integer number from text.
Definition: fsms.h:430
A FSM that recognizes some fixed, short (shorter than 255 chars) string.
Definition: fsms.h:317
A FSM that recognizes a real or integer number from a decimal text.
Definition: fsms.h:491
A FSM that recognizes sequences of separator characters.
Definition: fsms.h:231
LongestUnsigned to_number(const void *p)
Convert a pointer address to a number.