shithub: rgbds

Download patch

ref: 6e805cd3182390d756dc973dd61f2d31a476cdb1
parent: e11f25024e619c9c1fdd6d3a2cf577f937fa13f9
author: ISSOtm <eldredhabert0@gmail.com>
date: Fri Jul 31 20:52:10 EDT 2020

Implement macro args

This finally allows running 90% of the test suite, debugging time!

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -373,7 +373,7 @@
 	struct LexerState *state = malloc(sizeof(*state));
 
 	if (!state) {
-		error("Failed to allocate memory for lexer state: %s", strerror(errno));
+		error("Failed to allocate memory for lexer state: %s\n", strerror(errno));
 		return NULL;
 	}
 	// TODO: init `path`
@@ -1088,7 +1088,7 @@
 				}
 			}
 		} else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
-			error("Unterminated interpolation\n");
+			error("Missing }\n");
 			break;
 		} else if (c == '}') {
 			shiftChars(1);
@@ -1441,10 +1441,6 @@
 				shiftChars(1); /* Shift that EOL */
 			/* fallthrough */
 		case '\n':
-			if (lexerStateEOL) {
-				lexer_SetState(lexerStateEOL);
-				lexerStateEOL = NULL;
-			}
 			return '\n';
 
 		case EOF:
@@ -1490,9 +1486,95 @@
 	}
 }
 
+static bool isWhitespace(int c)
+{
+	return c == ' ' || c == '\t';
+}
+
 static int yylex_RAW(void)
 {
-	fatalerror("LEXER_RAW not yet implemented\n");
+	/* This is essentially a modified `readString` */
+	size_t i = 0;
+
+	/* Trim left of string... */
+	while (isWhitespace(peek(0)))
+		shiftChars(1);
+
+	for (;;) {
+		int c = peek(0);
+
+		switch (c) {
+		case ',':
+			shiftChars(1);
+			/* fallthrough */
+		case '\r':
+		case '\n': /* Do not shift these! */
+		case EOF:
+			if (c != ',')
+				lexer_SetMode(LEXER_NORMAL);
+			if (i == sizeof(yylval.tzString)) {
+				i--;
+				warning(WARNING_LONG_STR, "Macro argument too long\n");
+			}
+			/* Trim whitespace */
+			while (i && isWhitespace(yylval.tzString[i - 1]))
+				i--;
+			yylval.tzString[i] = '\0';
+			return T_STRING;
+
+		case '\\': /* Character escape */
+			c = peek(1);
+			switch (c) {
+			case ',':
+			case '\\': /* Return that character unchanged */
+			case '"':
+			case '{':
+			case '}':
+				shiftChars(1);
+				break;
+			case 'n':
+				c = '\n';
+				shiftChars(1);
+				break;
+			case 'r':
+				c = '\r';
+				shiftChars(1);
+				break;
+			case 't':
+				c = '\t';
+				shiftChars(1);
+				break;
+
+			case EOF: /* Can't really print that one */
+				error("Illegal character escape at end of input\n");
+				c = '\\';
+				break;
+			default:
+				error("Illegal character escape '%s'\n", print(c));
+				c = '\\';
+				break;
+			}
+			break;
+
+		case '{': /* Symbol interpolation */
+			shiftChars(1);
+			char const *ptr = readInterpolation();
+
+			if (ptr) {
+				while (*ptr) {
+					if (i == sizeof(yylval.tzString))
+						break;
+					yylval.tzString[i++] = *ptr++;
+				}
+			}
+			continue; /* Do not copy an additional character */
+
+		/* Regular characters will just get copied */
+		}
+		if (i < sizeof(yylval.tzString)) /* Copy one extra to flag overflow */
+			yylval.tzString[i++] = c;
+		shiftChars(1);
+	}
 }
 
 /*
@@ -1548,11 +1630,16 @@
 int yylex(void)
 {
 restart:
-	if (lexerState->atLineStart
-	/* Newlines read within an expansion should not increase the line count */
-	 && (!lexerState->expansions || lexerState->expansions->distance)) {
-		lexerState->lineNo++;
-		lexerState->colNo = 0;
+	if (lexerState->atLineStart) {
+		/* Newlines read within an expansion should not increase the line count */
+		if (!lexerState->expansions || lexerState->expansions->distance) {
+			lexerState->lineNo++;
+			lexerState->colNo = 0;
+		}
+		if (lexerStateEOL) {
+			lexer_SetState(lexerStateEOL);
+			lexerStateEOL = NULL;
+		}
 	}
 
 	static int (* const lexerModeFuncs[])(void) = {
@@ -1572,6 +1659,7 @@
 			if (!lexerState->capturing) {
 				if (!yywrap())
 					goto restart;
+				return 0;
 			}
 		}
 	}