Sun, 12 Aug 2012 03:23:33 +0300
Added for-loop support
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.h | file | annotate | diff | comparison | revisions |
--- a/databuffer.h Sun Aug 12 01:52:42 2012 +0300 +++ b/databuffer.h Sun Aug 12 03:23:33 2012 +0300 @@ -254,6 +254,22 @@ for (unsigned int x = 0; x < writesize; x++) printf ("%d. [%d]\n", x, *(buffer+x)); } + + // Count the amount of marks + unsigned int CountMarks () { + unsigned int count = 0; + for (unsigned int u = 0; u < MAX_MARKS; u++) + count += !!marks[u]; + return count; + } + + // Count the amount of refs + unsigned int CountReferences () { + unsigned int count = 0; + for (unsigned int u = 0; u < MAX_MARKS; u++) + count += !!refs[u]; + return count; + } }; #endif // __DATABUFFER_H__ \ No newline at end of file
--- a/main.cxx Sun Aug 12 01:52:42 2012 +0300 +++ b/main.cxx Sun Aug 12 03:23:33 2012 +0300 @@ -57,14 +57,15 @@ #include "botcommands.h" const char* g_Keywords[] = { - "state", "event", + "for", + "goto", + "if", "mainloop", "onenter", "onexit", - "var", - "goto", - "if", + "state", + "var" "while", // These ones aren't implemented yet but I plan to do so, thus they are @@ -76,7 +77,6 @@ "do", "else", "enum", // Would enum actually be useful? I think so. - "for", "func", // Would function support need external support from zandronum? "return", "switch", @@ -169,7 +169,11 @@ // Parse done, print statistics and write to file unsigned int globalcount = CountGlobalVars (); + int NumMarks = w->MainBuffer->CountMarks (); + int NumRefs = w->MainBuffer->CountReferences (); printf ("%u / %u global variable%s\n", globalcount, MAX_SCRIPT_VARIABLES, PLURAL (globalcount)); + printf ("%d / %d mark%s used\n", NumMarks, MAX_MARKS, PLURAL (NumMarks)); + printf ("%d / %d ref%s used\n", NumRefs, MAX_MARKS, PLURAL (NumRefs)); printf ("%d state%s written\n", g_NumStates, PLURAL (g_NumStates)); printf ("%d event%s written\n", g_NumEvents, PLURAL (g_NumEvents)); w->WriteToFile ();
--- a/objwriter.cxx Sun Aug 12 01:52:42 2012 +0300 +++ b/objwriter.cxx Sun Aug 12 03:23:33 2012 +0300 @@ -56,6 +56,7 @@ MainLoopBuffer = new DataBuffer; OnEnterBuffer = new DataBuffer; numWrittenBytes = 0; + numWrittenReferences = 0; filepath = path; } @@ -121,6 +122,7 @@ error ("size of unsigned char isn't 1, but %d!\n", sizeof (unsigned char)); // First, resolve references + numWrittenReferences = 0; for (unsigned int u = 0; u < MAX_MARKS; u++) { ScriptMarkReference* ref = MainBuffer->refs[u]; if (!ref) @@ -131,6 +133,8 @@ uni.val = static_cast<word> (MainBuffer->marks[ref->num]->pos); memset (MainBuffer->buffer + ref->pos + v, uni.b[v], 1); } + + numWrittenReferences++; } // Then, dump the main buffer to the file
--- a/objwriter.h Sun Aug 12 01:52:42 2012 +0300 +++ b/objwriter.h Sun Aug 12 03:23:33 2012 +0300 @@ -60,6 +60,7 @@ DataBuffer* OnEnterBuffer; DataBuffer* MainLoopBuffer; unsigned int numWrittenBytes; + unsigned int numWrittenReferences; // ==================================================================== // METHODS
--- a/parser.cxx Sun Aug 12 01:52:42 2012 +0300 +++ b/parser.cxx Sun Aug 12 03:23:33 2012 +0300 @@ -72,6 +72,7 @@ // of necessary buffering so stuff is written in the correct order. void ScriptReader::BeginParse (ObjWriter* w) { while (Next()) { + // ============================================================ if (!token.icompare ("state")) { MUST_TOPLEVEL @@ -106,6 +107,7 @@ continue; } + // ============================================================ if (!token.icompare ("event")) { MUST_TOPLEVEL @@ -126,6 +128,7 @@ continue; } + // ============================================================ if (!token.icompare ("mainloop")) { MUST_TOPLEVEL MustNext ("{"); @@ -136,6 +139,7 @@ continue; } + // ============================================================ if (!token.icompare ("onenter") || !token.icompare ("onexit")) { MUST_TOPLEVEL bool onenter = !token.compare ("onenter"); @@ -148,6 +152,7 @@ continue; } + // ============================================================ if (!token.compare ("var")) { // For now, only globals are supported if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) @@ -170,6 +175,7 @@ continue; } + // ============================================================ // Label if (!PeekNext().compare (":")) { MUST_NOT_TOPLEVEL @@ -186,6 +192,7 @@ continue; } + // ============================================================ // Goto if (!token.icompare ("goto")) { MUST_NOT_TOPLEVEL @@ -205,6 +212,7 @@ continue; } + // ============================================================ // If if (!token.icompare ("if")) { MUST_NOT_TOPLEVEL @@ -236,6 +244,7 @@ continue; } + // ============================================================ // While if (!token.compare ("while")) { MUST_NOT_TOPLEVEL @@ -270,6 +279,50 @@ continue; } + // ============================================================ + // For loop + if (!token.icompare ("for")) { + MUST_NOT_TOPLEVEL + PushBlockStack (); + + // Initializer + MustNext ("("); + MustNext (); + DataBuffer* init = ParseStatement (w); + MustNext (";"); + + // Condition + MustNext (); + DataBuffer* cond = ParseExpression (TYPE_INT); + MustNext (";"); + + // Incrementor + MustNext (); + DataBuffer* incr = ParseStatement (w); + MustNext (")"); + MustNext ("{"); + + // First, write out the initializer + w->WriteBuffer (init); + + // Init two marks + int mark1 = w->AddMark (MARKTYPE_INTERNAL, ""); + int mark2 = w->AddMark (MARKTYPE_INTERNAL, ""); + + // Add the condition + w->WriteBuffer (cond); + w->Write<long> (DH_IFNOTGOTO); + w->AddReference (mark2); + + // Store the marks and incrementor + blockstack[g_BlockStackCursor].mark1 = mark1; + blockstack[g_BlockStackCursor].mark2 = mark2; + blockstack[g_BlockStackCursor].buffer1 = incr; + blockstack[g_BlockStackCursor].type = BLOCKTYPE_FOR; + continue; + } + + // ============================================================ if (!token.compare ("}")) { // Closing brace @@ -281,6 +334,10 @@ // Adjust the closing mark. w->MoveMark (info->mark1); break; + case BLOCKTYPE_FOR: + // Write the incrementor at the end of the loop block + w->WriteBuffer (info->buffer1); + // fall-thru case BLOCKTYPE_WHILE: // Write down the instruction to go back to the start of the loop w->Write (DH_GOTO); @@ -314,16 +371,10 @@ continue; } - // If it's a variable, expect assignment. - if (ScriptVar* var = FindGlobalVariable (token)) { - DataBuffer* b = ParseAssignment (var); - MustNext (";"); - w->WriteBuffer (b); - continue; - } - - // If it's not a keyword, parse it as an expression. - DataBuffer* b = ParseExpression (TYPE_VOID); + // ============================================================ + // If nothing else, parse it as a statement (which is either + // assignment or expression) + DataBuffer* b = ParseStatement (w); w->WriteBuffer (b); MustNext (";"); } @@ -479,8 +530,8 @@ MustNext (); DataBuffer* rb = ParseExprValue (reqtype); + retbuf->Merge (lb); retbuf->Merge (rb); - retbuf->Merge (lb); long dh = DataHeaderByOperator (NULL, oper); retbuf->Write<word> (dh); @@ -622,4 +673,17 @@ info->type = 0; info->mark1 = 0; info->mark2 = 0; + info->buffer1 = NULL; +} + +DataBuffer* ScriptReader::ParseStatement (ObjWriter* w) { + // If it's a variable, expect assignment. + if (ScriptVar* var = FindGlobalVariable (token)) { + DataBuffer* b = ParseAssignment (var); + return b; + } + + // If it's not a keyword, parse it as an expression. + DataBuffer* b = ParseExpression (TYPE_VOID); + return b; } \ No newline at end of file
--- a/scriptreader.h Sun Aug 12 01:52:42 2012 +0300 +++ b/scriptreader.h Sun Aug 12 03:23:33 2012 +0300 @@ -57,6 +57,7 @@ unsigned int mark1; unsigned int mark2; unsigned int type; + DataBuffer* buffer1; }; // ============================================================================ @@ -115,6 +116,7 @@ // preprocessor.cxx: void PreprocessDirectives (); void PreprocessMacros (); + DataBuffer* ParseStatement (ObjWriter* w); private: bool atnewline; @@ -165,7 +167,8 @@ // Block types enum { BLOCKTYPE_IF, - BLOCKTYPE_WHILE + BLOCKTYPE_WHILE, + BLOCKTYPE_FOR }; #endif // __SCRIPTREADER_H__ \ No newline at end of file