Skip to content

Commit

Permalink
Disable EQUS expansion for raw symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
Rangi42 committed Feb 5, 2025
1 parent d9d381c commit b6c70b3
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 38 deletions.
6 changes: 5 additions & 1 deletion man/rgbasm.5
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,9 @@ Additionally, label names can contain up to a single dot
.Ql \&. ,
which may not be the first character.
.Pp
A symbol cannot have the same name as a reserved keyword, unless it is prefixed by a hash
A symbol cannot have the same name as a reserved keyword, unless it is a
.Dq raw symbol
prefixed by a hash
.Sq # .
For example,
.Ql #load
Expand Down Expand Up @@ -1387,6 +1389,8 @@ This expansion is disabled in a few contexts:
and
.Ql MACRO name
will not expand string constants in their names.
Expansion is also disabled for raw string constant symbols (string constant symbols prefixed by a hash
.Sq # ) .
.Bd -literal -offset indent
DEF COUNTREG EQUS "[hl+]"
ld a, COUNTREG
Expand Down
18 changes: 11 additions & 7 deletions src/asm/lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1910,17 +1910,21 @@ static Token yylex_NORMAL() {
// `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
assume(token.value.holds<std::string>());

// Local symbols cannot be string expansions
// Raw symbols and local symbols cannot be string expansions
if (token.type == T_(ID) && lexerState->expandStrings) {
// Attempt string expansion
Symbol const *sym = sym_FindExactSymbol(token.value.get<std::string>());

if (sym && sym->type == SYM_EQUS) {
std::shared_ptr<std::string> str = sym->getEqus();

assume(str);
beginExpansion(str, sym->name);
continue; // Restart, reading from the new buffer
if (raw) {
token.type = T_(STR_ID);
} else {
std::shared_ptr<std::string> str = sym->getEqus();

assume(str);
beginExpansion(str, sym->name);
continue; // Restart, reading from the new buffer
}
}
}

Expand All @@ -1936,7 +1940,7 @@ static Token yylex_NORMAL() {
// character *immediately* follows the identifier. Thus, at the beginning of a line,
// "Label:" and "mac:" are treated as label definitions, but "Label :" and "mac :"
// are treated as macro invocations.
if (token.type == T_(ID) && peek() == ':') {
if ((token.type == T_(ID) || token.type == T_(STR_ID)) && peek() == ':') {
token.type = T_(LABEL);
}

Expand Down
63 changes: 33 additions & 30 deletions src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@
%token <std::string> STRING "string"
%token <std::string> LABEL "label"
%token <std::string> ID "identifier"
%token <std::string> STR_ID "string identifier"
%token <std::string> LOCAL_ID "local identifier"
%token <std::string> ANON "anonymous label"

Expand Down Expand Up @@ -344,6 +345,7 @@
%type <std::string> string
%type <std::string> strcat_args
// Strings used for identifiers
%type <std::string> sym_id
%type <std::string> def_id
%type <std::string> redef_id
%type <std::string> def_numeric
Expand All @@ -357,6 +359,7 @@
%type <std::string> redef_equs
%type <std::string> scoped_id
%type <std::string> scoped_anon_id
%type <std::string> scoped_anon_id_no_str

// SM83 instruction parameters
%type <int32_t> reg_r
Expand Down Expand Up @@ -510,10 +513,12 @@ endc:
}
;
sym_id: ID | STR_ID;
def_id:
OP_DEF {
lexer_ToggleStringExpansion(false);
} ID {
} sym_id {
lexer_ToggleStringExpansion(true);
$$ = std::move($3);
}
Expand All @@ -522,34 +527,19 @@ def_id:
redef_id:
POP_REDEF {
lexer_ToggleStringExpansion(false);
} ID {
} sym_id {
lexer_ToggleStringExpansion(true);
$$ = std::move($3);
}
;
// LABEL covers identifiers followed by a double colon (e.g. `call Function::ret`,
// to be read as `call Function :: ret`). This should not conflict with anything.
scoped_id:
ID {
$$ = std::move($1);
}
| LOCAL_ID {
$$ = std::move($1);
}
| LABEL {
$$ = std::move($1);
}
;
scoped_id: sym_id | LOCAL_ID | LABEL;
scoped_anon_id:
scoped_id {
$$ = std::move($1);
}
| ANON {
$$ = std::move($1);
}
;
scoped_anon_id_no_str: ID | LOCAL_ID | LABEL | ANON;
scoped_anon_id: scoped_anon_id_no_str | STR_ID;
label:
%empty
Expand All @@ -576,7 +566,7 @@ label:
;
macro:
ID {
sym_id {
// Parsing 'macro_args' will restore the lexer's normal mode
lexer_SetMode(LEXER_RAW);
} macro_args {
Expand Down Expand Up @@ -862,7 +852,7 @@ rept:
for:
POP_FOR {
lexer_ToggleStringExpansion(false);
} ID {
} sym_id {
lexer_ToggleStringExpansion(true);
} COMMA for_args NEWLINE capture_rept endofline {
if ($8.span.ptr) {
Expand Down Expand Up @@ -906,7 +896,7 @@ break:
def_macro:
POP_MACRO {
lexer_ToggleStringExpansion(false);
} ID {
} sym_id {
lexer_ToggleStringExpansion(true);
} NEWLINE capture_macro endofline {
if ($6.span.ptr) {
Expand Down Expand Up @@ -1171,16 +1161,16 @@ charmap_args:
;

newcharmap:
POP_NEWCHARMAP ID {
POP_NEWCHARMAP sym_id {
charmap_New($2, nullptr);
}
| POP_NEWCHARMAP ID COMMA ID {
| POP_NEWCHARMAP sym_id COMMA sym_id {
charmap_New($2, &$4);
}
;

setcharmap:
POP_SETCHARMAP ID {
POP_SETCHARMAP sym_id {
charmap_Set($2);
}
;
Expand All @@ -1192,7 +1182,7 @@ pushc:
;

pushc_setcharmap:
POP_PUSHC ID {
POP_PUSHC sym_id {
charmap_Push();
charmap_Set($2);
}
Expand Down Expand Up @@ -1325,7 +1315,7 @@ relocexpr:
;

relocexpr_no_str:
scoped_anon_id {
scoped_anon_id_no_str {
$$.makeSymbol($1);
}
| NUMBER {
Expand Down Expand Up @@ -1418,7 +1408,7 @@ relocexpr_no_str:
| OP_ISCONST LPAREN relocexpr RPAREN {
$$.makeNumber($3.isKnown());
}
| OP_BANK LPAREN scoped_anon_id RPAREN {
| OP_BANK LPAREN scoped_anon_id_no_str RPAREN {
// '@' is also an ID; it is handled here
$$.makeBankSymbol($3);
}
Expand Down Expand Up @@ -1547,6 +1537,19 @@ string:
STRING {
$$ = std::move($1);
}
| STR_ID {
if (Symbol *sym = sym_FindExactSymbol($1); !sym) {
if (sym_IsPurgedExact($1)) {
::error("Unknown symbol \"%s\"; it was purged\n", $1.c_str());
} else {
::error("Unknown symbol \"%s\"\n", $1.c_str());
}
} else if (sym->type != SYM_EQUS) {
::error("Symbol \"%s\" is not a string symbol", $1.c_str());
} else {
$$ = *sym->getEqus();
}
}
| OP_STRSUB LPAREN string COMMA iconst COMMA uconst RPAREN {
size_t len = strlenUTF8($3, false);
uint32_t pos = adjustNegativePos($5, len, "STRSUB");
Expand Down

0 comments on commit b6c70b3

Please sign in to comment.