Good bunch of changes

Wed, 19 Dec 2012 03:27:15 +0200

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Wed, 19 Dec 2012 03:27:15 +0200
changeset 66
4fc1ec88aa41
parent 65
ec04357f5bb9
child 67
0a202714eea4

Good bunch of changes

common.h file | annotate | diff | comparison | revisions
main.cxx file | annotate | diff | comparison | revisions
parser.cxx file | annotate | diff | comparison | revisions
preprocessor.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/common.h	Sun Aug 26 23:54:58 2012 +0300
+++ b/common.h	Wed Dec 19 03:27:15 2012 +0200
@@ -91,11 +91,16 @@
 bool fexists (char* path);
 
 // Make the parser's variables globally available
-#ifndef __PARSER_CXX__
 extern int g_NumStates;
 extern int g_NumEvents;
 extern int g_CurMode;
 extern str g_CurState;
+
+#define neurosphere if (g_Neurosphere)
+#define twice for (int repeat_token = 0; repeat_token < 2; repeat_token++)
+
+#ifndef __GNUC__
+#define __attribute__(X)
 #endif
 
 // Power function
--- a/main.cxx	Sun Aug 26 23:54:58 2012 +0300
+++ b/main.cxx	Wed Dec 19 03:27:15 2012 +0200
@@ -90,6 +90,7 @@
 int main (int argc, char** argv) {
 	// Intepret command-line parameters:
 	// -l: list commands
+	// I guess there should be a better way to do this.
 	if (argc == 2 && !strcmp (argv[1], "-l")) {
 		ReadCommands ();
 		printf ("Begin list of commands:\n");
@@ -113,7 +114,7 @@
 	if (VERSION_REVISION)
 		header.appendformat (".%d", VERSION_REVISION);
 	
-	headerline.repeat ((header.len()/2)-1);
+	headerline *= (header.len() / 2) - 1;
 	headerline += '-';
 	printf ("%s\n%s\n", header.chars(), headerline.chars());
 	
@@ -227,7 +228,7 @@
 	// Locate the extension and chop it out
 	unsigned int extdot = s.last (".");
 	if (extdot >= s.len()-4)
-		s.trim (s.len() - extdot);
+		s -= (s.len() - extdot);
 	
 	s += ".o";
 	return s.chars();
--- a/parser.cxx	Sun Aug 26 23:54:58 2012 +0300
+++ b/parser.cxx	Wed Dec 19 03:27:15 2012 +0200
@@ -69,6 +69,7 @@
 DataBuffer* g_IfExpression = NULL;
 bool g_CanElse = false;
 str* g_UndefinedLabels[MAX_MARKS];
+bool g_Neurosphere = false; // neurosphere-compat
 
 // ============================================================================
 // Main parser code. Begins read of the script file, checks the syntax of it
@@ -84,13 +85,13 @@
 	
 	while (Next()) {
 		// Check if else is potentically valid
-		if (!token.compare ("else") && !g_CanElse)
+		if (token == "else" && !g_CanElse)
 			ParserError ("else without preceding if");
-		if (token.compare ("else") != 0)
+		if (token != "else")
 			g_CanElse = false;
 		
 		// ============================================================
-		if (!token.compare ("state")) {
+		if (token == "state") {
 			MUST_TOPLEVEL
 			
 			MustString ();
@@ -125,7 +126,7 @@
 		}
 		
 		// ============================================================
-		if (!token.compare ("event")) {
+		if (token == "event") {
 			MUST_TOPLEVEL
 			
 			// Event definition
@@ -146,7 +147,7 @@
 		}
 		
 		// ============================================================
-		if (!token.compare ("mainloop")) {
+		if (token == "mainloop") {
 			MUST_TOPLEVEL
 			MustNext ("{");
 			
@@ -157,9 +158,9 @@
 		}
 		
 		// ============================================================
-		if (!token.compare ("onenter") || !token.compare ("onexit")) {
+		if (token == "onenter" || token == "onexit") {
 			MUST_TOPLEVEL
-			bool onenter = !token.compare ("onenter");
+			bool onenter = token == "onenter";
 			MustNext ("{");
 			
 			// Mode must be set before dataheader is written here,
@@ -170,7 +171,7 @@
 		}
 		
 		// ============================================================
-		if (!token.compare ("var")) {
+		if (token == "var") {
 			// For now, only globals are supported
 			if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
 				ParserError ("variables must only be global for now");
@@ -194,7 +195,7 @@
 		
 		// ============================================================
 		// Goto
-		if (!token.compare ("goto")) {
+		if (token == "goto") {
 			MUST_NOT_TOPLEVEL
 			
 			// Get the name of the label
@@ -218,7 +219,7 @@
 		
 		// ============================================================
 		// If
-		if (!token.compare ("if")) {
+		if (token == "if") {
 			MUST_NOT_TOPLEVEL
 			PushScope ();
 			
@@ -248,7 +249,7 @@
 			continue;
 		}
 		
-		if (!token.compare ("else")) {
+		if (token == "else") {
 			MUST_NOT_TOPLEVEL
 			MustNext ("{");
 			
@@ -276,7 +277,7 @@
 		
 		// ============================================================
 		// While
-		if (!token.compare ("while")) {
+		if (token == "while") {
 			MUST_NOT_TOPLEVEL
 			PushScope ();
 			
@@ -310,7 +311,7 @@
 		
 		// ============================================================
 		// For loop
-		if (!token.compare ("for")) {
+		if (token == "for") {
 			MUST_NOT_TOPLEVEL
 			PushScope ();
 			
@@ -353,7 +354,7 @@
 		
 		// ============================================================
 		// Do/while loop
-		if (!token.compare ("do")) {
+		if (token == "do") {
 			MUST_NOT_TOPLEVEL
 			PushScope ();
 			MustNext ("{");
@@ -364,7 +365,7 @@
 		
 		// ============================================================
 		// Switch
-		if (!token.compare ("switch")) {
+		if (token == "switch") {
 			/* This goes a bit tricky. switch is structured in the
 			 * bytecode followingly:
 			 * (expression)
@@ -392,7 +393,7 @@
 		}
 		
 		// ============================================================
-		if (!token.compare ("case")) {
+		if (token == "case") {
 			// case is only allowed inside switch
 			if (SCOPE(0).type != SCOPETYPE_SWITCH)
 				ParserError ("case label outside switch");
@@ -422,7 +423,7 @@
 			continue;
 		}
 		
-		if (!token.compare ("default")) {
+		if (token == "default") {
 			if (SCOPE(0).type != SCOPETYPE_SWITCH)
 				ParserError ("default label outside switch");
 			
@@ -448,7 +449,7 @@
 		
 		// ============================================================
 		// Break statement.
-		if (!token.compare ("break")) {
+		if (token == "break") {
 			if (!g_ScopeCursor)
 				ParserError ("unexpected `break`");
 			
@@ -476,7 +477,7 @@
 		
 		// ============================================================
 		// Continue
-		if (!token.compare ("continue")) {
+		if (token == "continue") {
 			MustNext (";");
 			
 			int curs;
@@ -492,6 +493,8 @@
 					w->AddReference (scopestack[curs].mark1);
 					found = true;
 					break;
+				default:
+					break;
 				}
 			}
 			
@@ -612,7 +615,10 @@
 					
 					// Move the closing mark here
 					w->MoveMark (SCOPE(0).mark1);
+					break;
 				}
+				case SCOPETYPE_UNKNOWN:
+					break;
 				}
 				
 				// Descend down the stack
@@ -639,14 +645,23 @@
 			continue;
 		}
 		
+		// Check if it's a command
+		CommandDef* comm = FindCommand (token);
+		if (comm) {
+			w->GetCurrentBuffer()->Merge (ParseCommand (comm));
+			MustNext (";");
+			continue;
+		}
+		
 		// ============================================================
-		// If nothing else, parse it as a statement (which is either
-		// assignment or expression)
+		// If nothing else, parse it as a statement
 		DataBuffer* b = ParseStatement (w);
 		w->WriteBuffer (b);
 		MustNext (";");
 	}
 	
+	// ===============================================================================
+	// Script file ended. Do some last checks and write the last things to main buffer
 	if (g_CurMode != MODE_TOPLEVEL)
 		ParserError ("script did not end at top level; did you forget a `}`?");
 	
@@ -817,18 +832,17 @@
 			
 			// It also is handled differently: there isn't a dataheader for ternary
 			// operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this.
+			// Behold, big block of writing madness! :P
 			int mark1 = retbuf->AddMark (""); // start of "else" case
 			int mark2 = retbuf->AddMark (""); // end of expression
-			retbuf->Write<word> (DH_IFNOTGOTO);
-			retbuf->AddMarkReference (mark1);
-			retbuf->Merge (rb);
-			retbuf->Write<word> (DH_GOTO);
-			retbuf->AddMarkReference (mark2);
-			retbuf->MoveMark (mark1); // start of "else" case
-			retbuf->Merge (tb);
-			retbuf->Write<word> (DH_GOTO);
-			retbuf->AddMarkReference (mark2);
-			retbuf->MoveMark (mark2); // move endmark to end
+			retbuf->Write<word> (DH_IFNOTGOTO); // if the first operand (condition)
+			retbuf->AddMarkReference (mark1); // didn't eval true, jump into mark1
+			retbuf->Merge (rb); // otherwise, perform second operand (true case)
+			retbuf->Write<word> (DH_GOTO); // afterwards, jump to the end, which is
+			retbuf->AddMarkReference (mark2); // marked by mark2.
+			retbuf->MoveMark (mark1); // move mark1 at the end of the true case
+			retbuf->Merge (tb); // perform third operand (false case)
+			retbuf->MoveMark (mark2); // move the ending mark2 here
 		} else {
 			// Write to buffer
 			retbuf->Merge (rb);
@@ -1053,7 +1067,7 @@
 		ParserError ("too deep scope");
 	
 	ScopeInfo* info = &SCOPE(0);
-	info->type = 0;
+	info->type = SCOPETYPE_UNKNOWN;
 	info->mark1 = 0;
 	info->mark2 = 0;
 	info->buffer1 = NULL;
--- a/preprocessor.cxx	Sun Aug 26 23:54:58 2012 +0300
+++ b/preprocessor.cxx	Wed Dec 19 03:27:15 2012 +0200
@@ -104,7 +104,7 @@
 	str directive = PPReadWord (trash);
 	
 	// Now check the directive name against known names
-	if (!directive.icompare ("include")) {
+	if (directive == "include") {
 		// #include-directive
 		char terminator;
 		str file = PPReadWord (terminator);
@@ -113,6 +113,12 @@
 			ParserError ("expected file name for #include, got nothing instead");
 		OpenFile (file);
 		return true;
+	} else if (directive == "neurosphere") {
+		// #neurosphere - activates neurosphere compatibility, aka stuff
+		// that is still WIP and what main zandronum does not yet support.
+		// Most end users should never need this.
+		g_Neurosphere = true;
+		return true;
 	}
 	
 	ParserError ("unknown directive `#%s`!", directive.chars());
--- a/scriptreader.h	Sun Aug 26 23:54:58 2012 +0300
+++ b/scriptreader.h	Wed Dec 19 03:27:15 2012 +0200
@@ -52,12 +52,69 @@
 
 class ScriptVar;
 
+enum type_e {
+	TYPE_VOID = 0,
+	TYPE_INT,
+	TYPE_STRING,
+	TYPE_FLOAT,
+	TYPE_BOOL
+};
+
+// Operators
+enum operator_e {
+	OPER_ADD,
+	OPER_SUBTRACT,
+	OPER_MULTIPLY,
+	OPER_DIVIDE,
+	OPER_MODULUS,
+	OPER_ASSIGN,
+	OPER_ASSIGNADD,
+	OPER_ASSIGNSUB,
+	OPER_ASSIGNMUL,
+	OPER_ASSIGNDIV,
+	OPER_ASSIGNMOD, // -- 10
+	OPER_EQUALS,
+	OPER_NOTEQUALS,
+	OPER_LESSTHAN,
+	OPER_GREATERTHAN,
+	OPER_LESSTHANEQUALS,
+	OPER_GREATERTHANEQUALS,
+	OPER_LEFTSHIFT,
+	OPER_RIGHTSHIFT,
+	OPER_ASSIGNLEFTSHIFT,
+	OPER_ASSIGNRIGHTSHIFT, // -- 20
+	OPER_OR,
+	OPER_AND,
+	OPER_BITWISEOR,
+	OPER_BITWISEAND,
+	OPER_BITWISEEOR,
+	OPER_TERNARY,
+};
+
+// Mark types
+enum marktype_e {
+	MARKTYPE_LABEL,
+	MARKTYPE_IF,
+	MARKTYPE_INTERNAL, // internal structures
+};
+
+// Block types
+enum scopetype_e {
+	SCOPETYPE_UNKNOWN,
+	SCOPETYPE_IF,
+	SCOPETYPE_WHILE,
+	SCOPETYPE_FOR,
+	SCOPETYPE_DO,
+	SCOPETYPE_SWITCH,
+	SCOPETYPE_ELSE,
+};
+
 // ============================================================================
 // Meta-data about blocks
 struct ScopeInfo {
 	unsigned int mark1;
 	unsigned int mark2;
-	unsigned int type;
+	scopetype_e type;
 	DataBuffer* buffer1;
 	
 	// switch-related stuff
@@ -147,61 +204,6 @@
 	str PPReadWord (char &term);
 };
 
-enum {
-	TYPE_VOID = 0,
-	TYPE_INT,
-	TYPE_STRING,
-	TYPE_FLOAT,
-	TYPE_BOOL
-};
-
-// Operators
-enum {
-	OPER_ADD,
-	OPER_SUBTRACT,
-	OPER_MULTIPLY,
-	OPER_DIVIDE,
-	OPER_MODULUS,
-	OPER_ASSIGN,
-	OPER_ASSIGNADD,
-	OPER_ASSIGNSUB,
-	OPER_ASSIGNMUL,
-	OPER_ASSIGNDIV,
-	OPER_ASSIGNMOD, // -- 10
-	OPER_EQUALS,
-	OPER_NOTEQUALS,
-	OPER_LESSTHAN,
-	OPER_GREATERTHAN,
-	OPER_LESSTHANEQUALS,
-	OPER_GREATERTHANEQUALS,
-	OPER_LEFTSHIFT,
-	OPER_RIGHTSHIFT,
-	OPER_ASSIGNLEFTSHIFT,
-	OPER_ASSIGNRIGHTSHIFT, // -- 20
-	OPER_OR,
-	OPER_AND,
-	OPER_BITWISEOR,
-	OPER_BITWISEAND,
-	OPER_BITWISEEOR,
-	OPER_TERNARY,
-};
-
-// Mark types
-enum {
-	MARKTYPE_LABEL,
-	MARKTYPE_IF,
-	MARKTYPE_INTERNAL, // internal structures
-};
-
-// Block types
-enum {
-	SCOPETYPE_UNSET = 0,
-	SCOPETYPE_IF,
-	SCOPETYPE_WHILE,
-	SCOPETYPE_FOR,
-	SCOPETYPE_DO,
-	SCOPETYPE_SWITCH,
-	SCOPETYPE_ELSE,
-};
+extern bool g_Neurosphere;
 
 #endif // __SCRIPTREADER_H__
\ No newline at end of file
--- a/str.cxx	Sun Aug 26 23:54:58 2012 +0300
+++ b/str.cxx	Wed Dec 19 03:27:15 2012 +0200
@@ -42,6 +42,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include "array.h"
 #include "str.h"
 #include "common.h"
 
@@ -400,60 +401,26 @@
 }
 
 // ============================================================================
-#if 0
-str** str::split (char* del) {
-	unsigned int arrcount = count (del) + 1;
-	str** arr = new str* [arrcount];
+array<str> str::split (str del) {
+	array<str> res;
+	unsigned int a = 0;
 	
-	unsigned int a = 0;
-	unsigned int index = 0;
+	// Find all separators and store the text left to them.
 	while (1) {
-		unsigned int b = first (del, a+1);
-		printf ("next: %u (<-> %u)\n", b, len());
+		unsigned int b = first (del, a);
 		
 		if (b == len())
 			break;
 		
-		str* x = new str;
-		x->append (substr (a, b));
-		arr[index] = x;
-		index++;
-		a = b;
+		res.push (substr (a, b));
+		a = b + strlen (del);
 	}
 	
-	return arr;
-}
-#endif
-
-// ============================================================================
-// OPERATORS
-str str::operator + (str& c) {
-	append (c);
-	return *this;
+	// Add the string at the right of the last separator
+	res.push (substr (a, len()));
+	return res;
 }
 
-str& str::operator += (char c) {
-	append (c);
-	return *this;
-}
-
-str& str::operator += (const char* c) {
-	append (c);
-	return *this;
-}
-
-str& str::operator += (const str c) {
-	append (c);
-	return *this;
-}
-
-char str::operator [] (unsigned int pos) {
-	return text[pos];
-}
-
-str::operator char* () const {
-	return text;
-}
-
-str::operator int () const {return atoi(text);}
-str::operator unsigned int () const {return atoi(text);}
\ No newline at end of file
+array<str> str::operator/ (str splitstring) {return split(splitstring);}
+array<str> str::operator/ (char* splitstring) {return split(splitstring);}
+array<str> str::operator/ (const char* splitstring) {return split(splitstring);}
\ No newline at end of file
--- a/str.h	Sun Aug 26 23:54:58 2012 +0300
+++ b/str.h	Wed Dec 19 03:27:15 2012 +0200
@@ -41,6 +41,8 @@
 #ifndef __STR_H__
 #define __STR_H__
 
+template<class T> class array;
+
 char* vdynformat (const char* c, va_list v, unsigned int size);
 
 #define SCCF_NUMBER	1<<0
@@ -141,20 +143,91 @@
 	// Counts the amount of substrings in the string
 	unsigned int count (char* s);
 	
-#if 0
-	str** split (char* del);
-#endif
+	array<str> split (str del);
 	
 	// ======================================================================
 	// OPERATORS
-	str operator + (str& c);
-	str& operator += (char c);
-	str& operator += (const char* c);
-	str& operator += (const str c);
-	char operator [] (unsigned int pos);
-	operator char* () const;
-	operator int () const;
-	operator unsigned int () const;
+	str operator+ (str& c) {
+		append (c);
+		return *this;
+	}
+	
+	str& operator+= (char c) {
+		append (c);
+		return *this;
+	}
+	
+	str& operator+= (const char* c) {
+		append (c);
+		return *this;
+	}
+	
+	str& operator+= (const str c) {
+		append (c);
+		return *this;
+	}
+	
+	str operator* (const int repcount) {
+		repeat (repcount);
+		return *this;
+	}
+	
+	str& operator*= (const int repcount) {
+		repeat (repcount);
+		return *this;
+	}
+	
+	str operator- (const int trimcount) {
+		trim (trimcount);
+		return *this;
+	}
+	
+	str& operator-= (const int trimcount) {
+		trim (trimcount);
+		return *this;
+	}
+	
+	array<str> operator/ (str splitstring);
+	array<str> operator/ (char* splitstring);
+	array<str> operator/ (const char* splitstring);
+	
+	str operator+ () {
+		return toupper ();
+	}
+	
+	str operator- () {
+		return tolower ();
+	}
+	
+	str operator! () {
+		reverse ();
+		return *this;
+	}
+	
+#define DEFINE_OPERATOR_TYPE(OPER, TYPE) \
+	bool operator OPER (TYPE other) {return compare(other) OPER 0;}
+#define DEFINE_OPERATOR(OPER) \
+	DEFINE_OPERATOR_TYPE (OPER, str) \
+	DEFINE_OPERATOR_TYPE (OPER, char*) \
+	DEFINE_OPERATOR_TYPE (OPER, const char*)
+	
+	DEFINE_OPERATOR (==)
+	DEFINE_OPERATOR (!=)
+	DEFINE_OPERATOR (>)
+	DEFINE_OPERATOR (<)
+	DEFINE_OPERATOR (>=)
+	DEFINE_OPERATOR (<=)
+	
+	char operator [] (unsigned int pos) {
+		return text[pos];
+	}
+	
+	operator char* () const {
+		return text;
+	}
+	
+	operator int () const {return atoi(text);}
+	operator unsigned int () const {return atoi(text);}
 };
 
 #endif // __STR_H__
\ No newline at end of file

mercurial