Last active
October 12, 2018 11:32
-
-
Save matovitch/625b0a9776917ddb164c723ffe5dbb2e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://coliru.stacked-crooked.com/a/a138703355819566 | |
#include <string_view> | |
#include <iostream> | |
#include <cstdint> | |
template <uint8_t low, | |
uint8_t high> | |
struct TIsBetween | |
{ | |
bool operator()(const uint8_t byte) const | |
{ | |
return byte >= low && | |
byte <= high; | |
} | |
}; | |
template <uint8_t... bytes> | |
struct TIsIn | |
{ | |
bool operator()(const uint8_t byte) const | |
{ | |
const auto compare = [byte](const uint8_t test) { return byte == test; }; | |
return (compare(bytes) || ...); | |
} | |
}; | |
template <uint8_t byte> | |
using TIs = TIsIn<byte>; | |
using isDigit = TIsBetween<'0', '9'>; | |
using isDigitExceptZero = TIsBetween<'1', '9'>; | |
using isExponent = TIsIn<'e', 'E'>; | |
using isPlusOrMinus = TIsIn<'+', '-'>; | |
using isDot = TIs<'.'>; | |
enum Token | |
{ | |
UNKNOWN, | |
INT, | |
FLOAT | |
}; | |
static const char* TOKEN_AS_CSTR[] = | |
{ | |
"UNKNOWN", | |
"INT", | |
"FLOAT" | |
}; | |
class Reader | |
{ | |
public: | |
Reader(const std::string_view stringToRead) : | |
_head{reinterpret_cast<const uint8_t*>(stringToRead.data())}, | |
_tail{_head + stringToRead.size()} | |
{} | |
operator bool() const | |
{ | |
return _head < _tail; | |
} | |
uint8_t operator*() const | |
{ | |
return *_head; | |
} | |
void operator++() | |
{ | |
_head++; | |
} | |
private: | |
const uint8_t* _head; | |
const uint8_t* const _tail; | |
}; | |
template <class GotoPredicate, int GOTO_NEXT_STATE_INDEX> | |
struct TGoto | |
{ | |
using Predicate = GotoPredicate; | |
static constexpr int NEXT_STATE_INDEX = GOTO_NEXT_STATE_INDEX; | |
}; | |
template <int MATCH, class... GotosOrMatch> | |
struct TState; | |
template <int INDEX> | |
struct TStateIndex; | |
template <> | |
struct TStateIndex<1> | |
{ | |
using Type = TState | |
< | |
UNKNOWN, | |
TGoto<isDigitExceptZero , 2>, | |
TGoto<isPlusOrMinus , 3>, | |
TGoto<isDot , 4> | |
>; | |
}; | |
template <> | |
struct TStateIndex<2> | |
{ | |
using Type = TState | |
< | |
INT, | |
TGoto<isDigit , 2>, | |
TGoto<isDot , 5> | |
>; | |
}; | |
template <> | |
struct TStateIndex<3> | |
{ | |
using Type = TState | |
< | |
UNKNOWN, | |
TGoto<isDigitExceptZero , 2>, | |
TGoto<isDot , 4> | |
>; | |
}; | |
template <> | |
struct TStateIndex<4> | |
{ | |
using Type = TState | |
< | |
UNKNOWN, | |
TGoto<isDigit , 5> | |
>; | |
}; | |
template <> | |
struct TStateIndex<5> | |
{ | |
using Type = TState | |
< | |
FLOAT, | |
TGoto<isDigit , 5>, | |
TGoto<isExponent , 6> | |
>; | |
}; | |
template <> | |
struct TStateIndex<6> | |
{ | |
using Type = TState | |
< | |
UNKNOWN, | |
TGoto<isPlusOrMinus , 7>, | |
TGoto<isDigit , 8> | |
>; | |
}; | |
template <> | |
struct TStateIndex<7> | |
{ | |
using Type = TState | |
< | |
UNKNOWN, | |
TGoto<isDigit, 8> | |
>; | |
}; | |
template <> | |
struct TStateIndex<8> | |
{ | |
using Type = TState | |
< | |
FLOAT, | |
TGoto<isDigit, 8> | |
>; | |
}; | |
template <int INDEX> | |
using TGetState = typename TStateIndex<INDEX>::Type; | |
template <int STATE_INDEX> | |
void tGotoState(Reader& reader) | |
{ | |
TGetState<STATE_INDEX>{}(reader); | |
} | |
template <int MATCH> | |
struct TState<MATCH> | |
{ | |
void operator()(Reader& reader) const | |
{ | |
if constexpr (MATCH == UNKNOWN) | |
{ | |
++reader; | |
} | |
std::cout << "Matched: " << TOKEN_AS_CSTR[MATCH] << std::endl; | |
tGotoState<1>(reader); | |
} | |
}; | |
template <int MATCH, class Goto, class... Gotos> | |
struct TState<MATCH, Goto, Gotos...> | |
{ | |
using Predicate = typename Goto::Predicate; | |
static constexpr int NEXT_STATE_INDEX = Goto::NEXT_STATE_INDEX; | |
void operator()(Reader& reader) const | |
{ | |
if (!reader) | |
{ | |
return; | |
} | |
if (!Predicate{}(*reader)) | |
{ | |
return TState<MATCH, Gotos...>{}(reader); | |
} | |
++reader; | |
tGotoState<NEXT_STATE_INDEX>(reader); | |
} | |
}; | |
void runMachine(const std::string_view stringToLex) | |
{ | |
Reader reader{stringToLex}; | |
tGotoState<1>(reader); | |
} | |
int main() | |
{ | |
runMachine("52 -22 +1 -.2 2.37e-05 "); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment