Refactor peekInternal to be a LexerState method

This commit is contained in:
Rangi42
2024-03-28 13:19:02 -04:00
parent 4172d330b9
commit 83c0634f15
2 changed files with 20 additions and 19 deletions

View File

@@ -14,7 +14,7 @@
#include "platform.hpp" // SSIZE_MAX #include "platform.hpp" // SSIZE_MAX
#define LEXER_BUF_SIZE 128 #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"); 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 // 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"); 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; } bool canPeek(uint8_t distance) const { return offset + distance < span.size; }
uint8_t peek(uint8_t distance) const { return span.ptr[offset + distance]; } uint8_t peek(uint8_t distance) const { return span.ptr[offset + distance]; }
std::shared_ptr<char[]> makeSharedContentPtr() const { std::shared_ptr<char[]> makeSharedContentPtr() const {
return std::shared_ptr<char[]>(span.ptr, &span.ptr[offset]); return std::shared_ptr<char[]>(span.ptr, &span.ptr[offset]);
} }
@@ -106,6 +107,8 @@ struct LexerState {
~LexerState(); ~LexerState();
int peek(uint8_t distance);
std::shared_ptr<char[]> makeSharedCaptureBufPtr() const { std::shared_ptr<char[]> makeSharedCaptureBufPtr() const {
return std::shared_ptr<char[]>(captureBuf, captureBuf->data()); return std::shared_ptr<char[]>(captureBuf, captureBuf->data());
} }

View File

@@ -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_) { 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<ViewedContent>(span); content.emplace<ViewedContent>(span);
clear(lineNo_); clear(lineNo_);
lexerStateEOL = this; lexerStateEOL = this;
@@ -687,35 +687,33 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
} }
} }
// We only need one character of lookahead, for macro arguments int LexerState::peek(uint8_t distance) {
static int peekInternal(uint8_t distance) { // We only need one character of lookahead, for macro arguments
for (Expansion &exp : lexerState->expansions) { assert(distance == 0 || distance == 1);
for (Expansion &exp : expansions) {
// An expansion that has reached its end will have `exp->offset` == `exp->size()`, // 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()); assert(exp.offset <= exp.size());
if (exp.canPeek(distance)) if (exp.canPeek(distance))
return exp.peek(distance); return exp.peek(distance);
distance -= exp.size() - exp.offset; distance -= exp.size() - exp.offset;
} }
if (auto *view = std::get_if<ViewedContent>(&lexerState->content); view) { if (auto *view = std::get_if<ViewedContent>(&content); view) {
if (view->canPeek(distance)) if (view->canPeek(distance))
return view->peek(distance); return view->peek(distance);
return EOF;
} else { } else {
assert(std::holds_alternative<BufferedContent>(lexerState->content)); assert(std::holds_alternative<BufferedContent>(content));
auto &cbuf = std::get<BufferedContent>(lexerState->content); auto &cbuf = std::get<BufferedContent>(content);
assert(distance < LEXER_BUF_SIZE); assert(distance < LEXER_BUF_SIZE);
if (!cbuf.canPeek(distance))
cbuf.refill(); // Buffer isn't full enough, read some chars in
if (cbuf.canPeek(distance)) if (cbuf.canPeek(distance))
return cbuf.peek(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 // forward declarations for peek
@@ -723,7 +721,7 @@ static void shiftChar();
static std::shared_ptr<std::string> readInterpolation(size_t depth); static std::shared_ptr<std::string> readInterpolation(size_t depth);
static int peek() { static int peek() {
int c = peekInternal(0); int c = lexerState->peek(0);
if (lexerState->macroArgScanDistance > 0) if (lexerState->macroArgScanDistance > 0)
return c; return c;
@@ -733,7 +731,7 @@ static int peek() {
if (c == '\\' && !lexerState->disableMacroArgs) { if (c == '\\' && !lexerState->disableMacroArgs) {
// If character is a backslash, check for a macro arg // If character is a backslash, check for a macro arg
lexerState->macroArgScanDistance++; lexerState->macroArgScanDistance++;
c = peekInternal(1); c = lexerState->peek(1);
if (isMacroChar(c)) { if (isMacroChar(c)) {
shiftChar(); shiftChar();
shiftChar(); shiftChar();