Split the .peek() method into its next-char and lookahead cases

This commit is contained in:
Rangi42
2024-03-28 15:00:29 -04:00
parent 6f74e4fb9c
commit 106e516962
2 changed files with 33 additions and 7 deletions

View File

@@ -100,7 +100,8 @@ struct LexerState {
~LexerState(); ~LexerState();
int peek(uint8_t distance); int peekChar();
int peekCharAhead();
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

@@ -687,13 +687,37 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
} }
} }
int LexerState::peek(uint8_t distance) { int LexerState::peekChar() {
// This is `.peekCharAhead()` modified for zero lookahead distance
for (Expansion &exp : expansions) {
if (exp.offset < exp.size())
return (uint8_t)(*exp.contents)[exp.offset];
}
if (auto *view = std::get_if<ViewedContent>(&content); view) {
if (view->offset < view->span.size)
return (uint8_t)view->span.ptr[view->offset];
} else {
assert(std::holds_alternative<BufferedContent>(content));
auto &cbuf = std::get<BufferedContent>(content);
if (cbuf.size == 0)
cbuf.refill();
assert(cbuf.offset < LEXER_BUF_SIZE);
if (cbuf.size > 0)
return (uint8_t)cbuf.buf[cbuf.offset];
}
// If there aren't enough chars, give up
return EOF;
}
int LexerState::peekCharAhead() {
// We only need one character of lookahead, for macro arguments // We only need one character of lookahead, for macro arguments
assert(distance == 0 || distance == 1); uint8_t distance = 1;
for (Expansion &exp : expansions) { 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 `.peek()` will continue with its parent // and `.peekCharAhead()` will continue with its parent
assert(exp.offset <= exp.size()); assert(exp.offset <= exp.size());
if (exp.offset + distance < exp.size()) if (exp.offset + distance < exp.size())
return (uint8_t)(*exp.contents)[exp.offset + distance]; return (uint8_t)(*exp.contents)[exp.offset + distance];
@@ -708,10 +732,11 @@ int LexerState::peek(uint8_t distance) {
auto &cbuf = std::get<BufferedContent>(content); auto &cbuf = std::get<BufferedContent>(content);
assert(distance < LEXER_BUF_SIZE); assert(distance < LEXER_BUF_SIZE);
if (cbuf.size <= distance) if (cbuf.size <= distance)
cbuf.refill(); // Buffer isn't full enough, read some chars in cbuf.refill();
if (cbuf.size > distance) if (cbuf.size > distance)
return (uint8_t)cbuf.buf[(cbuf.offset + distance) % LEXER_BUF_SIZE]; return (uint8_t)cbuf.buf[(cbuf.offset + distance) % LEXER_BUF_SIZE];
} }
// If there aren't enough chars, give up // If there aren't enough chars, give up
return EOF; return EOF;
} }
@@ -721,7 +746,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 = lexerState->peek(0); int c = lexerState->peekChar();
if (lexerState->macroArgScanDistance > 0) if (lexerState->macroArgScanDistance > 0)
return c; return c;
@@ -731,7 +756,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 = lexerState->peek(1); c = lexerState->peekCharAhead();
if (isMacroChar(c)) { if (isMacroChar(c)) {
shiftChar(); shiftChar();
shiftChar(); shiftChar();