Added if() support

Mon, 30 Jul 2012 03:38:02 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Mon, 30 Jul 2012 03:38:02 +0300
changeset 38
e4bbd540663b
parent 37
c349dca807f9
child 39
07b7ab8080cf

Added if() support

commands.cxx file | annotate | diff | comparison | revisions
databuffer.h 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.cxx file | annotate | diff | comparison | revisions
scriptreader.h file | annotate | diff | comparison | revisions
stringtable.cxx file | annotate | diff | comparison | revisions
--- a/commands.cxx	Sun Jul 29 16:55:32 2012 +0300
+++ b/commands.cxx	Mon Jul 30 03:38:02 2012 +0300
@@ -122,9 +122,10 @@
 			if (curarg >= comm->numargs) {
 				r->MustNext ("=");
 				switch (type) {
-				case RETURNVAL_INT: r->MustNumber(); break;
+				case RETURNVAL_INT:
+				case RETURNVAL_BOOLEAN:
+					r->MustNumber(); break;
 				case RETURNVAL_STRING: r->MustString(); break;
-				case RETURNVAL_BOOLEAN: r->MustBool(); break;
 				}
 				
 				comm->defvals[curarg] = r->token;
--- a/databuffer.h	Sun Jul 29 16:55:32 2012 +0300
+++ b/databuffer.h	Mon Jul 30 03:38:02 2012 +0300
@@ -222,6 +222,13 @@
 			}
 		}
 	}
+	
+	// Adjusts a mark to the current position
+	void MoveMark (unsigned int mark) {
+		if (!marks[mark])
+			return;
+		marks[mark]->pos = writesize - sizeof (word);
+	}
 };
 
 #endif // __DATABUFFER_H__
\ No newline at end of file
--- a/main.cxx	Sun Jul 29 16:55:32 2012 +0300
+++ b/main.cxx	Mon Jul 30 03:38:02 2012 +0300
@@ -64,6 +64,7 @@
 	"onexit",
 	"var",
 	"goto",
+	"if",
 	
 	// These ones aren't implemented yet but I plan to do so, thus they are
 	// reserved. Also serves as a to-do list of sorts for me. >:F
@@ -76,7 +77,6 @@
 	"enum", // Would enum actually be useful? I think so.
 	"for",
 	"func", // Would function support need external support from zandronum?
-	"if",
 	"return",
 	"switch",
 	"while"
@@ -169,17 +169,17 @@
 	
 	// Parse done, print statistics and write to file
 	unsigned int globalcount = CountGlobalVars ();
-	printf ("%u/%u global variable%s\n", globalcount, MAX_SCRIPT_VARIABLES, PLURAL (globalcount));
+	printf ("%u / %u global variable%s\n", globalcount, MAX_SCRIPT_VARIABLES, PLURAL (globalcount));
 	printf ("%d state%s written\n", g_NumStates, PLURAL (g_NumStates));
 	printf ("%d event%s written\n", g_NumEvents, PLURAL (g_NumEvents));
 	w->WriteToFile ();
 	
 	// Clear out the junk
-	printf ("clear r\n");
 	delete r;
-	printf ("clear w\n");
 	delete w;
-	printf ("done!\n");
+	
+	// Done!
+	exit (0);
 }
 
 // ============================================================================
--- a/objwriter.cxx	Sun Jul 29 16:55:32 2012 +0300
+++ b/objwriter.cxx	Mon Jul 30 03:38:02 2012 +0300
@@ -59,16 +59,6 @@
 	filepath = path;
 }
 
-ObjWriter::~ObjWriter () {
-	delete MainBuffer;
-	delete OnEnterBuffer;
-	
-	// This crashes for some reason o_O
-	// Should make no difference anyway, since ObjWriter
-	// is only deleted at the end of the program anyway
-	// delete MainLoopBuffer;
-}
-
 void ObjWriter::WriteString (char* s) {
 	Write<long> (strlen (s));
 	for (unsigned int u = 0; u < strlen (s); u++)
@@ -123,7 +113,7 @@
 			WriteString (g_StringTable[a]);
 	}
 	
