ref: 7a314e7aff2a6e9a0f82cc7f98269276fcc167cb
parent: 637bbbdf4312ca6efb6eb4ad6ae4ad7f06d9357e
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Sun Apr 18 19:47:10 EDT 2021
Support numeric symbol names in \(parentheses) For example, \(_NARG) will get the last argument
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -724,6 +724,8 @@
static int peek(void);
static void shiftChar(void);
static uint32_t readNumber(int radix, uint32_t baseValue);
+static bool startsIdentifier(int c);
+static bool continuesIdentifier(int c);
static uint32_t readParentheticMacroArgNum(void)
{
@@ -736,15 +738,42 @@
uint32_t num = 0;
int c = peek();
- bool hasDigit = c >= '0' && c <= '9';
+ bool empty = false;
- if (hasDigit)
+ if (c >= '0' && c <= '9') {
num = readNumber(10, 0);
+ } else if (startsIdentifier(c)) {
+ char symName[MAXSYMLEN + 1];
+ size_t i = 0;
+ for (; continuesIdentifier(c); c = peek()) {
+ if (i < sizeof(symName))
+ symName[i++] = c;
+ shiftChar();
+ }
+
+ if (i == sizeof(symName)) {
+ warning(WARNING_LONG_STR, "Symbol name too long\n");
+ i--;
+ }
+ symName[i] = '\0';
+
+ struct Symbol const *sym = sym_FindScopedSymbol(symName);
+
+ if (!sym)
+ fatalerror("Parenthetic symbol \"%s\" does not exist\n", symName);
+ else if (!sym_IsNumeric(sym))
+ fatalerror("Parenthetic symbol \"%s\" is not numeric\n", symName);
+
+ num = sym_GetConstantSymValue(sym);
+ } else {
+ empty = true;
+ }
+
c = peek();
if (c != ')')
fatalerror("Invalid character in parenthetic macro argument %s\n", printChar(c));
- else if (!hasDigit)
+ else if (empty)
fatalerror("Empty parenthetic macro argument\n");
else if (num == 0)
fatalerror("Invalid parenthetic macro argument '\\(0)'\n");
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -1569,7 +1569,10 @@
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 parentheses, like
.Ql \[rs](10) .
-This parenthetic syntax only supports decimal numbers.
+This parenthetic syntax supports decimal numbers and numeric symbol names.
+For example,
+.Ql \[rs](_NARG)
+will get the last argument.
.Pp
Other macro arguments and symbol interpolations will be expanded inside the parentheses.
For example, if
@@ -1580,10 +1583,12 @@
.Ql \[rs](\[rs]1)
will expand to
.Ql \[rs](13) .
-And if
-.Ql x = 42 ,
+Or if
+.Ql v10 = 42
+and
+.Ql x = 10 ,
then
-.Ql \[rs]({d:x})
+.Ql \[rs](v{d:x})
will expand to
.Ql \[rs](42) .
.Pp
--- /dev/null
+++ b/test/asm/invalid-macro-arg-symbol.asm
@@ -1,0 +1,1 @@
+\(foo)
--- /dev/null
+++ b/test/asm/invalid-macro-arg-symbol.err
@@ -1,0 +1,2 @@
+FATAL: invalid-macro-arg-symbol.asm(1):
+ Parenthetic symbol "foo" does not exist
--- a/test/asm/parenthetic-macro-args.asm
+++ b/test/asm/parenthetic-macro-args.asm
@@ -12,6 +12,8 @@
println \(2__) + \(1_2) + \(\1)
x = 2
println \({d:x}) + \(1_{d:x}) + \(\(\(13)))
+y equs "NARG"
+ println \(x) + \(1_{d:x}_) + \(\(\(_{y})))
ENDM
mac 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 1
--- a/test/asm/parenthetic-macro-args.out
+++ b/test/asm/parenthetic-macro-args.out
@@ -4,3 +4,4 @@
last = D
$F0
$F0
+$F0