mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Use automatic allocation for IF stacks and expansions
Switch to using `std::deque` for IF stacks (supports `.clear()`)
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
#define RGBDS_ASM_LEXER_H
|
#define RGBDS_ASM_LEXER_H
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
#include "platform.hpp" // SSIZE_MAX
|
#include "platform.hpp" // SSIZE_MAX
|
||||||
|
|
||||||
@@ -74,7 +73,7 @@ struct LexerState {
|
|||||||
uint32_t colNo;
|
uint32_t colNo;
|
||||||
int lastToken;
|
int lastToken;
|
||||||
|
|
||||||
std::stack<struct IfStackEntry> *ifStack;
|
std::deque<struct IfStackEntry> ifStack;
|
||||||
|
|
||||||
bool capturing; // Whether the text being lexed should be captured
|
bool capturing; // Whether the text being lexed should be captured
|
||||||
size_t captureSize; // Amount of text captured
|
size_t captureSize; // Amount of text captured
|
||||||
@@ -85,7 +84,7 @@ struct LexerState {
|
|||||||
bool disableInterpolation;
|
bool disableInterpolation;
|
||||||
size_t macroArgScanDistance; // Max distance already scanned for macro args
|
size_t macroArgScanDistance; // Max distance already scanned for macro args
|
||||||
bool expandStrings;
|
bool expandStrings;
|
||||||
std::deque<struct Expansion> *expansions; // Front is the innermost current expansion
|
std::deque<struct Expansion> expansions; // Front is the innermost current expansion
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct LexerState *lexerState;
|
extern struct LexerState *lexerState;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stack>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -294,9 +293,7 @@ static void initState(struct LexerState &state)
|
|||||||
state.atLineStart = true; // yylex() will init colNo due to this
|
state.atLineStart = true; // yylex() will init colNo due to this
|
||||||
state.lastToken = T_EOF;
|
state.lastToken = T_EOF;
|
||||||
|
|
||||||
state.ifStack = new(std::nothrow) std::stack<struct IfStackEntry>();
|
state.ifStack.clear();
|
||||||
if (!state.ifStack)
|
|
||||||
fatalerror("Unable to allocate new IF stack: %s\n", strerror(errno));
|
|
||||||
|
|
||||||
state.capturing = false;
|
state.capturing = false;
|
||||||
state.captureBuf = NULL;
|
state.captureBuf = NULL;
|
||||||
@@ -306,9 +303,7 @@ static void initState(struct LexerState &state)
|
|||||||
state.macroArgScanDistance = 0;
|
state.macroArgScanDistance = 0;
|
||||||
state.expandStrings = true;
|
state.expandStrings = true;
|
||||||
|
|
||||||
state.expansions = new(std::nothrow) std::deque<struct Expansion>();
|
state.expansions.clear();
|
||||||
if (!state.expansions)
|
|
||||||
fatalerror("Unable to allocate new expansion stack: %s\n", strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nextLine(void)
|
static void nextLine(void)
|
||||||
@@ -319,40 +314,40 @@ static void nextLine(void)
|
|||||||
|
|
||||||
uint32_t lexer_GetIFDepth(void)
|
uint32_t lexer_GetIFDepth(void)
|
||||||
{
|
{
|
||||||
return lexerState->ifStack->size();
|
return lexerState->ifStack.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer_IncIFDepth(void)
|
void lexer_IncIFDepth(void)
|
||||||
{
|
{
|
||||||
lexerState->ifStack->push({ .ranIfBlock = false, .reachedElseBlock = false });
|
lexerState->ifStack.push_front({ .ranIfBlock = false, .reachedElseBlock = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer_DecIFDepth(void)
|
void lexer_DecIFDepth(void)
|
||||||
{
|
{
|
||||||
if (lexerState->ifStack->empty())
|
if (lexerState->ifStack.empty())
|
||||||
fatalerror("Found ENDC outside an IF construct\n");
|
fatalerror("Found ENDC outside an IF construct\n");
|
||||||
|
|
||||||
lexerState->ifStack->pop();
|
lexerState->ifStack.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lexer_RanIFBlock(void)
|
bool lexer_RanIFBlock(void)
|
||||||
{
|
{
|
||||||
return lexerState->ifStack->top().ranIfBlock;
|
return lexerState->ifStack.front().ranIfBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lexer_ReachedELSEBlock(void)
|
bool lexer_ReachedELSEBlock(void)
|
||||||
{
|
{
|
||||||
return lexerState->ifStack->top().reachedElseBlock;
|
return lexerState->ifStack.front().reachedElseBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer_RunIFBlock(void)
|
void lexer_RunIFBlock(void)
|
||||||
{
|
{
|
||||||
lexerState->ifStack->top().ranIfBlock = true;
|
lexerState->ifStack.front().ranIfBlock = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer_ReachELSEBlock(void)
|
void lexer_ReachELSEBlock(void)
|
||||||
{
|
{
|
||||||
lexerState->ifStack->top().reachedElseBlock = true;
|
lexerState->ifStack.front().reachedElseBlock = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lexer_OpenFile(struct LexerState &state, char const *path)
|
bool lexer_OpenFile(struct LexerState &state, char const *path)
|
||||||
@@ -461,8 +456,6 @@ void lexer_DeleteState(struct LexerState &state)
|
|||||||
close(state.cbuf.fd);
|
close(state.cbuf.fd);
|
||||||
else if (state.isFile && !state.mmap.isReferenced)
|
else if (state.isFile && !state.mmap.isReferenced)
|
||||||
munmap(state.mmap.ptr, state.mmap.size);
|
munmap(state.mmap.ptr, state.mmap.size);
|
||||||
delete state.ifStack;
|
|
||||||
delete state.expansions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct KeywordDictNode {
|
struct KeywordDictNode {
|
||||||
@@ -560,7 +553,7 @@ static void beginExpansion(char const *str, bool owned, char const *name)
|
|||||||
if (name)
|
if (name)
|
||||||
lexer_CheckRecursionDepth();
|
lexer_CheckRecursionDepth();
|
||||||
|
|
||||||
lexerState->expansions->push_front({
|
lexerState->expansions.push_front({
|
||||||
.name = name ? strdup(name) : NULL,
|
.name = name ? strdup(name) : NULL,
|
||||||
.contents = { .unowned = str },
|
.contents = { .unowned = str },
|
||||||
.size = size,
|
.size = size,
|
||||||
@@ -571,7 +564,7 @@ static void beginExpansion(char const *str, bool owned, char const *name)
|
|||||||
|
|
||||||
void lexer_CheckRecursionDepth(void)
|
void lexer_CheckRecursionDepth(void)
|
||||||
{
|
{
|
||||||
if (lexerState->expansions->size() > maxRecursionDepth + 1)
|
if (lexerState->expansions.size() > maxRecursionDepth + 1)
|
||||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,7 +699,7 @@ static size_t readInternal(size_t bufIndex, size_t nbChars)
|
|||||||
// We only need one character of lookahead, for macro arguments
|
// We only need one character of lookahead, for macro arguments
|
||||||
static int peekInternal(uint8_t distance)
|
static int peekInternal(uint8_t distance)
|
||||||
{
|
{
|
||||||
for (struct Expansion &exp : *lexerState->expansions) {
|
for (struct Expansion &exp : lexerState->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 `peekInternal` will continue with its parent
|
||||||
assert(exp.offset <= exp.size);
|
assert(exp.offset <= exp.size);
|
||||||
@@ -825,9 +818,9 @@ static void shiftChar(void)
|
|||||||
lexerState->macroArgScanDistance--;
|
lexerState->macroArgScanDistance--;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
if (!lexerState->expansions->empty()) {
|
if (!lexerState->expansions.empty()) {
|
||||||
// Advance within the current expansion
|
// Advance within the current expansion
|
||||||
struct Expansion &expansion = lexerState->expansions->front();
|
struct Expansion &expansion = lexerState->expansions.front();
|
||||||
|
|
||||||
assert(expansion.offset <= expansion.size);
|
assert(expansion.offset <= expansion.size);
|
||||||
expansion.offset++;
|
expansion.offset++;
|
||||||
@@ -835,7 +828,7 @@ restart:
|
|||||||
// When advancing would go past an expansion's end, free it,
|
// When advancing would go past an expansion's end, free it,
|
||||||
// move up to its parent, and try again to advance
|
// move up to its parent, and try again to advance
|
||||||
freeExpansion(expansion);
|
freeExpansion(expansion);
|
||||||
lexerState->expansions->pop_front();
|
lexerState->expansions.pop_front();
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -892,7 +885,7 @@ void lexer_DumpStringExpansions(void)
|
|||||||
if (!lexerState)
|
if (!lexerState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (struct Expansion &exp : *lexerState->expansions) {
|
for (struct Expansion &exp : lexerState->expansions) {
|
||||||
// Only register EQUS expansions, not string args
|
// Only register EQUS expansions, not string args
|
||||||
if (exp.name)
|
if (exp.name)
|
||||||
fprintf(stderr, "while expanding symbol \"%s\"\n", exp.name);
|
fprintf(stderr, "while expanding symbol \"%s\"\n", exp.name);
|
||||||
@@ -916,7 +909,7 @@ static void discardBlockComment(void)
|
|||||||
handleCRLF(c);
|
handleCRLF(c);
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case '\n':
|
case '\n':
|
||||||
if (lexerState->expansions->empty())
|
if (lexerState->expansions.empty())
|
||||||
nextLine();
|
nextLine();
|
||||||
continue;
|
continue;
|
||||||
case '/':
|
case '/':
|
||||||
@@ -969,7 +962,7 @@ static void readLineContinuation(void)
|
|||||||
shiftChar();
|
shiftChar();
|
||||||
// Handle CRLF before nextLine() since shiftChar updates colNo
|
// Handle CRLF before nextLine() since shiftChar updates colNo
|
||||||
handleCRLF(c);
|
handleCRLF(c);
|
||||||
if (lexerState->expansions->empty())
|
if (lexerState->expansions.empty())
|
||||||
nextLine();
|
nextLine();
|
||||||
break;
|
break;
|
||||||
} else if (c == ';') {
|
} else if (c == ';') {
|
||||||
@@ -2322,7 +2315,7 @@ int yylex(void)
|
|||||||
if (lexerState->lastToken == T_EOB && yywrap())
|
if (lexerState->lastToken == T_EOB && yywrap())
|
||||||
return T_EOF;
|
return T_EOF;
|
||||||
// Newlines read within an expansion should not increase the line count
|
// Newlines read within an expansion should not increase the line count
|
||||||
if (lexerState->atLineStart && lexerState->expansions->empty())
|
if (lexerState->atLineStart && lexerState->expansions.empty())
|
||||||
nextLine();
|
nextLine();
|
||||||
|
|
||||||
static int (* const lexerModeFuncs[NB_LEXER_MODES])(void) = {
|
static int (* const lexerModeFuncs[NB_LEXER_MODES])(void) = {
|
||||||
@@ -2353,7 +2346,7 @@ static void startCapture(struct CaptureBody *capture)
|
|||||||
|
|
||||||
capture->lineNo = lexer_GetLineNo();
|
capture->lineNo = lexer_GetLineNo();
|
||||||
|
|
||||||
if (lexerState->isMmapped && lexerState->expansions->empty()) {
|
if (lexerState->isMmapped && lexerState->expansions.empty()) {
|
||||||
capture->body = &lexerState->mmap.ptr[lexerState->mmap.offset];
|
capture->body = &lexerState->mmap.ptr[lexerState->mmap.offset];
|
||||||
} else {
|
} else {
|
||||||
lexerState->captureCapacity = 128; // The initial size will be twice that
|
lexerState->captureCapacity = 128; // The initial size will be twice that
|
||||||
|
|||||||
Reference in New Issue
Block a user