Sun, 09 Feb 2014 22:43:58 +0200
- improved error handling a tad
src/Expression.cc | file | annotate | diff | comparison | revisions | |
src/Expression.h | file | annotate | diff | comparison | revisions | |
src/Main.cc | file | annotate | diff | comparison | revisions | |
src/Main.h | file | annotate | diff | comparison | revisions | |
src/Parser.cc | file | annotate | diff | comparison | revisions | |
src/Parser.h | file | annotate | diff | comparison | revisions |
--- a/src/Expression.cc Sun Feb 09 21:27:55 2014 +0200 +++ b/src/Expression.cc Sun Feb 09 22:43:58 2014 +0200 @@ -47,8 +47,11 @@ while ((sym = ParseSymbol()) != null) mSymbols << sym; + // If we were unable to get any expression symbols, something's wonky with + // the script. Report an error. mBadTokenText is set to the token that + // ParseSymbol ends at when it returns false. if (mSymbols.IsEmpty()) - Error ("Expected expression"); + Error ("unknown identifier '%1'", mBadTokenText); AdjustOperators(); Verify(); @@ -173,6 +176,7 @@ catch (ELocalException&) { // We use a local enum here since catch(...) would catch Error() calls. + mBadTokenText = mLexer->GetToken()->text; mLexer->SetPosition (pos); delete op; return null;
--- a/src/Expression.h Sun Feb 09 21:27:55 2014 +0200 +++ b/src/Expression.h Sun Feb 09 22:43:58 2014 +0200 @@ -57,6 +57,7 @@ Lexer* mLexer; SymbolList mSymbols; EType mType; + String mBadTokenText; ExpressionValue* Evaluate(); // Process the expression and yield a result ExpressionSymbol* ParseSymbol();
--- a/src/Main.cc Sun Feb 09 21:27:55 2014 +0200 +++ b/src/Main.cc Sun Feb 09 22:43:58 2014 +0200 @@ -97,10 +97,12 @@ Print ("Script parsed successfully.\n"); // Parse done, print statistics and write to file - int globalcount = parser->GetScope (0).globalVariables.Size(); + int globalcount = parser->GetHighestVarIndex (true) + 1; + int statelocalcount = parser->GetHighestVarIndex (false) + 1; int stringcount = CountStringsInTable(); Print ("%1 / %2 strings\n", stringcount, gMaxStringlistSize); Print ("%1 / %2 global variable indices\n", globalcount, gMaxGlobalVars); + Print ("%1 / %2 state variable indices\n", statelocalcount, gMaxGlobalVars); Print ("%1 / %2 events\n", parser->GetNumEvents(), gMaxEvents); Print ("%1 state%s1\n", parser->GetNumStates()); @@ -108,7 +110,7 @@ delete parser; return 0; } - catch (ScriptError& e) + catch (std::exception& e) { PrintTo (stderr, "error: %1\n", e.what()); return 1;
--- a/src/Main.h Sun Feb 09 21:27:55 2014 +0200 +++ b/src/Main.h Sun Feb 09 22:43:58 2014 +0200 @@ -78,6 +78,18 @@ String GetVersionString (EFormLength len); String MakeVersionString (int major, int minor, int patch); +template<typename T> +inline T max (T a, T b) +{ + return a > b ? a : b; +} + +template<typename T> +inline T min (T a, T b) +{ + return a < b ? a : b; +} + #ifndef __GNUC__ #define __attribute__(X) #endif
--- a/src/Parser.cc Sun Feb 09 21:27:55 2014 +0200 +++ b/src/Parser.cc Sun Feb 09 22:43:58 2014 +0200 @@ -51,7 +51,9 @@ mStateSpawnDefined (false), mGotMainLoop (false), mScopeCursor (-1), - mCanElse (false) {} + mCanElse (false), + mHighestGlobalVarIndex (0), + mHighestStateVarIndex (0) {} // ============================================================================ // @@ -77,9 +79,11 @@ } // ============================================================================ -// Main Parser code. Begins read of the script file, checks the syntax of it +// +// Main compiler 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 BotscriptParser::ParseBotscript (String fileName) { // Lex and preprocess the file @@ -325,7 +329,6 @@ Variable* var = new Variable; var->origin = mLexer->DescribeCurrentPosition(); const bool isconst = mLexer->GetNext (tkConst); - const bool isglobal = true; mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); EType vartype = (TokenIs (tkInt)) ? EIntType : @@ -335,12 +338,6 @@ mLexer->MustGetNext (tkSymbol); String name = GetTokenString(); - /* - * TODO - if (isglobal && mScopeStack[0].globalVariables.Size() >= gMaxGlobalVars) - Error ("too many global variables!"); - */ - for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) { if (var->name == name) @@ -395,6 +392,7 @@ else SCOPE(0).localVariables << var; + SuggestHighestVarIndex (IsInGlobalState(), var->index); mLexer->MustGetNext (tkSemicolon); Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); } @@ -1359,7 +1357,7 @@ // void BotscriptParser::WriteToFile (String outfile) { - FILE* fp = fopen (outfile, "w"); + FILE* fp = fopen (outfile, "wb"); if (fp == null) Error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); @@ -1402,3 +1400,23 @@ { return mCurrentState.IsEmpty(); } + +// ============================================================================ +// +void BotscriptParser::SuggestHighestVarIndex (bool global, int index) +{ + if (global) + mHighestGlobalVarIndex = max (mHighestGlobalVarIndex, index); + else + mHighestStateVarIndex = max (mHighestStateVarIndex, index); +} + +// ============================================================================ +// +int BotscriptParser::GetHighestVarIndex (bool global) +{ + if (global) + return mHighestGlobalVarIndex; + + return mHighestStateVarIndex; +} \ No newline at end of file
--- a/src/Parser.h Sun Feb 09 21:27:55 2014 +0200 +++ b/src/Parser.h Sun Feb 09 22:43:58 2014 +0200 @@ -174,6 +174,8 @@ void WriteToFile (String outfile); Variable* FindVariable (const String& name); bool IsInGlobalState() const; + void SuggestHighestVarIndex (bool global, int index); + int GetHighestVarIndex (bool global); inline ScopeInfo& GetScope (int offset) { @@ -217,6 +219,8 @@ int mScopeCursor; bool mCanElse; List<UndefinedLabel> mUndefinedLabels; + int mHighestGlobalVarIndex; + int mHighestStateVarIndex; // How many bytes have we written to file? int mNumWrittenBytes;