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:
Rangi
2021-04-20 19:50:46 -04:00
committed by Eldred Habert
parent db1f77f90b
commit 27f38770d4
6 changed files with 73 additions and 12 deletions

View File

@@ -2056,6 +2056,7 @@ static int yylex_RAW(void)
lexer_GetLineNo(), lexer_GetColNo());
/* This is essentially a modified `appendStringLiteral` */
unsigned int parenDepth = 0;
size_t i = 0;
int c;
@@ -2076,8 +2077,7 @@ static int yylex_RAW(void)
discardComment();
c = peek();
/* fallthrough */
case ',': /* End of macro arg */
case '\r':
case '\r': /* End of line */
case '\n':
case EOF:
goto finish;
@@ -2092,12 +2092,29 @@ static int yylex_RAW(void)
append_yylval_string(c); /* Append the slash */
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 */
shiftChar();
c = peek();
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 '"':
case '{':
@@ -2137,6 +2154,7 @@ static int yylex_RAW(void)
/* fallthrough */
default: /* Regular characters will just get copied */
append:
append_yylval_string(c);
shiftChar();
break;

View File

@@ -1184,7 +1184,11 @@ ENDM
.Pp
Macro arguments support all the escape sequences of strings, as well as
.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
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
@@ -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.
However, some characters need to be escaped, as in the following example:
.Bd -literal -offset indent
MACRO PrintMacro
MACRO PrintMacro1
PRINTLN STRCAT(\[rs]1)
ENDM
PrintMacro1 "Hello "\[rs], \[rs]
"world"
MACRO PrintMacro2
PRINT \[rs]1
ENDM
PrintMacro STRCAT("Hello "\[rs], \[rs]
"world\[rs]n")
PrintMacro2 STRCAT("Hello ", \[rs]
"world\[rs]n")
.Ed
.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
.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
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

View 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"),

View File

View 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")

View File

@@ -22,7 +22,7 @@ STR EQUS "str\"ing"
printargs "literal \"\\\"", \ ; comment 2
"""multi-"line"
""string"" arg"""
printargs MUL(2.0\, 3.0)
printargs MUL(2.0, 3.0)
printargs "unclosed
printlit NUM
@@ -32,7 +32,7 @@ STR EQUS "str\"ing"
printlit "literal \"\\\"", \ ; comment 4
"""multi-"line"
""string"" arg"""
printlit MUL(2.0\, 3.0)
printlit MUL(2.0, 3.0)
printlit this\n is\, \{not\} a\\n syntax\" error
printlit "unclosed
printlit """EOF