Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 # .
Comment on lines +1108 to 1110
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be more explicit that “raw symbol” means “prefixed with a hash”.

I'm also realising that “raw identifier” is a better name, since it might not be referring to a symbol yet? (And identifiers are names for symbols. I'd be fine with calling those “raw names”, if that sounds better than “identifier”.)

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 # ) .
Comment on lines +1392 to +1393
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the vein of my previous comment:

Suggested change
Expansion is also disabled for raw string constant symbols (string constant symbols prefixed by a hash
.Sq # ) .
Also, expansion is
.Sy not
performed if the string symbol's name is preceded 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 @@ -1908,17 +1908,21 @@ static Token yylex_NORMAL() {
// `token` is either a `SYMBOL` or a `LOCAL`, 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_(SYMBOL) && 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_SYMBOL);
} else {
std::shared_ptr<std::string> str = sym->getEqus();

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

Expand All @@ -1934,7 +1938,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_(SYMBOL) && peek() == ':') {
if ((token.type == T_(SYMBOL) || token.type == T_(STR_SYMBOL)) && peek() == ':') {
token.type = T_(LABEL);
}

Expand Down
40 changes: 28 additions & 12 deletions src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@
%token <int32_t> NUMBER "number"
%token <std::string> STRING "string"
%token <std::string> SYMBOL "symbol"
%token <std::string> STR_SYMBOL "string symbol"
%token <std::string> LABEL "label"
%token <std::string> LOCAL "local label"
%token <std::string> ANON "anonymous label"
Expand Down Expand Up @@ -354,10 +355,14 @@
%type <std::string> def_rl
%type <std::string> def_equs
%type <std::string> redef_equs
%type <std::string> symbol
%type <std::string> scoped_sym
// `scoped_sym_no_anon` exists because anonymous labels usually count as "scoped symbols", but some
// contexts treat anonymous labels and other labels/symbols differently, e.g. `purge` or `export`.
%type <std::string> scoped_sym_no_anon
// `scoped_sym_no_str` exists because string symbols usually count as symbols, but some contexts
// treat string symbols and other symbols differently, e.g. `relocexpr_no_str`.
%type <std::string> scoped_sym_no_str

// SM83 instruction parameters
%type <int32_t> reg_r
Expand Down Expand Up @@ -514,7 +519,7 @@ endc:
def_id:
OP_DEF {
lexer_ToggleStringExpansion(false);
} SYMBOL {
} symbol {
lexer_ToggleStringExpansion(true);
$$ = std::move($3);
}
Expand All @@ -523,13 +528,17 @@ def_id:
redef_id:
POP_REDEF {
lexer_ToggleStringExpansion(false);
} SYMBOL {
} symbol {
lexer_ToggleStringExpansion(true);
$$ = std::move($3);
}
;

scoped_sym_no_anon: SYMBOL | LABEL | LOCAL;
symbol: SYMBOL | STR_SYMBOL;

scoped_sym_no_str: SYMBOL | LABEL | LOCAL | ANON;

scoped_sym_no_anon: symbol | LABEL | LOCAL;

scoped_sym: scoped_sym_no_anon | ANON;

Expand Down Expand Up @@ -558,7 +567,7 @@ label:
;

macro:
SYMBOL {
symbol {
// Parsing 'macro_args' will restore the lexer's normal mode
lexer_SetMode(LEXER_RAW);
} macro_args {
Expand Down Expand Up @@ -844,7 +853,7 @@ rept:
for:
POP_FOR {
lexer_ToggleStringExpansion(false);
} SYMBOL {
} symbol {
lexer_ToggleStringExpansion(true);
} COMMA for_args NEWLINE capture_rept endofline {
if ($8.span.ptr) {
Expand Down Expand Up @@ -888,7 +897,7 @@ break:
def_macro:
POP_MACRO {
lexer_ToggleStringExpansion(false);
} SYMBOL {
} symbol {
lexer_ToggleStringExpansion(true);
} NEWLINE capture_macro endofline {
if ($6.span.ptr) {
Expand Down Expand Up @@ -1153,16 +1162,16 @@ charmap_args:
;

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

setcharmap:
POP_SETCHARMAP SYMBOL {
POP_SETCHARMAP symbol {
charmap_Set($2);
}
;
Expand All @@ -1174,7 +1183,7 @@ pushc:
;

pushc_setcharmap:
POP_PUSHC SYMBOL {
POP_PUSHC symbol {
charmap_Push();
charmap_Set($2);
}
Expand Down Expand Up @@ -1307,7 +1316,7 @@ relocexpr:
;

relocexpr_no_str:
scoped_sym {
scoped_sym_no_str {
$$.makeSymbol($1);
}
| NUMBER {
Expand Down Expand Up @@ -1400,7 +1409,7 @@ relocexpr_no_str:
| OP_ISCONST LPAREN relocexpr RPAREN {
$$.makeNumber($3.isKnown());
}
| OP_BANK LPAREN scoped_sym RPAREN {
| OP_BANK LPAREN scoped_sym_no_str RPAREN {
// '@' is also a SYMBOL; it is handled here
$$.makeBankSymbol($3);
}
Expand Down Expand Up @@ -1529,6 +1538,13 @@ string:
STRING {
$$ = std::move($1);
}
| STR_SYMBOL {
if (Symbol *sym = sym_FindExactSymbol($1); sym && sym->type == SYM_EQUS) {
$$ = *sym->getEqus();
} else {
::error("'%s' is not a string symbol", $1.c_str());
}
}
| OP_STRSUB LPAREN string COMMA iconst COMMA uconst RPAREN {
size_t len = strlenUTF8($3, false);
uint32_t pos = adjustNegativePos($5, len, "STRSUB");
Expand Down
2 changes: 1 addition & 1 deletion test/asm/anon-label-bad.err
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ error: anon-label-bad.asm(6):
error: anon-label-bad.asm(9):
syntax error, unexpected anonymous label
error: anon-label-bad.asm(10):
syntax error, unexpected anonymous label, expecting symbol or label or local label
syntax error, unexpected anonymous label, expecting symbol or string symbol or label or local label
error: anon-label-bad.asm(22):
syntax error, unexpected ::
error: Assembly aborted (5 errors)!
6 changes: 3 additions & 3 deletions test/asm/def-scoped.err
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error: def-scoped.asm(10):
syntax error, unexpected local label, expecting symbol
syntax error, unexpected local label, expecting symbol or string symbol
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... this sounds confusing. “Why is it expecting a symbol or a symbol?”

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is one reason why I prefer #1648 as well.

error: def-scoped.asm(13):
syntax error, unexpected local label, expecting symbol
syntax error, unexpected local label, expecting symbol or string symbol
error: def-scoped.asm(16):
syntax error, unexpected local label, expecting symbol
syntax error, unexpected local label, expecting symbol or string symbol
error: Assembly aborted (3 errors)!
8 changes: 4 additions & 4 deletions test/asm/label-macro-arg.err
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
error: label-macro-arg.asm(38) -> label-macro-arg.asm::test_char(25):
syntax error, unexpected local label, expecting symbol
syntax error, unexpected local label, expecting symbol or string symbol
while expanding symbol "VAR_DEF"
error: label-macro-arg.asm(38) -> label-macro-arg.asm::test_char(26):
syntax error, unexpected local label, expecting symbol
syntax error, unexpected local label, expecting symbol or string symbol
error: label-macro-arg.asm(38) -> label-macro-arg.asm::test_char(29):
Interpolated symbol "sizeof_.something" does not exist
error: label-macro-arg.asm(39) -> label-macro-arg.asm::test_char(25):
syntax error, unexpected label, expecting symbol
syntax error, unexpected label, expecting symbol or string symbol
while expanding symbol "VAR_DEF"
error: label-macro-arg.asm(39) -> label-macro-arg.asm::test_char(26):
syntax error, unexpected label, expecting symbol
syntax error, unexpected label, expecting symbol or string symbol
error: label-macro-arg.asm(39) -> label-macro-arg.asm::test_char(29):
Invalid format spec 'sizeof_'
error: label-macro-arg.asm(39) -> label-macro-arg.asm::test_char(29):
Expand Down
29 changes: 29 additions & 0 deletions test/asm/raw-string-symbol-errors.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
def n equ 42
def s equs "hello"
macro m
endm

assert (#n) == 42
assert (#s) == $656c6c6f
assert (#m) == 0
assert (#u) == 0

assert strlen(#n) == 0
assert strlen(#s) == 5
assert strlen(#m) == 0
assert strlen(#u) == 0

def d_n = (#n)
def d_s = (#s)
def d_m = (#m)
def d_u = (#u)

def s_n equs #n
def s_s equs #s
def s_m equs #m
def s_u equs #u

purge #s
purge #s
assert (#s) == 0
assert strlen(#s) == 0
27 changes: 27 additions & 0 deletions test/asm/raw-string-symbol-errors.err
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
warning: raw-string-symbol-errors.asm(7): [-Wobsolete]
Treating multi-unit strings as numbers is deprecated
error: raw-string-symbol-errors.asm(8):
'm' is not a numeric symbol
error: raw-string-symbol-errors.asm(11):
syntax error, unexpected symbol
error: raw-string-symbol-errors.asm(13):
syntax error, unexpected symbol
error: raw-string-symbol-errors.asm(14):
syntax error, unexpected symbol
warning: raw-string-symbol-errors.asm(17): [-Wobsolete]
Treating multi-unit strings as numbers is deprecated
error: raw-string-symbol-errors.asm(18):
'm' is not a numeric symbol
error: raw-string-symbol-errors.asm(19):
Expected constant expression: 'u' is not constant at assembly time
error: raw-string-symbol-errors.asm(21):
syntax error, unexpected symbol
error: raw-string-symbol-errors.asm(23):
syntax error, unexpected symbol
error: raw-string-symbol-errors.asm(24):
syntax error, unexpected symbol
error: raw-string-symbol-errors.asm(27):
's' was already purged
error: raw-string-symbol-errors.asm(29):
syntax error, unexpected symbol
error: Assembly aborted (11 errors)!
34 changes: 34 additions & 0 deletions test/asm/raw-string-symbols.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
opt Wno-unmapped-char

def hello equs "world"
def name equs "hello"
println "{name}"
println #name
assert !strcmp(strsub(#name, 1, 4), "hell")
assert strlen(#hello) == charlen(#hello)
assert strlen("{hello}") == 5

def multi equs """the quick
brown fox"""
println #multi

def char equs "A"
def n = #char
println n
def n = (#char)
println n
def n = 1 + #char
println n
assert #char == $41

def fmt equs "%s %s %d"
println strfmt(#fmt, #name, #hello, (#char))

purge #name
assert !def(name) && !def(#name) && def(hello)

section "test", rom0
#label:
db #hello
dw #hello
dw BANK(#label), #label
8 changes: 8 additions & 0 deletions test/asm/raw-string-symbols.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
hello
hello
the quick
brown fox
$41
$41
$42
hello world 65
Binary file added test/asm/raw-string-symbols.out.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion test/asm/syntax-error-lexer-mode.err
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: syntax-error-lexer-mode.asm(7):
syntax error, unexpected af
error: syntax-error-lexer-mode.asm(11):
syntax error, unexpected af, expecting symbol
syntax error, unexpected af, expecting symbol or string symbol
error: Assembly aborted (2 errors)!
Loading