#pragma once #include "RegularExpression.h" #include "Strings.hpp" namespace tp { extern ModuleManifest gModuleTokenizer; template class Tokenizer { TransitionMatrix mTransitionMatrix; RegEx::CompileError mError; bool scanFailed() { return mTransitionMatrix.isTrapped(); } public: Tokenizer() { MODULE_SANITY_CHECK(gModuleTokenizer) } void build(const InitialierList>& rules) { NFA nfa; mError = RegEx::compile(nfa, rules); if (mError.isError()) { return; } DFA dfa(nfa); mTransitionMatrix.construct(dfa); } [[nodiscard]] bool isBuild() const { return !mError.isError(); } const RegEx::CompileError& getBuildError() { return mError; } void resetMatrix() { mTransitionMatrix.reset(); } tTokType advanceSymbol(tAlphabetType symbol) { return mTransitionMatrix.move(symbol); } tTokType advanceToken(const tAlphabetType* source, ualni source_len, ualni* token_len) { tTokType out = tNoTokVal; *token_len = 0; for (ualni idx = 0; idx < source_len; idx++) { out = advanceSymbol(source[idx]); if (out != tNoTokVal) { *token_len = idx; break; } } return out; } ~Tokenizer() = default; }; template class SimpleTokenizer { Tokenizer mTokenizer; const tAlphabetType* mSource = nullptr; ualni mLastTokLen = 0; ualni mSourceLen = 0; ualni mAdvancedOffset = 0; public: struct Cursor { const tAlphabetType* mSource = nullptr; ualni mAdvancedOffset = 0; const tAlphabetType* str() { return mSource + mAdvancedOffset; } }; SimpleTokenizer() = default; void build(const InitialierList>& rules) { mTokenizer.build(rules); } [[nodiscard]] bool isBuild() const { return mTokenizer.isBuild(); } const RegEx::CompileError& getBuildError() { return mTokenizer.getBuildError(); } void bindSource(const tAlphabetType* source) { mSource = source; while (mSource[mSourceLen]) mSourceLen++; mSourceLen++; } [[nodiscard]] bool isInputLeft() const { if (!mSource) { return false; } if (mSource[mAdvancedOffset] == 0) { return false; } return true; } Cursor getCursor() const { return { mSource, mAdvancedOffset }; } Cursor getCursorPrev() const { return { mSource, mAdvancedOffset - mLastTokLen }; } void setCursor(const Cursor& crs) { mAdvancedOffset = crs.mAdvancedOffset; mLastTokLen = 0; } tTokType readTok() { if (mSourceLen == mAdvancedOffset + 1) { return tSourceEndTokVal; } tTokType out = mTokenizer.advanceToken(mSource + mAdvancedOffset, mSourceLen - mAdvancedOffset, &mLastTokLen); mAdvancedOffset += mLastTokLen; return out; } tTokType lookupTok() { auto out = readTok(); discardTok(); return out; } void discardTok() { mTokenizer.resetMatrix(); mAdvancedOffset -= mLastTokLen; mLastTokLen = 0; } void skipTok() { readTok(); } void reset() { mAdvancedOffset = mLastTokLen = 0; mTokenizer.resetMatrix(); } [[nodiscard]] ualni lastTokLEn() const { return mLastTokLen; } String extractVal() { auto crs = getCursorPrev(); String out; out.resize(mLastTokLen); memCopy(out.write(), crs.str(), mLastTokLen); return out; } }; }