diff -r 5cd91fd1526c -r 1b35c9985989 parser.cxx --- 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 (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 (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