Avoid treating labels and macros differently in column 1 (#1515)

Fixes #1512
This commit is contained in:
Sylvie
2024-09-22 19:26:25 -04:00
committed by GitHub
parent 15919e550f
commit 6b89938da7
9 changed files with 75 additions and 39 deletions

View File

@@ -41,7 +41,6 @@ or
Labels tie a name to a specific location within a section (see
.Sx Labels
below).
They must come first in the line.
.Pp
Instructions are assembled into Game Boy opcodes.
Multiple instructions on one line can be separated by double colons

View File

@@ -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);
return token;

View File

@@ -433,22 +433,6 @@ line:
fstk_StopRept();
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;

28
test/asm/lexer-hack.asm Normal file
View 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
View 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
View 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

View File

@@ -1,10 +1,11 @@
MACRO mac
println "got {d:_NARG} args"
ENDM
mac
mac 42
notmac
mac
mac 42
mac::
mac ::
def x = 1 ; so far so good...
def n equ 2 + * / ^ 3 ; oops
def s equs "no closing quote, lol
section "test", rom0 ; good again
ld a, 42 ; keep going...
ld xor, ret ; oh no :(
label1: ; yes...
label2:: ; yes...
label3::: ; no!
halt stop abort ; please
println "finally!"

View File

@@ -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):
syntax error, unexpected newline, expecting : or ::
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
syntax error, unexpected xor
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):
'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)!

View File

@@ -1,2 +1 @@
got 0 args
got 1 args
finally!