3#include "elementa/license.inc"
4#include "elementa/checks.inc"
6#ifndef ELEMENTA_ADTS_FSM_H
7#define ELEMENTA_ADTS_FSM_H
96 virtual bool atEnd(
void)
const = 0;
110 "] at ending state right after reset, "
111 "before consuming anything"); }
116 return(std::string{
"FSM ("} +
136template <
typename Obs =
char>
142 using Ptr = std::shared_ptr<FSM>;
154static_assert(std::is_scalar<Obs>::value,
"Obs must be a scalar type in a FSM");
167 BaseTextFSM(
bool casesensitive =
true): casesensitive_{casesensitive} {}
172 char caseChar(
char c)
173 {
return(casesensitive_ ? c : std::toupper(c,std::locale())); }
201 bool atEnd(
void)
const {
return(end_); }
204 {
if (o == c_) { end_ =
true;
return(
true); }
else return(
false); }
240 bool atEnd(
void)
const {
return(end_); }
243 {
if (seps_.find_first_of(o) != std::string::npos)
244 { end_ =
true;
return(
true); }
245 else return(
false); }
257 const std::string seps_;
282 bool atEnd(
void)
const {
return(end_); }
283 bool consume(
char o);
284 void reset(
void) { init_ =
true; end_ =
false; }
294 static constexpr bool kIsDigit(
char c)
295 {
return((c >=
'0')&&(c <=
'9')); }
297 static constexpr bool kIsCharOfIdentifier(
char c)
298 {
return( (c==
'_') ||
299 ( (c>=
'a') && (c<=
'z') ) ||
300 ( (c>=
'A') && (c<=
'Z') ) ); }
326 { copyFrom(o);
return(*
this); }
327 KeywordFSM(KeywordFSM && o) =
delete;
328 KeywordFSM & operator=(KeywordFSM && o) =
delete;
334 std::string
word(
void)
const {
return(rdstr()); }
336 bool atEnd(
void)
const {
return(rdpos() >= rdlen()); }
338 {
if ((rdpos() >= rdlen()) ||
339 (caseChar(o) != caseChar(rd())))
return(
false);
340 inc();
return(
true); }
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]); }
383 const std::string & commend =
"*/");
392 void reset(
void) { st_ = State::kInit; cstart_->reset(); cend_->reset(); }
393 bool atEnd(
void)
const {
return(st_ == State::kFinished); }
395 bool consume(
char o);
399 {
return(cstart_->word()); }
403 {
return(cend_->word()); }
411 enum State { kInit, kStart, kBody, kEnd, kFinished };
414 KeywordFSM * cstart_, * cend_;
444 bool withsign =
true):kind_{kind},withsign_{withsign}
448 IntegerTextFSM(IntegerTextFSM && o) { copyFrom(o); }
449 IntegerTextFSM & operator=(
const IntegerTextFSM & o)
450 { copyFrom(o);
return(*
this); }
452 { copyFrom(o);
return(*
this); }
454 bool atEnd(
void)
const {
return(atend_); }
455 bool consume(
char o);
459 {
return(
"IntegerText[" + KindEnum::IdName(kind_) +
460 (withsign_ ?
", with sign" :
"") +
"]" +
465 enum :uint8_t { kStInit, kAfterSign };
468 bool withsign_,alreadysign_;
473 void copyFrom(
const IntegerTextFSM & o);
474 bool recognizeAfterSign(
char c);
500 { copyFrom(o);
return(*
this); }
502 { copyFrom(o);
return(*
this); }
504 bool atEnd(
void)
const {
return(atend_); }
505 bool consume(
char o);
513 enum :uint8_t { kStInit, kStMantissa, kStMantissaDigit,
514 kStExponentInit, kStExponent };
517 bool alreadysign_,alreadydot_;
constexpr const char * kYesNoCString(bool b)
User-friendly yes/no output.
#define ELE_CODE_INVSTATE(expl)
To throw an invalid-state exception with an explanation.
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
BaseTextFSM(bool casesensitive=true)
Constructor.
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
bool atEnd(void) const
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.
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.
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
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.
std::string endText(void) const
Return the end text for comments.
ELE_CLASS_ENUM(Kind, kDec, kHex, kOct, kBin)
Kinds of number that can be recognized.
~KeywordFSM(void)
Destructor.
std::string beginText(void) const
Return the start text for comments.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
std::string word(void) const
Getter for the word.
char character(void) const noexcept
Return the character this fsm is able to recognize.
void resetCheck(void)
Reset checking the post-condition that the FSM does not go to an ending.
size_t Num
To represent a number of FSMs.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
IdentifierFSM(void)
Constructor. */.
CharFSM(char c)
Constructor.
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.
SeparatorsFSM(const std::string &seps="\n\t \f\r\v\x00")
Constructor.
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.
std::string to_string(void) const
Return a text representation of the FSM. Can be overriden.
const std::string & separators(void) const noexcept
Return a reference to the separators this fsm is able to recognize.
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
NumberTextFSM(void)
Constructor.
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
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.
bool atEnd(void) const
Must return TRUE if the current state is an absorbing/final one.
void reset(void)
Must set the FSM to a preliminary state when it has not been fed yet.
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.
Common functionality for any FSM.
Shortcut for FSMs that work with chars.
A FSM that recognizes only a given character.
Base interface for FSMs with a given observation type.
A FSM that recognizes a standard identifier in text.
A FSM that recognizes an integer number from text.
A FSM that recognizes some fixed, short (shorter than 255 chars) string.
A FSM that recognizes a real or integer number from a decimal text.
A FSM that recognizes sequences of separator characters.
LongestUnsigned to_number(const void *p)
Convert a pointer address to a number.