shithub: rgbds

Download patch

ref: af530859f013d52507efcdc4c8f00ade0d7193c2
parent: 58739b0bf2e4057783fed0e8acfc3d0a7668b568
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Wed Dec 9 06:01:51 EST 2020

Allow underscores in numeric literals

Fixes #539

Changes \@'s output to start with "_u", not "_", so it will be valid within labels but not numerics

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -999,16 +999,16 @@
 {
 	uint32_t value = baseValue;
 
-	for (;;) {
+	for (;; shiftChars(1)) {
 		int c = peek(0);
 
-		if (c < '0' || c > '0' + radix - 1)
+		if (c == '_')
+			continue;
+		else if (c < '0' || c > '0' + radix - 1)
 			break;
 		if (value > (UINT32_MAX - (c - '0')) / radix)
 			warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
 		value = value * radix + (c - '0');
-
-		shiftChars(1);
 	}
 
 	yylval.nConstValue = value;
@@ -1019,17 +1019,19 @@
 	uint32_t value = 0, divisor = 1;
 
 	dbgPrint("Reading fractional part\n");
-	for (;;) {
+	for (;; shiftChars(1)) {
 		int c = peek(0);
 
-		if (c < '0' || c > '9')
+		if (c == '_')
+			continue;
+		else if (c < '0' || c > '9')
 			break;
-		shiftChars(1);
 		if (divisor > (UINT32_MAX - (c - '0')) / 10) {
 			warning(WARNING_LARGE_CONSTANT,
 				"Precision of fixed-point constant is too large\n");
 			/* Discard any additional digits */
-			while (c = peek(0), c >= '0' && c <= '9')
+			shiftChars(1);
+			while (c = peek(0), (c >= '0' && c <= '9') || c == '_')
 				shiftChars(1);
 			break;
 		}
@@ -1055,7 +1057,7 @@
 	uint32_t value = 0;
 
 	dbgPrint("Reading binary number with digits [%c,%c]\n", binDigits[0], binDigits[1]);
-	for (;;) {
+	for (;; shiftChars(1)) {
 		int c = peek(0);
 		int bit;
 
@@ -1063,13 +1065,13 @@
 			bit = 0;
 		else if (c == binDigits[1])
 			bit = 1;
+		else if (c == '_')
+			continue;
 		else
 			break;
 		if (value > (UINT32_MAX - bit) / 2)
 			warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
 		value = value * 2 + bit;
-
-		shiftChars(1);
 	}
 
 	yylval.nConstValue = value;
@@ -1081,7 +1083,7 @@
 	bool empty = true;
 
 	dbgPrint("Reading hex number\n");
-	for (;;) {
+	for (;; shiftChars(1)) {
 		int c = peek(0);
 
 		if (c >= 'a' && c <= 'f') /* Convert letters to right after digits */
@@ -1090,6 +1092,8 @@
 			c = c - 'A' + 10;
 		else if (c >= '0' && c <= '9')
 			c = c - '0';
+		else if (c == '_' && !empty)
+			continue;
 		else
 			break;
 
@@ -1097,7 +1101,6 @@
 			warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
 		value = value * 16 + c;
 
-		shiftChars(1);
 		empty = false;
 	}
 
--- a/src/asm/macro.c
+++ b/src/asm/macro.c
@@ -117,7 +117,8 @@
 		if (uniqueID > maxUniqueID)
 			maxUniqueID = uniqueID;
 		/* The buffer is guaranteed to be the correct size */
-		sprintf(uniqueIDBuf, "_%" PRIu32, id);
+		/* This is a valid label fragment, but not a valid numeric */
+		sprintf(uniqueIDBuf, "_u%" PRIu32, id);
 		uniqueIDPtr = uniqueIDBuf;
 	}
 }
--- /dev/null
+++ b/test/asm/underscore-in-numeric-literal.asm
@@ -1,0 +1,21 @@
+SECTION "Test", ROM0
+
+_1234::
+
+; without underscores
+	dw _1234 ; label
+	db 123, 123, 123 ; decimal
+	dw 12345 ; decimal
+	dw $abcd ; hex
+	db &200 ; octal
+	db %11110000, %10 ; binary
+	dl 6.283185 ; fixed point
+
+; with underscores
+	dw _1234 ; label
+	db 123, 1_23, 1__23 ; decimal
+	dw 12_345 ; decimal
+	dw $ab_cd ; hex
+	db &2_0_0_ ; octal
+	db %1111_0000, %1_0 ; binary
+	dl 6_._283_185 ; fixed point
binary files /dev/null b/test/asm/underscore-in-numeric-literal.out.bin differ
--- a/test/asm/unique-id.err
+++ b/test/asm/unique-id.err
@@ -1,19 +1,19 @@
 warning: unique-id.asm(12) -> unique-id.asm::m(4): [-Wuser]
-    _1
+    _u1
 warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser]
-    _2
+    _u2
 warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser]
-    _3
+    _u3
 warning: unique-id.asm(12) -> unique-id.asm::m(8): [-Wuser]
-    _1
+    _u1
 warning: unique-id.asm(14) -> unique-id.asm::m(4): [-Wuser]
-    _4
+    _u4
 warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser]
-    _5
+    _u5
 warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser]
-    _6
+    _u6
 warning: unique-id.asm(14) -> unique-id.asm::m(8): [-Wuser]
-    _4
+    _u4
 FATAL: unique-id.asm(15):
     Macro argument '\@' not defined
 while expanding symbol "print"