Added comment support

Mon, 16 Jul 2012 04:07:15 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Mon, 16 Jul 2012 04:07:15 +0300
changeset 28
fb46d3d40064
parent 27
15c06a191f9b
child 29
b4e09ae24bf1

Added comment support

commands.cxx file | annotate | diff | comparison | revisions
commands.def 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	Sun Jul 15 19:01:47 2012 +0300
+++ b/commands.cxx	Mon Jul 16 04:07:15 2012 +0300
@@ -142,15 +142,10 @@
 		numCommDefs++;
 	}
 	
-	/*
-	CommandDef* c;
-	ITERATE_COMMANDS (c) {
-		printf ("[%u] %s: %d, %d arguments, return type %d\n",
-			c->number, c->name.chars(), c->numargs, c->maxargs, c->returnvalue);
-	}
-	*/
+	delete r;
 	
-	delete r;
+	if (!numCommDefs)
+		error ("error: no commands defined!\n");
 	printf ("%d command definitions read.\n", numCommDefs);
 }
 
--- a/commands.def	Sun Jul 15 19:01:47 2012 +0300
+++ b/commands.def	Mon Jul 16 04:07:15 2012 +0300
@@ -1,3 +1,8 @@
+/* This file defines the commands botc will treat as valid. Do not edit unless
+ * you know what you are doing!
+ *
+ * Syntax: number:name:returntype:numargs:maxargs[:argumentlist]
+ */
 0:changestate:void:1:1:str(statename)
 1:delay:void:1:1:int(tics)
 2:rand:int:2:2:int(a):int(b)
--- a/parser.cxx	Sun Jul 15 19:01:47 2012 +0300
+++ b/parser.cxx	Mon Jul 16 04:07:15 2012 +0300
@@ -262,8 +262,6 @@
 	if (!g_stateSpawnDefined)
 		ParserError ("script must have a state named `stateSpawn`!");
 	
-	
-	
 	// Dump the last state's onenter and mainloop
 	w->WriteBuffers();
 	
--- a/scriptreader.cxx	Sun Jul 15 19:01:47 2012 +0300
+++ b/scriptreader.cxx	Mon Jul 16 04:07:15 2012 +0300
@@ -54,20 +54,22 @@
 }
 
 ScriptReader::ScriptReader (str path) {
-	atnewline = false;
-	filepath = path;
 	if (!(fp = fopen (path, "r"))) {
 		error ("couldn't open %s for reading!\n", path.chars ());
 		exit (1);
 	}
 	
+	filepath = path;
 	curline = 1;
 	curchar = 1;
 	pos = 0;
 	token = "";
+	atnewline = false;
+	commentmode = 0;
 }
 
 ScriptReader::~ScriptReader () {
+	FinalChecks ();
 	fclose (fp);
 }
 
@@ -90,12 +92,66 @@
 	return c[0];
 }
 
+char ScriptReader::PeekChar (int offset) {
+	// Store current position
+	long curpos = ftell (fp);
+	
+	// Forward by offset
+	fseek (fp, offset, SEEK_CUR);
+	
+	// Read the character
+	char* c = (char*)malloc (sizeof (char));
+	if (!fread (c, sizeof (char), 1, fp))
+		return 0;
+	
+	// Rewind back
+	fseek (fp, curpos, SEEK_SET);
+	
+	return c[0];
+}
+
 // true if was found, false if not.
 bool ScriptReader::Next () {
 	str tmp = "";
+	
 	while (!feof (fp)) {
+		// Check if the next token possibly starts a comment.
+		if (PeekChar () == '/' && !tmp.len()) {
+			char c2 = PeekChar (1);
+			// C++-style comment
+			if (c2 == '/')
+				commentmode = 1;
+			else if (c2 == '*')
+				commentmode = 2;
+			
+			// We don't need to actually read in the
+			// comment characters, since they will get
+			// ignored due to comment mode anyway.
+		}
+		
 		c = ReadChar ();
 		
+		// If this is a comment we're reading, check if this character
+		// gets the comment terminated, otherwise ignore it.
+		if (commentmode > 0) {
+			if (commentmode == 1 && c == '\n') {
+				// C++-style comments are terminated by a newline
+				commentmode = 0;
+				continue;
+			} else if (commentmode == 2 && c == '*') {
+				// C-style comments are terminated by a `*/`
+				if (PeekChar() == '/') {
+					commentmode = 0;
+					// Now the char has to be read in since we
+					// no longer are reading a comment
+					ReadChar ();
+				}
+			}
+			
+			// Otherwise, ignore it.
+			continue;
+		}
+		
 		// Non-alphanumber characters (sans underscore) break the word too.
 		// If there was prior data, the delimeter pushes the cursor back so
 		// that the next character will be the same delimeter. If there isn't,
@@ -243,4 +299,13 @@
 	case RETURNVAL_STRING: MustString (); break;
 	case RETURNVAL_BOOLEAN: MustBool (); break;
 	}
+}
+
+// Checks to be performed at the end of file
+void ScriptReader::FinalChecks () {
+	// If comment mode is 2 by the time the file ended, the
+	// comment was left unterminated. 1 is no problem, since
+	// it's terminated by newlines anyway.
+	if (commentmode == 2)
+		ParserError ("unterminated `/*`-style comment");
 }
\ No newline at end of file
--- a/scriptreader.h	Sun Jul 15 19:01:47 2012 +0300
+++ b/scriptreader.h	Mon Jul 16 04:07:15 2012 +0300
@@ -56,6 +56,7 @@
 	unsigned int curline;
 	unsigned int curchar;
 	str token;
+	int commentmode;
 	
 	// ====================================================================
 	// METHODS
@@ -63,6 +64,7 @@
 	ScriptReader (str path);
 	~ScriptReader ();
 	char ReadChar ();
+	char PeekChar (int offset = 0);
 	bool Next ();
 	str PeekNext ();
 	void Seek (unsigned int n, int origin);
@@ -76,6 +78,8 @@
 	void ParserError (const char* message, ...);
 	void ParserWarning (const char* message, ...);
 	
+	void FinalChecks ();
+	
 	// parser.cxx:
 	void BeginParse (ObjWriter* w);
 	void ParseCommand (CommandDef* comm, ObjWriter* w);

mercurial