From db2cda790c564d4c554544a9741981252f06816d Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Fri, 1 Aug 2025 12:12:22 -0400 Subject: [PATCH] Factor out a single `consumeChar` function This and `peek` are the only functions that should call the low-level `peekChar` and `peekCharAhead` methods. --- src/asm/lexer.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index 50d2811a..151dcc9b 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -780,6 +780,20 @@ static void shiftChar() { } } +static bool consumeChar(int c) { + // This is meant to be called when the "extra" behavior of `peek()` is not wanted, + // e.g. painting the peeked-at character "blue". + if (lexerState->peekChar() != c) { + return false; + } + + // Increment `lexerState->expansionScanDistance` to prevent `shiftChar()` from calling + // `peek()` and to balance its decrement. + ++lexerState->expansionScanDistance; + shiftChar(); + return true; +} + static int bumpChar() { int c = peek(); if (c != EOF) { @@ -1214,15 +1228,9 @@ static std::shared_ptr readInterpolation(size_t depth) { FormatSpec fmt{}; for (;;) { - // If `lexerState->disableExpansions` is false, `peek()` will expand nested interpolations - // and recursively call `readInterpolation()`, which can cause stack overflow. - // `lexerState->peekChar()` lets `readInterpolation()` handle its own nested expansions, - // increasing `depth` each time. - if (lexerState->peekChar() == '{') { - // Increment `lexerState->expansionScanDistance` to prevent `shiftChar()` from calling - // `peek()` and to balance its decrement. - ++lexerState->expansionScanDistance; - shiftChar(); + // Use `consumeChar()` since `peek()` might expand nested interpolations and recursively + // call `readInterpolation()`, which can cause stack overflow. + if (consumeChar('{')) { if (std::shared_ptr str = readInterpolation(depth + 1); str) { beginExpansion(str, *str); } @@ -1428,17 +1436,13 @@ static void readString(std::string &str, bool rawString) { str += '"'; } shiftChar(); - // `peek()` would mark the third character here as "painted blue" whether or not it is a - // third quote, which would incorrectly prevent expansions right after an empty string "". - // `lexerState->peekChar()` avoids this, and is okay since expansions are disabled here. - if (lexerState->peekChar() != '"') { + // Use `consumeChar()` since `peek()` would mark the third character here as "painted blue" + // whether or not it is a third quote, which would incorrectly prevent expansions right + // after an empty string "". + if (!consumeChar('"')) { // "" is an empty string, skip the loop return; } - // Increment `lexerState->expansionScanDistance` to prevent `shiftChar()` from calling - // `peek()` and to balance its decrement. - ++lexerState->expansionScanDistance; - shiftChar(); // """ begins a multi-line string if (rawMode) { str += '"';