mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Avoid treating labels and macros differently in column 1 (#1515)
Fixes #1512
This commit is contained in:
@@ -41,7 +41,6 @@ or
|
|||||||
Labels tie a name to a specific location within a section (see
|
Labels tie a name to a specific location within a section (see
|
||||||
.Sx Labels
|
.Sx Labels
|
||||||
below).
|
below).
|
||||||
They must come first in the line.
|
|
||||||
.Pp
|
.Pp
|
||||||
Instructions are assembled into Game Boy opcodes.
|
Instructions are assembled into Game Boy opcodes.
|
||||||
Multiple instructions on one line can be separated by double colons
|
Multiple instructions on one line can be separated by double colons
|
||||||
|
|||||||
@@ -1849,7 +1849,19 @@ static Token yylex_NORMAL() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.type == T_(ID) && (lexerState->atLineStart || peek() == ':'))
|
// This is a "lexer hack"! We need it to distinguish between label definitions
|
||||||
|
// (which start with `LABEL`) and macro invocations (which start with `ID`).
|
||||||
|
//
|
||||||
|
// If we had one `IDENTIFIER` token, the parser would need to perform "lookahead"
|
||||||
|
// to determine which rule applies. But since macros need to enter "raw" mode to
|
||||||
|
// parse their arguments, which may not even be valid tokens in "normal" mode, we
|
||||||
|
// cannot use lookahead to check for the presence of a `COLON`.
|
||||||
|
//
|
||||||
|
// Instead, we have separate `ID` and `LABEL` tokens, lexing as a `LABEL` if a ':'
|
||||||
|
// 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() == ':')
|
||||||
token.type = T_(LABEL);
|
token.type = T_(LABEL);
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
|
|||||||
@@ -433,22 +433,6 @@ line:
|
|||||||
fstk_StopRept();
|
fstk_StopRept();
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
// Hint about unindented macros parsed as labels
|
|
||||||
| LABEL error {
|
|
||||||
lexer_SetMode(LEXER_NORMAL);
|
|
||||||
lexer_ToggleStringExpansion(true);
|
|
||||||
} endofline {
|
|
||||||
Symbol *macro = sym_FindExactSymbol($1);
|
|
||||||
|
|
||||||
if (macro && macro->type == SYM_MACRO)
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
" To invoke `%s` as a macro it must be indented\n",
|
|
||||||
$1.c_str()
|
|
||||||
);
|
|
||||||
fstk_StopRept();
|
|
||||||
yyerrok;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
endofline: NEWLINE | EOB;
|
endofline: NEWLINE | EOB;
|
||||||
|
|||||||
28
test/asm/lexer-hack.asm
Normal file
28
test/asm/lexer-hack.asm
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
MACRO mac
|
||||||
|
println "got {d:_NARG} args: \#"
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
; indented, these were always macro invocations
|
||||||
|
mac
|
||||||
|
mac ro
|
||||||
|
mac : ld a, 1
|
||||||
|
|
||||||
|
; in column 1, we historically treated these as labels
|
||||||
|
mac
|
||||||
|
mac ro
|
||||||
|
mac : ld b, 2
|
||||||
|
|
||||||
|
SECTION "test", ROM0
|
||||||
|
|
||||||
|
; a colon makes these into labels
|
||||||
|
Label1: ld c, 3
|
||||||
|
Label2: ld d, 4
|
||||||
|
|
||||||
|
; a macro invocation when already defined as a label
|
||||||
|
Label1 args
|
||||||
|
; and a label definition when already defined as a macro
|
||||||
|
mac: ld e, 5
|
||||||
|
|
||||||
|
; the space before the colon matters!
|
||||||
|
undef :
|
||||||
|
undef :
|
||||||
9
test/asm/lexer-hack.err
Normal file
9
test/asm/lexer-hack.err
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
error: lexer-hack.asm(22):
|
||||||
|
"Label1" is not a macro
|
||||||
|
error: lexer-hack.asm(24):
|
||||||
|
'mac' already defined at lexer-hack.asm(1)
|
||||||
|
error: lexer-hack.asm(27):
|
||||||
|
Macro "undef" not defined
|
||||||
|
error: lexer-hack.asm(28):
|
||||||
|
Macro "undef" not defined
|
||||||
|
error: Assembly aborted (4 errors)!
|
||||||
6
test/asm/lexer-hack.out
Normal file
6
test/asm/lexer-hack.out
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
got 0 args:
|
||||||
|
got 1 args: ro
|
||||||
|
got 2 args: : ld a,1
|
||||||
|
got 0 args:
|
||||||
|
got 1 args: ro
|
||||||
|
got 2 args: : ld b,2
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
MACRO mac
|
def x = 1 ; so far so good...
|
||||||
println "got {d:_NARG} args"
|
def n equ 2 + * / ^ 3 ; oops
|
||||||
ENDM
|
def s equs "no closing quote, lol
|
||||||
mac
|
section "test", rom0 ; good again
|
||||||
mac 42
|
ld a, 42 ; keep going...
|
||||||
notmac
|
ld xor, ret ; oh no :(
|
||||||
mac
|
label1: ; yes...
|
||||||
mac 42
|
label2:: ; yes...
|
||||||
mac::
|
label3::: ; no!
|
||||||
mac ::
|
halt stop abort ; please
|
||||||
|
println "finally!"
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
|
error: syntax-error-after-syntax-error.asm(2):
|
||||||
|
syntax error, unexpected *
|
||||||
|
error: syntax-error-after-syntax-error.asm(3):
|
||||||
|
Unterminated string
|
||||||
error: syntax-error-after-syntax-error.asm(6):
|
error: syntax-error-after-syntax-error.asm(6):
|
||||||
syntax error, unexpected newline, expecting : or ::
|
syntax error, unexpected xor
|
||||||
error: syntax-error-after-syntax-error.asm(7):
|
|
||||||
syntax error, unexpected newline, expecting : or ::
|
|
||||||
To invoke `mac` as a macro it must be indented
|
|
||||||
error: syntax-error-after-syntax-error.asm(8):
|
|
||||||
syntax error, unexpected number, expecting : or ::
|
|
||||||
To invoke `mac` as a macro it must be indented
|
|
||||||
error: syntax-error-after-syntax-error.asm(9):
|
error: syntax-error-after-syntax-error.asm(9):
|
||||||
'mac' already defined at syntax-error-after-syntax-error.asm(1)
|
syntax error, unexpected :
|
||||||
error: syntax-error-after-syntax-error.asm(10):
|
error: syntax-error-after-syntax-error.asm(10):
|
||||||
'mac' already defined at syntax-error-after-syntax-error.asm(1)
|
syntax error, unexpected stop, expecting newline or end of buffer or ::
|
||||||
error: Assembly aborted (5 errors)!
|
error: Assembly aborted (5 errors)!
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
got 0 args
|
finally!
|
||||||
got 1 args
|
|
||||||
|
|||||||
Reference in New Issue
Block a user