From 075f132d77b23d07ce66e0e5ad7ac1bf45e60d00 Mon Sep 17 00:00:00 2001 From: Rangi Date: Wed, 27 May 2026 19:44:30 -0400 Subject: [PATCH] Use a smaller `unordered_map` just for looking up line-leading keywords --- src/asm/lexer.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index a0a125b1..f744c59e 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -2058,6 +2058,22 @@ finish: // Can't `break` out of a nested `for`-`switch` return Token(T_(YYEOF)); } +// This map lists all RGBASM keywords which `skipToLeadingKeyword` needs to recognize. +// It is a subset of `keywords`. +static UpperMap const leadingKeywords{ + // There is no need to recognize "MACRO", since macros cannot be nested + {"ENDM", T_(POP_ENDM)}, + + {"REPT", T_(POP_REPT)}, + {"FOR", T_(POP_FOR) }, + {"ENDR", T_(POP_ENDR)}, + + {"IF", T_(POP_IF) }, + {"ELSE", T_(POP_ELSE)}, + {"ELIF", T_(POP_ELIF)}, + {"ENDC", T_(POP_ENDC)}, +}; + static Token skipToLeadingKeywordFast(Procedure<> auto shiftFast) { // This is essentially `skipToLeadingKeyword` with `peek` and `shiftChar` replaced, // as well as anything that calls them like `nextChar` or `handleCRLF`. @@ -2082,7 +2098,7 @@ static Token skipToLeadingKeywordFast(Procedure<> auto shiftFast) { shiftFast(); } std::string_view leading{ptr + start, ptr + lexerState->offset}; - if (auto search = keywords.find(leading); search != keywords.end()) { + if (auto search = leadingKeywords.find(leading); search != leadingKeywords.end()) { // When this branch returns a token, there has been one more call to `peekFast` // than to `shiftFast`. Unlike `peek` and `shiftChar`, the optimized functions // do not update `lexerState->expansionScanDistance`, so it must be incremented @@ -2113,9 +2129,6 @@ static Token skipToLeadingKeywordFast(Procedure<> auto shiftFast) { // valid at the start of their lines, which enables ignoring everything except // the leading keyword in lines that have one (as well as line continuations). // -// The only keywords it needs to recognize are case-insensitive `IF`, `ELIF`, -// `ELSE`, `ENDC`, `REPT`, `FOR`, `ENDR`, and `ENDM` (not `MACRO`). -// // Note that when these constructs are *evaluated*, they can perform expansions // (for macro args, interpolations, and macro invocations) which may produce // tokens that would change how these constructs were captured or skipped, if @@ -2149,7 +2162,7 @@ static Token skipToLeadingKeyword() { for (c = nextChar(); continuesIdentifier(c); c = nextChar()) { builder += c; } - if (auto search = keywords.find(builder); search != keywords.end()) { + if (auto search = leadingKeywords.find(builder); search != leadingKeywords.end()) { return Token(search->second); } }