-	printf ("%u string%s written\n", stringcount, PLURAL (stringcount));
+	printf ("%u / %u string%s written\n", stringcount, MAX_LIST_STRINGS, PLURAL (stringcount));
 }
 
 // Write main buffer to file
@@ -139,7 +129,19 @@
 		for (unsigned int r = 0; r < MAX_MARKS; r++) {
 			if (MainBuffer->refs[r] && MainBuffer->refs[r]->pos == x) {
 				word ref = static_cast<word> (MainBuffer->marks[MainBuffer->refs[r]->num]->pos);
+				printf ("insert position %ld at script pos %u\n",
+					ref, x);
 				WriteDataToFile<word> (ref);
+				
+				// This reference is now used up
+				delete MainBuffer->refs[r];
+				MainBuffer->refs[r] = NULL;
+				
+				// All other references need their positions bumped up as the
+				// bytecode gained 4 more bytes with the written reference
+				for (unsigned int s = 0; s < MAX_MARKS; s++)
+					if (MainBuffer->refs[s])
+						MainBuffer->refs[s]->pos += sizeof (word);
 			}
 		}
 		
@@ -177,4 +179,9 @@
 			return u;
 	}
 	return MAX_MARKS;
+}
+
+// Moves a mark to the current position
+void ObjWriter::MoveMark (unsigned int mark) {
+	GetCurrentBuffer()->MoveMark (mark);
 }
\ No newline at end of file
--- a/objwriter.h	Sun Jul 29 16:55:32 2012 +0300
+++ b/objwriter.h	Mon Jul 30 03:38:02 2012 +0300
@@ -64,7 +64,6 @@
 	// ====================================================================
 	// METHODS
 	ObjWriter (str path);
-	~ObjWriter ();
 	void WriteString (char* s);
 	void WriteString (const char* s);
 	void WriteString (str s);
@@ -77,6 +76,7 @@
 	unsigned int AddMark (int type, str name);
 	unsigned int FindMark (int type, str name);
 	unsigned int AddReference (unsigned int mark);
