diff --git a/include/asm/lexer.hpp b/include/asm/lexer.hpp index ebfa81c0..f97a8135 100644 --- a/include/asm/lexer.hpp +++ b/include/asm/lexer.hpp @@ -134,13 +134,16 @@ struct CaptureBody { uint32_t lineNo; char const *body; size_t size; + + void startCapture(); + void endCapture(); }; void lexer_CheckRecursionDepth(); uint32_t lexer_GetLineNo(); uint32_t lexer_GetColNo(); void lexer_DumpStringExpansions(); -bool lexer_CaptureRept(CaptureBody &capture); -bool lexer_CaptureMacroBody(CaptureBody &capture); +CaptureBody lexer_CaptureRept(); +CaptureBody lexer_CaptureMacroBody(); #endif // RGBDS_ASM_LEXER_H diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index 357f012a..cf2437f3 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -2193,22 +2193,27 @@ yy::parser::symbol_type yylex() { } } -static void startCapture(CaptureBody &capture) { +void CaptureBody::startCapture() { + // Due to parser internals, it reads the EOL after the expression before calling this. + // Thus, we don't need to keep one in the buffer afterwards. + // The following assertion checks that. + assert(lexerState->atLineStart); + assert(!lexerState->capturing); lexerState->capturing = true; lexerState->captureSize = 0; lexerState->disableMacroArgs = true; lexerState->disableInterpolation = true; - capture.lineNo = lexer_GetLineNo(); + lineNo = lexer_GetLineNo(); if (auto *mmap = std::get_if(&lexerState->content); mmap && lexerState->expansions.empty()) { - capture.body = &mmap->ptr[mmap->offset]; + body = &mmap->ptr[mmap->offset]; } else if (auto *view = std::get_if(&lexerState->content); view && lexerState->expansions.empty()) { - capture.body = &view->ptr[view->offset]; + body = &view->ptr[view->offset]; } else { - capture.body = nullptr; // Indicates to retrieve the capture buffer when done capturing + body = nullptr; // Indicates to retrieve the capture buffer when done capturing assert(lexerState->captureBuf == nullptr); lexerState->captureBuf = new (std::nothrow) std::vector(); if (!lexerState->captureBuf) @@ -2216,12 +2221,15 @@ static void startCapture(CaptureBody &capture) { } } -static void endCapture(CaptureBody &capture) { - // This being `nullptr` means we're capturing from the capture buf, which is reallocated +void CaptureBody::endCapture() { + // This being `nullptr` means we're capturing from the capture buffer, which is reallocated // during the whole capture process, and so MUST be retrieved at the end - if (!capture.body) - capture.body = lexerState->captureBuf->data(); - capture.size = lexerState->captureSize; + if (!body) + body = lexerState->captureBuf->data(); + size = lexerState->captureSize; + + // ENDR/ENDM or EOF puts us past the start of the line + lexerState->atLineStart = false; lexerState->capturing = false; lexerState->captureBuf = nullptr; @@ -2229,16 +2237,13 @@ static void endCapture(CaptureBody &capture) { lexerState->disableInterpolation = false; } -bool lexer_CaptureRept(CaptureBody &capture) { - startCapture(capture); +CaptureBody lexer_CaptureRept() { + CaptureBody capture; + capture.startCapture(); size_t depth = 0; int c = EOF; - // Due to parser internals, it reads the EOL after the expression before calling this. - // Thus, we don't need to keep one in the buffer afterwards. - // The following assertion checks that. - assert(lexerState->atLineStart); for (;;) { nextLine(); // We're at line start, so attempt to match a `REPT` or `ENDR` token @@ -2282,16 +2287,17 @@ bool lexer_CaptureRept(CaptureBody &capture) { } finish: - endCapture(capture); - // ENDR or EOF puts us past the start of the line - lexerState->atLineStart = false; + capture.endCapture(); - // Returns true if an ENDR terminated the block, false if it reached EOF first - return c != EOF; + if (c == EOF) + capture.body = nullptr; // Indicates that it reached EOF before an ENDR terminated it + + return capture; } -bool lexer_CaptureMacroBody(CaptureBody &capture) { - startCapture(capture); +CaptureBody lexer_CaptureMacroBody() { + CaptureBody capture; + capture.startCapture(); // If the file is `mmap`ed, we need not to unmap it to keep access to the macro if (auto *mmap = std::get_if(&lexerState->content); mmap) @@ -2299,10 +2305,6 @@ bool lexer_CaptureMacroBody(CaptureBody &capture) { int c = EOF; - // Due to parser internals, it reads the EOL after the expression before calling this. - // Thus, we don't need to keep one in the buffer afterwards. - // The following assertion checks that. - assert(lexerState->atLineStart); for (;;) { nextLine(); // We're at line start, so attempt to match an `ENDM` token @@ -2336,10 +2338,10 @@ bool lexer_CaptureMacroBody(CaptureBody &capture) { } finish: - endCapture(capture); - // ENDM or EOF puts us past the start of the line - lexerState->atLineStart = false; + capture.endCapture(); - // Returns true if an ENDM terminated the block, false if it reached EOF first - return c != EOF; + if (c == EOF) + capture.body = nullptr; // Indicates that it reached EOF before an ENDM terminated it + + return capture; } diff --git a/src/asm/parser.y b/src/asm/parser.y index cacbd2d1..0734dcd6 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -10,6 +10,7 @@ #include #include + #include "asm/lexer.hpp" #include "asm/macro.hpp" #include "asm/rpn.hpp" #include "asm/section.hpp" @@ -56,7 +57,6 @@ #include "asm/fixpoint.hpp" #include "asm/format.hpp" #include "asm/fstack.hpp" - #include "asm/lexer.hpp" #include "asm/main.hpp" #include "asm/opt.hpp" #include "asm/output.hpp" @@ -70,8 +70,6 @@ using namespace std::literals; - static CaptureBody captureBody; // Captures a REPT/FOR or MACRO - yy::parser::symbol_type yylex(); // Provided by lexer.cpp static uint32_t str2int2(std::vector const &s); @@ -248,8 +246,8 @@ %token SECT_WRAM0 "WRAM0" SECT_WRAMX "WRAMX" SECT_HRAM "HRAM" %token SECT_VRAM "VRAM" SECT_SRAM "SRAM" SECT_OAM "OAM" -%type capture_rept -%type capture_macro +%type capture_rept +%type capture_macro %type sect_mod %type > macro_args @@ -869,8 +867,8 @@ load: rept: POP_REPT uconst NEWLINE capture_rept endofline { - if ($4) - fstk_RunRept($2, captureBody.lineNo, captureBody.body, captureBody.size); + if ($4.body) + fstk_RunRept($2, $4.lineNo, $4.body, $4.size); } ; @@ -880,22 +878,14 @@ for: } ID { lexer_ToggleStringExpansion(true); } COMMA for_args NEWLINE capture_rept endofline { - if ($8) - fstk_RunFor( - $3, - $6.start, - $6.stop, - $6.step, - captureBody.lineNo, - captureBody.body, - captureBody.size - ); + if ($8.body) + fstk_RunFor($3, $6.start, $6.stop, $6.step, $8.lineNo, $8.body, $8.size); } ; capture_rept: %empty { - $$ = lexer_CaptureRept(captureBody); + $$ = lexer_CaptureRept(); } ; @@ -930,14 +920,14 @@ def_macro: } ID { lexer_ToggleStringExpansion(true); } NEWLINE capture_macro endofline { - if ($6) - sym_AddMacro($3, captureBody.lineNo, captureBody.body, captureBody.size); + if ($6.body) + sym_AddMacro($3, $6.lineNo, $6.body, $6.size); } ; capture_macro: %empty { - $$ = lexer_CaptureMacroBody(captureBody); + $$ = lexer_CaptureMacroBody(); } ;