Added mainloop/onenter/onexit support, fixed state writing.. this thing can compile the script for the `jumping arghbot` now!

Sat, 14 Jul 2012 17:24:21 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sat, 14 Jul 2012 17:24:21 +0300
changeset 16
393359908179
parent 15
284c2fc6c1cd
child 17
b4fcc69e426a

Added mainloop/onenter/onexit support, fixed state writing.. this thing can compile the script for the `jumping arghbot` now!

commands.cxx file | annotate | diff | comparison | revisions
events.cxx file | annotate | diff | comparison | revisions
main.cxx file | annotate | diff | comparison | revisions
objwriter.cxx file | annotate | diff | comparison | revisions
objwriter.h file | annotate | diff | comparison | revisions
parser.cxx file | annotate | diff | comparison | revisions
scriptreader.h file | annotate | diff | comparison | revisions
str.cxx file | annotate | diff | comparison | revisions
str.h file | annotate | diff | comparison | revisions
--- a/commands.cxx	Sat Jul 14 16:31:21 2012 +0300
+++ b/commands.cxx	Sat Jul 14 17:24:21 2012 +0300
@@ -50,7 +50,7 @@
 CommandDef* g_CommDef;
 
 void ReadCommands () {
-	ScriptReader* r = new ScriptReader ((char*)"commands.def");
+	ScriptReader* r = new ScriptReader ("commands.def");
 	g_CommDef = NULL;
 	CommandDef* curdef = g_CommDef;
 	unsigned int numCommDefs = 0; 
--- a/events.cxx	Sat Jul 14 16:31:21 2012 +0300
+++ b/events.cxx	Sat Jul 14 17:24:21 2012 +0300
@@ -48,7 +48,7 @@
 
 EventDef* g_EventDef;
 void ReadEvents () {
-	ScriptReader* r = new ScriptReader ((char*)"events.def");
+	ScriptReader* r = new ScriptReader ("events.def");
 	g_EventDef = NULL;
 	EventDef* curdef = g_EventDef;
 	unsigned int numEventDefs = 0;
--- a/main.cxx	Sat Jul 14 16:31:21 2012 +0300
+++ b/main.cxx	Sat Jul 14 17:24:21 2012 +0300
@@ -53,19 +53,21 @@
 #include "botcommands.h"
 
 int main (int argc, char** argv) {
+	// Print header
+	str header;
+	str headerline = "-=";
+	header.appendformat ("%s version %d.%d.%d", APPNAME, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
+	headerline.repeat ((header.len()/2)-1);
+	headerline += '-';
+	printf ("%s\n%s\n", header.chars(), headerline.chars());
+	
 	if (argc != 3) {
 		fprintf (stderr, "usage: %s: <infile> <outFile>\n", argv[0]);
 		exit (1);
 	}
 	
-	// Print header
-	str header;
-	str headerline = "=-";
-	header.appendformat ("%s version %d.%d.%d", APPNAME, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
-	headerline.repeat ((header.len()/2)-1);
-	printf ("%s\n%s\n", header.chars(), headerline.chars());
-	
 	// Read definitions
+	printf ("Reading definitions...\n");
 	ReadEvents ();
 	ReadCommands ();
 	
@@ -74,15 +76,17 @@
 	ObjWriter *w = new ObjWriter (argv[2]);
 	
 	// We're set, begin parsing :)
+	printf ("Parsing script..\n");
 	r->BeginParse (w);
 	
-	// Clear out the junk afterwards
+	// Parse done, print statistics
+	printf ("%d states written\n", g_NumStates);
+	printf ("%d events written\n", g_NumEvents);
+	printf ("-- %u bytes written to %s\n", w->numWrittenBytes, argv[2]);
+	
+	// Clear out the junk
 	delete r;
 	delete w;
-	
-	// Print statistics
-	printf ("%d states written\n", g_NumStates);
-	printf ("%d events written\n", g_NumEvents);
 }
 
 void error (const char* text, ...) {
--- a/objwriter.cxx	Sat Jul 14 16:31:21 2012 +0300
+++ b/objwriter.cxx	Sat Jul 14 17:24:21 2012 +0300
@@ -38,6 +38,7 @@
  *	POSSIBILITY OF SUCH DAMAGE.
  */
 
+#define __OBJWRITER_CXX__
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -48,6 +49,7 @@
 #include "bots.h"
 
 ObjWriter::ObjWriter (str path) {
+	numWrittenBytes = 0;
 	fp = fopen (path, "w");
 	CHECK_FILE (fp, path, "writing");
 }
--- a/objwriter.h	Sat Jul 14 16:31:21 2012 +0300
+++ b/objwriter.h	Sat Jul 14 17:24:21 2012 +0300
@@ -50,6 +50,7 @@
 	// ====================================================================
 	// MEMBERS
 	FILE* fp;
+	unsigned int numWrittenBytes;
 	
 	// ====================================================================
 	// METHODS
@@ -61,6 +62,7 @@
 	
 	template <class T> void Write (T stuff) {
 		fwrite (&stuff, sizeof (T), 1, fp);
+		numWrittenBytes += sizeof (T);
 	}
 	
 	// Cannot use default arguments in function templates..
--- a/parser.cxx	Sat Jul 14 16:31:21 2012 +0300
+++ b/parser.cxx	Sat Jul 14 17:24:21 2012 +0300
@@ -56,8 +56,10 @@
 int g_NumEvents = 0;
 int g_CurMode = MODE_TOPLEVEL;
 str g_CurState = "";
+bool g_stateSpawnDefined = false;
 
 void ScriptReader::BeginParse (ObjWriter* w) {
+	bool gotMainLoop = false;
 	while (Next()) {
 		// printf ("got token %s\n", token.chars());
 		if (!token.compare ("#include")) {
@@ -78,18 +80,32 @@
 			// State name must be a word.
 			if (token.first (" ") != token.len())
 				ParserError ("state name must be a single word! got `%s`", token.chars());
+			str statename = token;
+			
+			// stateSpawn is special - it *must* be defined. If we
+			// encountered it, then mark down that we have it.
+			if (!token.icompare ("stateSpawn"))
+				g_stateSpawnDefined = true;
 			
 			// Must end in a colon
 			MustNext (":");
 			
+			// If the previous state did not define a mainloop,
+			// define a dummy one now, since one has to be present.
+			if (g_CurState.compare ("") != 0 && !gotMainLoop) {
+				w->Write (DH_MAINLOOP);
+				w->Write (DH_ENDMAINLOOP);
+			}
+			
 			w->Write (DH_STATENAME);
-			w->Write (token.len());
-			w->WriteString (token);
+			w->Write (statename.len());
+			w->WriteString (statename);
 			w->Write (DH_STATEIDX);
 			w->Write (g_NumStates);
 			
 			g_NumStates++;
 			g_CurState = token;
+			gotMainLoop = false;
 		} else if (!token.compare ("event")) {
 			MUST_TOPLEVEL
 			
@@ -107,17 +123,32 @@
 			w->Write (DH_EVENT);
 			w->Write<long> (e->number);
 			g_NumEvents++;
+		} else if (!token.compare ("mainloop")) {
+			MUST_TOPLEVEL
+			MustNext ("{");
+			g_CurMode = MODE_MAINLOOP;
+			w->Write (DH_MAINLOOP);
+			gotMainLoop = true;
+		} else if (!token.compare ("onenter") || !token.compare ("onexit")) {
+			MUST_TOPLEVEL
+			bool onenter = !token.compare ("onenter");
+			
+			MustNext ("{");
+			g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT;
+			w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
 		} else if (!token.compare ("}")) {
+			// Closing brace
+			int dataheader =	(g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
+						(g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
+						(g_CurMode == MODE_ONENTER) ? DH_ENDONENTER :
+						(g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1;
+			
+			if (dataheader == -1)
+				ParserError ("unexpected `}`");
+			
 			// Closing brace..
-			switch (g_CurMode) {
-			case MODE_EVENT:
-				// Brace closes event.
-				w->Write (DH_ENDEVENT);
-				g_CurMode = MODE_TOPLEVEL;
-				break;
-			default:
-				ParserError ("unexpected `}`");
-			}
+			w->Write (dataheader);
+			g_CurMode = MODE_TOPLEVEL;
 		} else {
 			// Check if it's a command.
 			CommandDef* comm = GetCommandByName (token);
@@ -129,7 +160,11 @@
 	}
 	
 	if (g_CurMode != MODE_TOPLEVEL)
-		ParserError ("script did not end at top level! did you forget a `}`?\n");
+		ParserError ("script did not end at top level! did you forget a `}`?");
+	
+	// stateSpawn must be defined!
+	if (!g_stateSpawnDefined)
+		ParserError ("script must have a state named `stateSpawn`!");
 	
 	/*
 	// State
@@ -151,6 +186,10 @@
 }
 
 void ScriptReader::ParseCommand (CommandDef* comm, ObjWriter* w) {
+	// If this was defined at top-level, we stop right at square one!
+	if (g_CurMode == MODE_TOPLEVEL)
+		ParserError ("no commands allowed at top level!");
+	
 	w->Write<long> (DH_COMMAND);
 	w->Write<long> (comm->number);
 	w->Write<long> (comm->maxargs);
--- a/scriptreader.h	Sat Jul 14 16:31:21 2012 +0300
+++ b/scriptreader.h	Sat Jul 14 17:24:21 2012 +0300
@@ -49,7 +49,10 @@
 // Where is the parser at?
 enum parsermode {
 	MODE_TOPLEVEL,	// at top level
-	MODE_EVENT	// inside event definition
+	MODE_EVENT,	// inside event definition
+	MODE_MAINLOOP,	// inside mainloop
+	MODE_ONENTER,	// inside onenter
+	MODE_ONEXIT,	// inside onexit
 };
 
 class ScriptReader {
--- a/str.cxx	Sat Jul 14 16:31:21 2012 +0300
+++ b/str.cxx	Sat Jul 14 17:24:21 2012 +0300
@@ -340,6 +340,18 @@
 	return compare (c.chars());
 }
 
+int str::icompare (const char* c) {
+	return icompare (str ((char*)c));
+}
+
+int str::icompare (str c) {
+	str a = text;
+	a.tolower();
+	str b = c;
+	b.tolower();
+	return strcmp (a.chars(), b.chars());
+}
+
 // ============================================================================
 str str::tolower () {
 	str n = text;
--- a/str.h	Sat Jul 14 16:31:21 2012 +0300
+++ b/str.h	Sat Jul 14 17:24:21 2012 +0300
@@ -132,8 +132,11 @@
 	// Convert string to upper case
 	str toupper ();
 	
+	// Compare this string with another
 	int compare (const char* c);
 	int compare (str c);
+	int icompare (str c);
+	int icompare (const char* c);
 	
 	// Counts the amount of substrings in the string
 	unsigned int count (char* s);

mercurial