+	void MoveMark (unsigned int mark);
 	
 	template <class T> void Write (T stuff) {
 		DataBuffer* buffer = GetCurrentBuffer ();
--- a/parser.cxx	Sun Jul 29 16:55:32 2012 +0300
+++ b/parser.cxx	Mon Jul 30 03:38:02 2012 +0300
@@ -63,14 +63,14 @@
 str g_CurState = "";
 bool g_stateSpawnDefined = false;
 bool g_GotMainLoop = false;
-int g_StructStack = 0;
+unsigned int g_BlockStackCursor = 0;
 
 // ============================================================================
 // Main parser code. Begins read of the script file, checks the syntax of it
 // and writes the data to the object file via ObjWriter - which also takes care
 // of necessary buffering so stuff is written in the correct order.
 void ScriptReader::BeginParse (ObjWriter* w) {
-	g_StructStack = 0;
+	g_BlockStackCursor = 0;
 	while (Next()) {
 		printf ("BeginParse: token: `%s`\n", token.chars());
 		if (!token.icompare ("state")) {
@@ -202,15 +202,53 @@
 			continue;
 		}
 		
+		// If
+		if (!token.icompare ("if")) {
+			// Condition
+			MustNext ("(");
+			
+			// Read the expression and write it.
+			MustNext ();
+			DataBuffer* c = ParseExpression (TYPE_INT);
+			w->WriteBuffer (c);
+			delete c;
+			
+			MustNext (")");
+			MustNext ("{");
+			
+			// Add a mark - to here temporarily - and add a reference to it.
+			// Upon a closing brace, the mark will be adjusted.
+			unsigned int marknum = w->AddMark (MARKTYPE_IF, "");
+			
+			// Use DH_IFNOTGOTO - if the expression is not true, we goto the mark
+			// we just defined - and this mark will be at the end of the block.
+			w->Write<word> (DH_IFNOTGOTO);
+			w->AddReference (marknum);
+			
+			// Store it in the block stack
+			blockstack[g_BlockStackCursor] = marknum;
+			g_BlockStackCursor++;
+			continue;
+		}
+		
 		if (!token.compare ("}")) {
-			// If this was done inside the struct stack (i.e.
-			// inside "if" for instance), it does not end the mode.
-			if (g_StructStack > 0) {
-				g_StructStack--;
+			// Closing brace
+			
+			// If we're in the block stack, we're descending down from it now
+			if (g_BlockStackCursor > 0) {
+				// Adjust its closing mark so that it's here.
+				unsigned int marknum = blockstack[g_BlockStackCursor];
+				if (marknum != MAX_MARKS) {
+					// printf ("\tblock %d stack mark moved from %d ",
+						g_BlockStackCursor, w->GetCurrentBuffer()->marks[marknum]->pos);
+					w->MoveMark (marknum);
+					// printf ("to %d\n", w->GetCurrentBuffer()->marks[marknum]->pos);
+				}
+				
+				g_BlockStackCursor--;
 				continue;
 			}
 			
-			// Closing brace
 			int dataheader =	(g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
 						(g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
 						(g_CurMode == MODE_ONENTER) ? DH_ENDONENTER :
@@ -367,6 +405,12 @@
 	case OPER_MULTIPLY: return DH_MULTIPLY;
 	case OPER_DIVIDE: return DH_DIVIDE;
 	case OPER_MODULUS: return DH_MODULUS;
+	case OPER_EQUALS: return DH_EQUALS;
+	case OPER_NOTEQUALS: return DH_NOTEQUALS;
+	case OPER_LESSTHAN: return DH_LESSTHAN;
+	case OPER_GREATERTHAN: return DH_GREATERTHAN;
+	case OPER_LESSTHANEQUALS: return DH_LESSTHANEQUALS;
+	case OPER_GREATERTHANEQUALS: return DH_GREATERTHANEQUALS;
 	}
 	
 	error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper);
@@ -431,7 +475,12 @@
 		oper += token;
 	
 	// Check one-char operators
-	int o =	!oper.compare ("=") ? OPER_ASSIGN :
+	bool equalsnext = !PeekNext (peek ? 1 : 0).compare ("=");
+	printf ("operator one-char: %s\nequals is%s next (`%s`)\n", oper.chars(),
+		(equalsnext) ? "" : " not", PeekNext (peek ? 1 : 0).chars());
+	int o =	(!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN :
+		(!oper.compare (">") && !equalsnext) ? OPER_GREATERTHAN :
+		(!oper.compare ("<") && !equalsnext) ? OPER_LESSTHAN :
 		!oper.compare ("+") ? OPER_ADD :
 		!oper.compare ("-") ? OPER_SUBTRACT :
 		!oper.compare ("*") ? OPER_MULTIPLY :
@@ -446,11 +495,17 @@
 	// Two-char operators
 	oper += PeekNext (peek ? 1 : 0);
 	
+	printf ("operator two-char: %s\n", oper.chars());
+	
 	o =	!oper.compare ("+=") ? OPER_ASSIGNADD :
 		!oper.compare ("-=") ? OPER_ASSIGNSUB :
 		!oper.compare ("*=") ? OPER_ASSIGNMUL :
 		!oper.compare ("/=") ? OPER_ASSIGNDIV :
 		!oper.compare ("%=") ? OPER_ASSIGNMOD :
+		!oper.compare ("==") ? OPER_EQUALS :
+		!oper.compare ("!=") ? OPER_NOTEQUALS :
+		!oper.compare (">=") ? OPER_GREATERTHANEQUALS :
+		!oper.compare ("<=") ? OPER_LESSTHANEQUALS :
 		-1;
 	
 	if (o != -1)
@@ -502,6 +557,7 @@
 			// All values are written unsigned - thus we need to write the value's
 			// absolute value, followed by an unary minus if it was negative.
 			b->Write<word> (DH_PUSHNUMBER);
+			
 			long v = atoi (token.chars ());
 			b->Write<word> (static_cast<word> (abs (v)));
 			if (v < 0)
--- a/scriptreader.cxx	Sun Jul 29 16:55:32 2012 +0300
+++ b/scriptreader.cxx	Mon Jul 30 03:38:02 2012 +0300
@@ -45,6 +45,7 @@
 #include "common.h"
 #include "scriptreader.h"
 
+// ============================================================================
 ScriptReader::ScriptReader (str path) {
 	token = "";
 	prevtoken = "";
@@ -58,6 +59,7 @@
 	commentmode = 0;
 }
 
+// ============================================================================
 ScriptReader::~ScriptReader () {
 	// If comment mode is 2 by the time the file ended, the
 	// comment was left unterminated. 1 is no problem, since
@@ -73,6 +75,7 @@
 	}
 }
 
+// ============================================================================
 // Opens a file and pushes its pointer to stack
 void ScriptReader::OpenFile (str path) {
 	if (fc+1 >= MAX_FILESTACK) 
@@ -100,9 +103,11 @@
 	atnewline = 0;
 }
 
+// ============================================================================
+// Closes the current file
 void ScriptReader::CloseFile (unsigned int u) {
 	if (u >= MAX_FILESTACK)
- 		u = fc;
+		u = fc;
 	
 	if (!fp[u])
 		return;
@@ -115,6 +120,7 @@
 		fseek (fp[fc], savedpos[fc], SEEK_SET);
 }
 
+// ============================================================================
 char ScriptReader::ReadChar () {
 	if (feof (fp[fc]))
 		return 0;
@@ -141,6 +147,8 @@
 	return c[0];
 }
 
+// ============================================================================
+// Peeks the next character
 char ScriptReader::PeekChar (int offset) {
 	// Store current position
 	long curpos = ftell (fp[fc]);
@@ -162,6 +170,7 @@
 	return c[0];
 }
 
+// ============================================================================
 // Read a token from the file buffer. Returns true if token was found, false if not.
 bool ScriptReader::Next (bool peek) {
 	prevpos = ftell (fp[fc]);
@@ -252,15 +261,7 @@
 	return true;
 }
 
-void ScriptReader::Prev () {
-	if (!prevpos)
-		error ("ScriptReader::Prev: cannot go back twice!\n");
-	
-	fseek (fp[fc], prevpos, SEEK_SET);
-	prevpos = 0;
-	token = prevtoken;
-}
-
+// ============================================================================
 // Returns the next token without advancing the cursor.
 str ScriptReader::PeekNext (int offset) {
 	// Store current information
@@ -283,6 +284,7 @@
 	return tmp;
 }
 
+// ============================================================================
 void ScriptReader::Seek (unsigned int n, int origin) {
 	switch (origin) {
 	case SEEK_SET:
@@ -300,6 +302,7 @@
 		Next();
 }
 
+// ============================================================================
 void ScriptReader::MustNext (const char* c) {
 	if (!Next()) {
 		if (strlen (c))
@@ -312,22 +315,26 @@
 		MustThis (c);
 }
 
+// ============================================================================
 void ScriptReader::MustThis (const char* c) {
 	if (token.compare (c) != 0)
 		ParserError ("expected `%s`, got `%s` instead", c, token.chars());
 }
 
+// ============================================================================
 void ScriptReader::ParserError (const char* message, ...) {
 	PERFORM_FORMAT (message, outmessage);
 	ParserMessage ("\nError: ", outmessage);
 	exit (1);
 }
 
+// ============================================================================
 void ScriptReader::ParserWarning (const char* message, ...) {
 	PERFORM_FORMAT (message, outmessage);
 	ParserMessage ("Warning: ", outmessage);
 }
 
+// ============================================================================
 void ScriptReader::ParserMessage (const char* header, char* message) {
 	if (fc >= 0 && fc < MAX_FILESTACK)
 		fprintf (stderr, "%sIn file %s, at line %u, col %u: %s\n",
@@ -336,6 +343,7 @@
 		fprintf (stderr, "%s%s\n", header, message);
 }
 
+// ============================================================================
 // if gotquote == 1, the current token already holds the quotation mark.
 void ScriptReader::MustString (bool gotquote) {
 	if (gotquote)
@@ -360,6 +368,7 @@
 	token = string;
 }
 
+// ============================================================================
 void ScriptReader::MustNumber (bool fromthis) {
 	str num;
 	if (!fromthis)
@@ -374,33 +383,14 @@
 		num += token;
 	}
 	
-	// Result must be a number.
-	if (!num.isnumber())
-		ParserError ("expected a number, got `%s`", num.chars());
-	
-	// Save the number into the token.
-	token = num;
-}
-
-void ScriptReader::MustBool () {
-	MustNext();
-	if (!token.compare ("0") || !token.compare ("1") ||
-	    !token.compare ("true") || !token.compare ("false") ||
-	    !token.compare ("yes") || !token.compare ("no")) {
-			return;
-	}
-	
-	ParserError ("expected a boolean value, got `%s`", token.chars());
-}
-
-bool ScriptReader::BoolValue () {
-	return (!token.compare ("1") || !token.compare ("true") || !token.compare ("yes"));
-}
-
-void ScriptReader::MustValue (int type) {
-	switch (type) {
-	case RETURNVAL_INT: MustNumber (); break;
-	case RETURNVAL_STRING: MustString (); break;
-	case RETURNVAL_BOOLEAN: MustBool (); break;
+	// "true" and "false" are valid numbers
+	if (!token.icompare ("true"))
+		token = "1";
+	else if (!token.icompare ("false"))
+		token = "0";
+	else {
+		if (!num.isnumber())
+			ParserError ("expected a number, got `%s`", num.chars());
+		token = num;
 	}
 }
\ No newline at end of file
--- a/scriptreader.h	Sun Jul 29 16:55:32 2012 +0300
+++ b/scriptreader.h	Mon Jul 30 03:38:02 2012 +0300
@@ -47,6 +47,7 @@
 #include "commands.h"
 
 #define MAX_FILESTACK 8
+#define MAX_STRUCTSTACK 32
 
 class ScriptVar;
 
@@ -61,6 +62,7 @@
 	unsigned int pos[MAX_FILESTACK];
 	unsigned int curline[MAX_FILESTACK];
 	unsigned int curchar[MAX_FILESTACK];
+	unsigned int blockstack[MAX_STRUCTSTACK];
 	long savedpos[MAX_FILESTACK]; // filepointer cursor position
 	str token;
 	int commentmode;
@@ -85,7 +87,6 @@
 	void MustString (bool gotquote = false);
 	void MustNumber (bool fromthis = false);
 	void MustBool ();
-	void MustValue (int type);
 	bool BoolValue ();
 	
 	void ParserError (const char* message, ...);
@@ -133,7 +134,13 @@
 	OPER_ASSIGNSUB,
 	OPER_ASSIGNMUL,
 	OPER_ASSIGNDIV,
-	OPER_ASSIGNMOD
+	OPER_ASSIGNMOD, // -- 10
+	OPER_EQUALS,
+	OPER_NOTEQUALS,
+	OPER_LESSTHAN,
+	OPER_GREATERTHAN,
+	OPER_LESSTHANEQUALS,
+	OPER_GREATERTHANEQUALS,
 };
 
 // Mark types
--- a/stringtable.cxx	Sun Jul 29 16:55:32 2012 +0300
+++ b/stringtable.cxx	Mon Jul 30 03:38:02 2012 +0300
@@ -58,6 +58,10 @@
 // ============================================================================
 // Potentially adds a string to the table and returns the index of it.
 unsigned int PushToStringTable (char* s) {
+	// Must not be too long.
+	if (strlen (s) >= MAX_STRING_LENGTH)
+		error ("string `%s` too long (%d characters max)\n", s, strlen (s));
+	
 	// Find a free slot in the table. 
 	unsigned int a;
 	for (a = 0; a < MAX_LIST_STRINGS; a++) {
@@ -72,7 +76,7 @@
 	
 	// no free slots!
 	if (a == MAX_LIST_STRINGS)
-		error ("too many strings defined!");
+		error ("too many strings defined!\n");
 	
 	// Determine the length
 	size_t l1 = strlen (s);

mercurial