shithub: rgbds

Download patch

ref: 5c7db42fc4bdbd4a7755423876b7554addf86799
parent: 4be92e14e622f0e8d01737e37a0e60f87a7d8a40
author: YamaArashi <[email protected]>
date: Fri Aug 22 22:55:52 EDT 2014

Added ELIF

In addition, make some formatting changes, and add some extra error handling (for when ELIF, ELSE, or ENDC are encountered without a corresponding IF).

--- a/include/asm/asm.h
+++ b/include/asm/asm.h
@@ -23,6 +23,7 @@
 extern ULONG nPC;
 extern ULONG nPass;
 extern ULONG nIFDepth;
+extern bool skipElif;
 extern char tzCurrentFileName[_MAX_PATH + 1];
 extern struct Section *pCurrentSection;
 extern struct sSymbol *tHashedSymbols[HASHSIZE];
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -289,71 +289,76 @@
 	yyskipbytes( ulNewMacroSize+4 );
 }
 
-ULONG	isIf( char *s )
+ULONG	isIf(char *s)
 {
-	return( (strncasecmp(s,"If",2)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[2]) );
+	return((strncasecmp(s,"If",2) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[2]));
 }
 
-ULONG	isElse( char *s )
+ULONG	isElif(char *s)
 {
-	return( (strncasecmp(s,"Else",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
+	return((strncasecmp(s,"Elif",4) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[4]));
 }
 
-ULONG	isEndc( char *s )
+ULONG	isElse(char *s)
 {
-	return( (strncasecmp(s,"Endc",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
+	return((strncasecmp(s,"Else",4) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[4]));
 }
 
-void	if_skip_to_else( void )
+ULONG	isEndc(char *s)
 {
-	SLONG	level=1, len, instring=0;
-	char	*src=pCurrentBuffer->pBuffer;
+	return((strncasecmp(s,"Endc",4) == 0) && isWhiteSpace(s[-1]) && isWhiteSpace(s[4]));
+}
 
-	while( *src && level )
-	{
-		if( *src=='\n' )
-			nLineNo+=1;
+void	if_skip_to_else()
+{
+	SLONG level = 1;
+	bool inString = false;
+	char *src=pCurrentBuffer->pBuffer;
 
-		if( instring==0 )
-		{
-			if( isIf(src) )
-			{
-				level+=1;
-				src+=2;
-			}
-			else if( level==1 && isElse(src) )
-			{
-				level-=1;
-				src+=4;
-			}
-			else if( isEndc(src) )
-			{
-				level-=1;
-				if( level!=0 )
-					src+=4;
-			}
-			else
-			{
-				if( *src=='\"' )
-					instring=1;
-				src+=1;
-			}
+	while (*src && level) {
+		if (*src == '\n') {
+			nLineNo++;
 		}
-		else
-		{
-			if( *src=='\\' )
-			{
-				src+=2;
+
+		if (!inString) {
+			if (isIf(src)) {
+				level++;
+				src += 2;
+
+			} else if (level == 1 && isElif(src)) {
+				level--;
+				skipElif = false;
+
+			} else if (level == 1 && isElse(src)) {
+				level--;
+				src += 4;
+
+			} else if (isEndc(src)) {
+				level--;
+				if (level != 0) {
+					src += 4;
+				}
+
+			} else {
+				if (*src=='\"') {
+					inString = true;
+				}
+				src++;
 			}
-			else if( *src=='\"' )
-			{
-				src+=1;
-				instring=0;
+		} else {
+			switch (*src) {
+			case '\\':
+				src += 2;
+				break;
+
+			case '\"':
+				src++;
+				inString = false;
+
+			default:
+				src++;
+				break;
 			}
-			else
-			{
-				src+=1;
-			}
 		}
 	}
 
@@ -361,58 +366,57 @@
 		fatalerror("Unterminated IF construct");
 	}
 
-	len=src-pCurrentBuffer->pBuffer;
+	SLONG len = src - pCurrentBuffer->pBuffer;
 
-	yyskipbytes( len );
-	yyunput( '\n' );
-	nLineNo-=1;
+	yyskipbytes(len);
+	yyunput('\n');
+	nLineNo--;
 }
 
-void	if_skip_to_endc( void )
+void	if_skip_to_endc()
 {
-	SLONG	level=1, len, instring=0;
-	char	*src=pCurrentBuffer->pBuffer;
+	SLONG level = 1;
+	bool inString = false;
+	char *src=pCurrentBuffer->pBuffer;
 
-	while( *src && level )
-	{
-		if( *src=='\n' )
-			nLineNo+=1;
+	while (*src && level) {
+		if (*src == '\n') {
+			nLineNo++;
+		}
 
-		if( instring==0 )
-		{
-			if( isIf(src) )
-			{
-				level+=1;
-				src+=2;
+		if (!inString) {
+			if (isIf(src)) {
+				level++;
+				src += 2;
+
+			} else if (isEndc(src)) {
+				level--;
+				if (level != 0) {
+					src += 4;
+				}
+
+			} else {
+				if (*src=='\"') {
+					inString = true;
+				}
+				src++;
 			}
-			else if( isEndc(src) )
-			{
-				level-=1;
-				if( level!=0 )
-					src+=4;
-			}
-			else
-			{
-				if( *src=='\"' )
-					instring=1;
-				src+=1;
-			}
 		}
-		else
-		{
-			if( *src=='\\' )
-			{
-				src+=2;
+		else {
+			switch (*src) {
+			case '\\':
+				src += 2;
+				break;
+
+			case '\"':
+				src++;
+				inString = false;
+				break;
+
+			default:
+				src++;
+				break;
 			}
-			else if( *src=='\"' )
-			{
-				src+=1;
-				instring=0;
-			}
-			else
-			{
-				src+=1;
-			}
 		}
 	}
 
@@ -420,11 +424,11 @@
 		fatalerror("Unterminated IF construct");
 	}
 
-	len=src-pCurrentBuffer->pBuffer;
+	SLONG len = src - pCurrentBuffer->pBuffer;
 
-	yyskipbytes( len );
-	yyunput( '\n' );
-	nLineNo-=1;
+	yyskipbytes(len);
+	yyunput('\n');
+	nLineNo--;
 }
 
 %}
@@ -492,7 +496,7 @@
 %token	<tzSym> T_POP_SET
 %token	<tzSym> T_POP_EQUS
 
-%token	T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_IF T_POP_ELSE T_POP_ENDC
+%token	T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_IF T_POP_ELIF T_POP_ELSE T_POP_ENDC
 %token	T_POP_IMPORT T_POP_EXPORT T_POP_GLOBAL
 %token	T_POP_DB T_POP_DS T_POP_DW T_POP_DL
 %token	T_POP_SECTION
@@ -627,6 +631,7 @@
 				|	printt
 				|	printv
 				|	if
+				|	elif
 				|	else
 				|	endc
 				|	import
@@ -867,26 +872,47 @@
 					}
 ;
 
-if				:	T_POP_IF const
-					{
-						nIFDepth+=1;
-						if( !$2 )
-						{
-							if_skip_to_else();	/* will continue parsing just after ELSE or just at ENDC keyword */
+if				:	T_POP_IF const {
+						nIFDepth++;
+						if (!$2) {
+							if_skip_to_else(); // Continue parsing after ELSE, or at ELIF or ENDC keyword
 						}
-					}
+					};
 
-else			:	T_POP_ELSE
-					{
-						if_skip_to_endc();		/* will continue parsing just at ENDC keyword */
-					}
-;
+elif			:	T_POP_ELIF const {
+						if (nIFDepth <= 0) {
+							fatalerror("Found ELIF outside an IF construct");
+						}
 
-endc			:	T_POP_ENDC
-					{
-						nIFDepth-=1;
-					}
-;
+						if (skipElif) {
+							// This is for when ELIF is reached at the end of an IF or ELIF block for which the condition was true.
+							if_skip_to_endc(); // Continue parsing at ENDC keyword
+
+						} else {
+							// This is for when ELIF is skipped to because the condition of the previous IF or ELIF block was false.
+							skipElif = true;
+
+							if (!$2) {
+								if_skip_to_else(); // Continue parsing after ELSE, or at ELIF or ENDC keyword
+							}
+						}
+					};
+
+else			:	T_POP_ELSE {
+						if (nIFDepth <= 0) {
+							fatalerror("Found ELSE outside an IF construct");
+						}
+
+						if_skip_to_endc(); // Continue parsing at ENDC keyword
+					};
+
+endc			:	T_POP_ENDC {
+						if (nIFDepth <= 0) {
+							fatalerror("Found ENDC outside an IF construct");
+						}
+
+						nIFDepth--;
+					};
 
 const_3bit		:	const
 					{
--- a/src/asm/globlex.c
+++ b/src/asm/globlex.c
@@ -329,6 +329,7 @@
 
 	{"if", T_POP_IF},
 	{"else", T_POP_ELSE},
+	{"elif", T_POP_ELIF},
 	{"endc", T_POP_ENDC},
 
 	{"wram0", T_SECT_WRAM0},
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -23,6 +23,7 @@
 clock_t nStartClock, nEndClock;
 SLONG nLineNo;
 ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors;
+bool skipElif;
 
 extern int yydebug;
 
@@ -414,6 +415,7 @@
 	nLineNo = 1;
 	nTotalLines = 0;
 	nIFDepth = 0;
+	skipElif = true;
 	nPC = 0;
 	nPass = 1;
 	nErrors = 0;
@@ -440,6 +442,7 @@
 	nTotalLines = 0;
 	nLineNo = 1;
 	nIFDepth = 0;
+	skipElif = true;
 	nPC = 0;
 	nPass = 2;
 	nErrors = 0;