Wed, 19 Dec 2012 03:27:15 +0200
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