shithub: rgbds

Download patch

ref: c20ac350746b318e6399b1bb11d1ad7800263bef
parent: 255b8bf9ba04a4621cd41daadf498156c4bc3d80
author: ISSOtm <eldredhabert0@gmail.com>
date: Sat Dec 19 08:02:05 EST 2020

Refactor `readString`

Much more readable, and avoids `peek(nz)`

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -692,6 +692,11 @@
 	free(expansion);
 }
 
+static bool isMacroChar(char c)
+{
+	return c == '@' || c == '#' || (c >= '0' && c <= '9');
+}
+
 static char const *readMacroArg(char name)
 {
 	char const *str;
@@ -795,7 +800,7 @@
 			/* If character is a backslash, check for a macro arg */
 			lexerState->macroArgScanDistance++;
 			c = peekInternal(distance + 1);
-			if (c == '@' || c == '#' || (c >= '0' && c <= '9')) {
+			if (isMacroChar(c)) {
 				char const *str = readMacroArg(c);
 
 				/*
@@ -1443,22 +1448,22 @@
 
 static void readString(void)
 {
-	size_t i = 0;
-
 	dbgPrint("Reading string\n");
 	lexerState->disableMacroArgs = true;
 	lexerState->disableInterpolation = true;
 
+	size_t i = 0;
 	bool multiline = false;
 
+	// We reach this function after reading a single quote, but we also support triple quotes
 	if (peek(0) == '"') {
 		shiftChars(1);
 		if (peek(0) == '"') {
-			/* """ begins a multi-line string */
+			// """ begins a multi-line string
 			shiftChars(1);
 			multiline = true;
 		} else {
-			/* "" is an empty string */
+			// "" is an empty string, skip the loop
 			goto finish;
 		}
 	}
@@ -1466,45 +1471,35 @@
 	for (;;) {
 		int c = peek(0);
 
-		if (c == '\r' || c == '\n') {
-			if (!multiline) {
-				/* '\r' or '\n' ends a single-line string early */
-				c = EOF;
-			} else if (c == '\r' && peek(1) == '\n') {
-				/* '\r\n' becomes '\n' in multi-line strings */
-				shiftChars(1);
-				c = '\n';
-			}
+		// '\r', '\n' or EOF ends a single-line string early
+		if (c == EOF || (!multiline && (c == '\r' || c == '\n'))) {
+			error("Unterminated string\n");
+			break;
 		}
 
+		// We'll be staying in the string, so we can safely consume the char
+		shiftChars(1);
+
+		// Handle CRLF (in multiline strings only, already handled above otherwise)
+		if (c == '\r' && peek(0) == '\n') {
+			shiftChars(1);
+			c = '\n';
+		}
+
 		switch (c) {
 		case '"':
 			if (multiline) {
-				/* """ ends a multi-line string */
-				if (peek(1) != '"' || peek(2) != '"')
+				// Only """ ends a multi-line string
+				if (peek(0) != '"' || peek(1) != '"')
 					break;
-				shiftChars(3);
-			} else {
-				shiftChars(1);
+				shiftChars(2);
 			}
-			if (i == sizeof(yylval.tzString)) {
-				i--;
-				warning(WARNING_LONG_STR, "String constant too long\n");
-			}
 			goto finish;
 
-		case EOF:
-			if (i == sizeof(yylval.tzString)) {
-				i--;
-				warning(WARNING_LONG_STR, "String constant too long\n");
-			}
-			error("Unterminated string\n");
-			goto finish;
-
-		case '\\': /* Character escape or macro arg */
-			c = peek(1);
+		case '\\': // Character escape or macro arg
+			c = peek(0);
 			switch (c) {
-			case '\\': /* Return that character unchanged */
+			case '\\': // Return that character unchanged
 			case '"':
 			case '{':
 			case '}':
@@ -1523,15 +1518,14 @@
 				shiftChars(1);
 				break;
 
-			/* Line continuation */
+			// Line continuation
 			case ' ':
 			case '\r':
 			case '\n':
-				shiftChars(1); /* Shift the backslash */
 				readLineContinuation();
 				continue;
 
-			/* Macro arg */
+			// Macro arg
 			case '@':
 			case '#':
 			case '0':
@@ -1544,13 +1538,13 @@
 			case '7':
 			case '8':
 			case '9':
-				shiftChars(2);
+				shiftChars(1);
 				char const *str = readMacroArg(c);
 
 				i = appendMacroArg(str, i);
-				continue; /* Do not copy an additional character */
+				continue; // Do not copy an additional character
 
-			case EOF: /* Can't really print that one */
+			case EOF: // Can't really print that one
 				error("Illegal character escape at end of input\n");
 				c = '\\';
 				break;
@@ -1561,8 +1555,9 @@
 			}
 			break;
 
-		case '{': /* Symbol interpolation */
-			shiftChars(1);
+		case '{': // Symbol interpolation
+			// We'll be exiting the string scope, so re-enable expansions
+			// (Not interpolations, since they're handled by the function itself...)
 			lexerState->disableMacroArgs = false;
 			char const *ptr = readInterpolation();
 
@@ -1570,16 +1565,20 @@
 				while (*ptr && i < sizeof(yylval.tzString))
 					yylval.tzString[i++] = *ptr++;
 			lexerState->disableMacroArgs = true;
-			continue; /* Do not copy an additional character */
+			continue; // Do not copy an additional character
 
-		/* Regular characters will just get copied */
+		// Regular characters will just get copied
 		}
-		if (i < sizeof(yylval.tzString)) /* Copy one extra to flag overflow */
+
+		if (i < sizeof(yylval.tzString)) // Copy one extra to flag overflow
 			yylval.tzString[i++] = c;
-		shiftChars(1);
 	}
 
 finish:
+	if (i == sizeof(yylval.tzString)) {
+		i--;
+		warning(WARNING_LONG_STR, "String constant too long\n");
+	}
 	yylval.tzString[i] = '\0';
 
 	dbgPrint("Read string \"%s\"\n", yylval.tzString);