diff --git a/include/asm/lexer.hpp b/include/asm/lexer.hpp index 899453d0..38e6e168 100644 --- a/include/asm/lexer.hpp +++ b/include/asm/lexer.hpp @@ -14,7 +14,7 @@ #include "platform.hpp" // SSIZE_MAX #define LEXER_BUF_SIZE 128 -// The buffer needs to be large enough for the maximum `peekInternal` lookahead distance +// The buffer needs to be large enough for the maximum `lexerState->peek()` lookahead distance static_assert(LEXER_BUF_SIZE > 1, "Lexer buffer size is too small"); // This caps the size of buffer reads, and according to POSIX, passing more than SSIZE_MAX is UB static_assert(LEXER_BUF_SIZE <= SSIZE_MAX, "Lexer buffer size is too large"); @@ -53,6 +53,7 @@ struct ViewedContent { bool canPeek(uint8_t distance) const { return offset + distance < span.size; } uint8_t peek(uint8_t distance) const { return span.ptr[offset + distance]; } + std::shared_ptr makeSharedContentPtr() const { return std::shared_ptr(span.ptr, &span.ptr[offset]); } @@ -106,6 +107,8 @@ struct LexerState { ~LexerState(); + int peek(uint8_t distance); + std::shared_ptr makeSharedCaptureBufPtr() const { return std::shared_ptr(captureBuf, captureBuf->data()); } diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index 03581060..8e853716 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -455,7 +455,7 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat } void LexerState::setViewAsNextState(char const *name, ContentSpan const &span, uint32_t lineNo_) { - path = name; // Used to report read errors in `peekInternal` + path = name; // Used to report read errors in `.peek()` content.emplace(span); clear(lineNo_); lexerStateEOL = this; @@ -687,35 +687,33 @@ static std::shared_ptr readMacroArg(char name) { } } -// We only need one character of lookahead, for macro arguments -static int peekInternal(uint8_t distance) { - for (Expansion &exp : lexerState->expansions) { +int LexerState::peek(uint8_t distance) { + // We only need one character of lookahead, for macro arguments + assert(distance == 0 || distance == 1); + + for (Expansion &exp : expansions) { // An expansion that has reached its end will have `exp->offset` == `exp->size()`, - // and `peekInternal` will continue with its parent + // and `.peek()` will continue with its parent assert(exp.offset <= exp.size()); if (exp.canPeek(distance)) return exp.peek(distance); distance -= exp.size() - exp.offset; } - if (auto *view = std::get_if(&lexerState->content); view) { + if (auto *view = std::get_if(&content); view) { if (view->canPeek(distance)) return view->peek(distance); - return EOF; } else { - assert(std::holds_alternative(lexerState->content)); - auto &cbuf = std::get(lexerState->content); - + assert(std::holds_alternative(content)); + auto &cbuf = std::get(content); assert(distance < LEXER_BUF_SIZE); + if (!cbuf.canPeek(distance)) + cbuf.refill(); // Buffer isn't full enough, read some chars in if (cbuf.canPeek(distance)) return cbuf.peek(distance); - // Buffer isn't full enough, read some chars in - cbuf.refill(); - if (cbuf.canPeek(distance)) - return cbuf.peek(distance); - // If there aren't enough chars even after refilling, give up - return EOF; } + // If there aren't enough chars, give up + return EOF; } // forward declarations for peek @@ -723,7 +721,7 @@ static void shiftChar(); static std::shared_ptr readInterpolation(size_t depth); static int peek() { - int c = peekInternal(0); + int c = lexerState->peek(0); if (lexerState->macroArgScanDistance > 0) return c; @@ -733,7 +731,7 @@ static int peek() { if (c == '\\' && !lexerState->disableMacroArgs) { // If character is a backslash, check for a macro arg lexerState->macroArgScanDistance++; - c = peekInternal(1); + c = lexerState->peek(1); if (isMacroChar(c)) { shiftChar(); shiftChar();