mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Parentheses in macro args prevent commas from starting new arguments
This is similar to C's behavior, and convenient for passing
function calls as single values, like `MUL(3.0, 4.0)` or
`STRSUB("str", 2, 1)`.
Fixes #704
This commit is contained in:
@@ -2056,6 +2056,7 @@ static int yylex_RAW(void)
|
|||||||
lexer_GetLineNo(), lexer_GetColNo());
|
lexer_GetLineNo(), lexer_GetColNo());
|
||||||
|
|
||||||
/* This is essentially a modified `appendStringLiteral` */
|
/* This is essentially a modified `appendStringLiteral` */
|
||||||
|
unsigned int parenDepth = 0;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@@ -2076,8 +2077,7 @@ static int yylex_RAW(void)
|
|||||||
discardComment();
|
discardComment();
|
||||||
c = peek();
|
c = peek();
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case ',': /* End of macro arg */
|
case '\r': /* End of line */
|
||||||
case '\r':
|
|
||||||
case '\n':
|
case '\n':
|
||||||
case EOF:
|
case EOF:
|
||||||
goto finish;
|
goto finish;
|
||||||
@@ -2092,12 +2092,29 @@ static int yylex_RAW(void)
|
|||||||
append_yylval_string(c); /* Append the slash */
|
append_yylval_string(c); /* Append the slash */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ',': /* End of macro arg */
|
||||||
|
if (parenDepth == 0)
|
||||||
|
goto finish;
|
||||||
|
goto append;
|
||||||
|
|
||||||
|
case '(': /* Open parentheses inside macro args */
|
||||||
|
if (parenDepth < UINT_MAX)
|
||||||
|
parenDepth++;
|
||||||
|
goto append;
|
||||||
|
|
||||||
|
case ')': /* Close parentheses inside macro args */
|
||||||
|
if (parenDepth > 0)
|
||||||
|
parenDepth--;
|
||||||
|
goto append;
|
||||||
|
|
||||||
case '\\': /* Character escape */
|
case '\\': /* Character escape */
|
||||||
shiftChar();
|
shiftChar();
|
||||||
c = peek();
|
c = peek();
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ',': /* Escape `\,` only inside a macro arg */
|
case ',': /* Escapes only valid inside a macro arg */
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
case '\\': /* Escapes shared with string literals */
|
case '\\': /* Escapes shared with string literals */
|
||||||
case '"':
|
case '"':
|
||||||
case '{':
|
case '{':
|
||||||
@@ -2137,6 +2154,7 @@ static int yylex_RAW(void)
|
|||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
|
|
||||||
default: /* Regular characters will just get copied */
|
default: /* Regular characters will just get copied */
|
||||||
|
append:
|
||||||
append_yylval_string(c);
|
append_yylval_string(c);
|
||||||
shiftChar();
|
shiftChar();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1184,7 +1184,11 @@ ENDM
|
|||||||
.Pp
|
.Pp
|
||||||
Macro arguments support all the escape sequences of strings, as well as
|
Macro arguments support all the escape sequences of strings, as well as
|
||||||
.Ql \[rs],
|
.Ql \[rs],
|
||||||
to escape commas, since those otherwise separate arguments.
|
to escape commas, as well as
|
||||||
|
.Ql \[rs](
|
||||||
|
and
|
||||||
|
.Ql \[rs])
|
||||||
|
to escape parentheses, since those otherwise separate and enclose arguments, respectively.
|
||||||
.Ss Exporting and importing symbols
|
.Ss Exporting and importing symbols
|
||||||
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.
|
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -1553,18 +1557,27 @@ which will print 5 and not 6 as you might have expected.
|
|||||||
Line continuations work as usual inside macros or lists of macro arguments.
|
Line continuations work as usual inside macros or lists of macro arguments.
|
||||||
However, some characters need to be escaped, as in the following example:
|
However, some characters need to be escaped, as in the following example:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
MACRO PrintMacro
|
MACRO PrintMacro1
|
||||||
|
PRINTLN STRCAT(\[rs]1)
|
||||||
|
ENDM
|
||||||
|
PrintMacro1 "Hello "\[rs], \[rs]
|
||||||
|
"world"
|
||||||
|
MACRO PrintMacro2
|
||||||
PRINT \[rs]1
|
PRINT \[rs]1
|
||||||
ENDM
|
ENDM
|
||||||
|
PrintMacro2 STRCAT("Hello ", \[rs]
|
||||||
PrintMacro STRCAT("Hello "\[rs], \[rs]
|
|
||||||
"world\[rs]n")
|
"world\[rs]n")
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The comma needs to be escaped to avoid it being treated as separating the macro's arguments.
|
The comma in
|
||||||
|
.Ql PrintMacro1
|
||||||
|
needs to be escaped to prevent it from starting another macro argument.
|
||||||
|
The comma in
|
||||||
|
.Ql PrintMacro2
|
||||||
|
does not need escaping because it is inside parentheses, similar to macro arguments in C.
|
||||||
The backslash in
|
The backslash in
|
||||||
.Ql \[rs]n
|
.Ql \[rs]n
|
||||||
does not need to be escaped because string literals also work as usual inside macro arguments.
|
also does not need escaping because string literals work as usual inside macro arguments.
|
||||||
.Pp
|
.Pp
|
||||||
Since there are only nine digits, you can only access the first nine macro arguments like this.
|
Since there are only nine digits, you can only access the first nine macro arguments like this.
|
||||||
To use the rest, you need to put the multi-digit argument number in angle brackets, like
|
To use the rest, you need to put the multi-digit argument number in angle brackets, like
|
||||||
|
|||||||
19
test/asm/macro-arg-parentheses.asm
Normal file
19
test/asm/macro-arg-parentheses.asm
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
MACRO printargs
|
||||||
|
REPT _NARG
|
||||||
|
PRINTLN \1
|
||||||
|
SHIFT
|
||||||
|
ENDR
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
printargs mul(3.0, 4.0)
|
||||||
|
|
||||||
|
MACRO printlit
|
||||||
|
REPT _NARG
|
||||||
|
PRINTLN "\1"
|
||||||
|
SHIFT
|
||||||
|
ENDR
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
printlit a(b,c\,d), ((e,f),g), ))h, i\,j,
|
||||||
|
printlit \(k, l), (m:\)n,o(p)q), (r,s)t
|
||||||
|
printlit "))u,v(", ("w,x","y,z"),
|
||||||
0
test/asm/macro-arg-parentheses.err
Normal file
0
test/asm/macro-arg-parentheses.err
Normal file
11
test/asm/macro-arg-parentheses.out
Normal file
11
test/asm/macro-arg-parentheses.out
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
$C0000
|
||||||
|
a(b,c,d)
|
||||||
|
((e,f),g)
|
||||||
|
))h
|
||||||
|
i,j
|
||||||
|
(k
|
||||||
|
l)
|
||||||
|
(m:)n,o(p)q)
|
||||||
|
(r,s)t
|
||||||
|
"))u,v("
|
||||||
|
("w,x","y,z")
|
||||||
@@ -22,7 +22,7 @@ STR EQUS "str\"ing"
|
|||||||
printargs "literal \"\\\"", \ ; comment 2
|
printargs "literal \"\\\"", \ ; comment 2
|
||||||
"""multi-"line"
|
"""multi-"line"
|
||||||
""string"" arg"""
|
""string"" arg"""
|
||||||
printargs MUL(2.0\, 3.0)
|
printargs MUL(2.0, 3.0)
|
||||||
printargs "unclosed
|
printargs "unclosed
|
||||||
|
|
||||||
printlit NUM
|
printlit NUM
|
||||||
@@ -32,7 +32,7 @@ STR EQUS "str\"ing"
|
|||||||
printlit "literal \"\\\"", \ ; comment 4
|
printlit "literal \"\\\"", \ ; comment 4
|
||||||
"""multi-"line"
|
"""multi-"line"
|
||||||
""string"" arg"""
|
""string"" arg"""
|
||||||
printlit MUL(2.0\, 3.0)
|
printlit MUL(2.0, 3.0)
|
||||||
printlit this\n is\, \{not\} a\\n syntax\" error
|
printlit this\n is\, \{not\} a\\n syntax\" error
|
||||||
printlit "unclosed
|
printlit "unclosed
|
||||||
printlit """EOF
|
printlit """EOF
|
||||||
Reference in New Issue
Block a user