Improved error handling; added parser warnings

Sat, 14 Jul 2012 02:16:48 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sat, 14 Jul 2012 02:16:48 +0300
changeset 7
118d3d5db64f
parent 6
0005527cad62
child 8
c8bfa7e6ae1b

Improved error handling; added parser warnings

commands.cxx file | annotate | diff | comparison | revisions
parser.cxx file | annotate | diff | comparison | revisions
scriptreader.cxx file | annotate | diff | comparison | revisions
scriptreader.h file | annotate | diff | comparison | revisions
--- a/commands.cxx	Sat Jul 14 01:49:32 2012 +0300
+++ b/commands.cxx	Sat Jul 14 02:16:48 2012 +0300
@@ -48,6 +48,7 @@
 
 CommandDef* g_CommDef;
 
+#define MAX
 void ReadCommands () {
 	ScriptReader* r = new ScriptReader ((char*)"commands.def");
 	g_CommDef = NULL;
@@ -57,6 +58,11 @@
 	while (r->Next()) {
 		CommandDef* comm = new CommandDef;
 		
+		// Any more than 4 is a warning, any less is an error.
+		unsigned int c = r->token.count (const_cast<char*> (":"));
+		if (c < 4)
+			r->ParserError ("not enough parameters: got %d, expected 4", c);
+		
 		int n = 0;
 		str t = "";
 		for (unsigned int u = 0; u < r->token.len(); u++) {
@@ -89,7 +95,7 @@
 					else if (!t.compare ("bool"))
 						comm->returnvalue = RETURNVAL_BOOLEAN;
 					else
-						r->ParseError ("bad return value type `%s`", t.chars());
+						r->ParserError ("bad return value type `%s`", t.chars());
 					break;
 				case 3:
 					// Num args
@@ -99,6 +105,9 @@
 					// Max args
 					comm->maxargs = i;
 					break;
+				default:
+					r->ParserWarning ("too many parameters");
+					break;
 				}
 				
 				n++;
--- a/parser.cxx	Sat Jul 14 01:49:32 2012 +0300
+++ b/parser.cxx	Sat Jul 14 02:16:48 2012 +0300
@@ -51,7 +51,7 @@
 #define TOKEN_CHARS token.chars()
 #define TOKEN_IS(s) !token.compare (s)
 #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \
-	ParseError ("%ss may only be defined at top level!", token.chars());
+	ParserError ("%ss may only be defined at top level!", token.chars());
 
 int g_NumStates = 0;
 int g_NumEvents = 0;
@@ -66,7 +66,7 @@
 			// First ensure that the file can be opened
 			FILE* newfile = fopen (token.chars(), "r");
 			if (!newfile)
-				ParseError ("couldn't open included file `%s`!", token.chars());
+				ParserError ("couldn't open included file `%s`!", token.chars());
 			fclose (newfile);
 			ScriptReader* newreader = new ScriptReader (token.chars());
 			newreader->BeginParse (w);
@@ -79,7 +79,7 @@
 			
 			// State name must be a word.
 			if (statename.first (" ") != statename.len())
-				ParseError ("state name must be a single word! got `%s`", (char*)statename);
+				ParserError ("state name must be a single word! got `%s`", (char*)statename);
 			
 			// Must end in a colon
 			MustNext (":");
@@ -100,7 +100,7 @@
 			
 			EventDef* e = FindEventByName (token);
 			if (!e)
-				ParseError ("bad event! got `%s`\n", token.chars());
+				ParserError ("bad event! got `%s`\n", token.chars());
 			
 			MustNext ("{");
 			
@@ -118,15 +118,15 @@
 				g_CurMode = MODE_TOPLEVEL;
 				break;
 			default:
-				ParseError ("unexpected `}`");
+				ParserError ("unexpected `}`");
 			}
 		} else {
-			ParseError ("unknown keyword `%s`!", TOKEN_CHARS);
+			ParserError ("unknown keyword `%s`!", TOKEN_CHARS);
 		}
 	}
 	
 	if (g_CurMode != MODE_TOPLEVEL)
-		ParseError ("script did not end at top level! did you forget a `}`?\n");
+		ParserError ("script did not end at top level! did you forget a `}`?\n");
 	
 	/*
 	// State
--- a/scriptreader.cxx	Sat Jul 14 01:49:32 2012 +0300
+++ b/scriptreader.cxx	Sat Jul 14 02:16:48 2012 +0300
@@ -53,9 +53,11 @@
 	return false;
 }
 
-ScriptReader::ScriptReader (char* path) {
+ScriptReader::ScriptReader (str path) {
+	atnewline = false;
+	filepath = path;
 	if (!(fp = fopen (path, "r"))) {
-		error ("couldn't open %s for reading!\n", path);
+		error ("couldn't open %s for reading!\n", path.chars ());
 		exit (1);
 	}
 	
@@ -73,9 +75,14 @@
 	if (!fread (c, sizeof (char), 1, fp))
 		return 0;
 	
-	// If we just read a new line, increase current line number counter.
+	// We're at a newline, thus next char read will begin the next line
+	if (atnewline) {
+		atnewline = false;
+		curline++;
+	}
+	
 	if (c[0] == '\n')
-		curline++;
+		atnewline = true;
 	
 	return c[0];
 }
@@ -157,17 +164,28 @@
 void ScriptReader::MustNext (const char* c) {
 	if (!Next()) {
 		if (strlen (c))
-			ParseError ("expected `%s`, reached end of file instead\n", c);
+			ParserError ("expected `%s`, reached end of file instead\n", c);
 		else
-			ParseError ("expected a token, reached end of file instead\n");
+			ParserError ("expected a token, reached end of file instead\n");
 	}
 	
 	if (strlen (c) && token.compare (c) != 0) {
-		ParseError ("expected `%s`, got `%s` instead", c, token.chars());
+		ParserError ("expected `%s`, got `%s` instead", c, token.chars());
 	}
 }
 
-void ScriptReader::ParseError (const char* message, ...) {
+void ScriptReader::ParserError (const char* message, ...) {
+	PERFORM_FORMAT (message, outmessage);
+	ParserMessage ("\nParse error\n", outmessage);
+	exit (1);
+}
+
+void ScriptReader::ParserWarning (const char* message, ...) {
 	PERFORM_FORMAT (message, outmessage);
-	error ("Parse error on line %d:\n%s\n", curline, outmessage);
+	ParserMessage ("Warning: ", outmessage);
+}
+
+void ScriptReader::ParserMessage (const char* header, char* message) {
+	fprintf (stderr, "%sIn file %s, on line %d: %s\n",
+		header, filepath.chars(), curline, message);
 }
\ No newline at end of file
--- a/scriptreader.h	Sat Jul 14 01:49:32 2012 +0300
+++ b/scriptreader.h	Sat Jul 14 02:16:48 2012 +0300
@@ -56,21 +56,25 @@
 	// ====================================================================
 	// MEMBERS
 	FILE* fp;
+	str filepath;
 	unsigned int pos;
 	unsigned int curline;
 	str token;
 	bool tokenquoted;
+	bool atnewline;
 	
 	// ====================================================================
 	// METHODS
-	ScriptReader (char* path);
+	ScriptReader (str path);
 	~ScriptReader ();
 	char ReadChar ();
 	bool Next ();
 	str PeekNext ();
 	void Seek (unsigned int n, int origin);
 	void MustNext (const char* c = "");
-	void ParseError (const char* message, ...);
+	void ParserError (const char* message, ...);
+	void ParserWarning (const char* message, ...);
+	void ParserMessage (const char* header, char* message);
 	
 	void BeginParse (ObjWriter* w);
 };

mercurial