--- a/src/Parser.cc Sun Feb 09 14:34:13 2014 +0200 +++ b/src/Parser.cc Sun Feb 09 14:56:58 2014 +0200 @@ -117,10 +117,8 @@ ParseOnEnterExit(); break; - case tkInt: - case tkStr: - case tkVoid: - ParseVariableDeclaration(); + case tkVar: + ParseVar(); break; case tkGoto: @@ -171,10 +169,6 @@ ParseBlockEnd(); break; - case tkConst: - ParseConst(); - break; - case tkEventdef: ParseEventdef(); break; @@ -328,9 +322,12 @@ // ============================================================================ // -void BotscriptParser::ParseVariableDeclaration() +void BotscriptParser::ParseVar() { - // For now, only globals are supported + const bool isconst = mLexer->GetNext (tkConst); + mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); + + // TODO if (mCurrentMode != ETopLevelMode || mCurrentState.IsEmpty() == false) Error ("variables must only be global for now"); @@ -341,12 +338,32 @@ mLexer->MustGetNext(); String varname = GetTokenString(); - // Var name must not be a number - if (varname.IsNumeric()) - Error ("variable name must not be a number"); + if (varname[0] >= '0' && varname[0] <= '9') + Error ("variable name must not start with a number"); ScriptVariable* var = DeclareGlobalVariable (type, varname); - (void) var; + + if (isconst == false) + { + var->writelevel = ScriptVariable::WRITE_Mutable; + } + else + { + mLexer->MustGetNext (tkAssign); + Expression expr (this, mLexer, type); + + if (expr.GetResult()->IsConstexpr()) + { + var->writelevel = ScriptVariable::WRITE_Constexpr; + var->value = expr.GetResult()->GetValue(); + } + else + { + // TODO: might need a VM-wise oninit for this... + Error ("const variables must be constexpr for now"); + } + } + mLexer->MustGetNext (tkSemicolon); } @@ -799,49 +816,6 @@ // ============================================================================ // -void BotscriptParser::ParseConst() -{ - ConstantInfo info; - - // Get the type - mLexer->MustGetNext(); - String typestring = GetTokenString(); - info.type = GetTypeByName (typestring); - - if (info.type == EUnknownType || info.type == EVoidType) - Error ("unknown type `%1` for constant", typestring); - - mLexer->MustGetNext(); - info.name = GetTokenString(); - - mLexer->MustGetNext (tkAssign); - - switch (info.type) - { - case EBoolType: - case EIntType: - { - mLexer->MustGetNext (tkNumber); - } break; - - case EStringType: - { - mLexer->MustGetNext (tkString); - } break; - - case EUnknownType: - case EVoidType: - break; - } - - info.val = mLexer->GetToken()->text; - mConstants << info; - - mLexer->MustGetNext (tkSemicolon); -} - -// ============================================================================ -// void BotscriptParser::ParseLabel() { CheckNotToplevel(); @@ -970,7 +944,7 @@ { DataBuffer* r = new DataBuffer (64); - if (mCurrentMode == ETopLevelMode) + if (mCurrentMode == ETopLevelMode && comm->returnvalue == EVoidType) Error ("command call at top level"); mLexer->MustGetNext (tkParenStart); @@ -1135,6 +1109,11 @@ // DataBuffer* BotscriptParser::ParseAssignment (ScriptVariable* var) { + if (var->writelevel != ScriptVariable::WRITE_Mutable) + { + Error ("cannot alter read-only variable $%1", var->name); + } + // Get an operator EAssignmentOperator oper = ParseAssignmentOperator(); DataBuffer* retbuf = new DataBuffer; @@ -1212,12 +1191,17 @@ // DataBuffer* BotscriptParser::ParseStatement() { - if (FindConstant (GetTokenString())) // There should not be constants here. - Error ("invalid use for constant\n"); + // If it's a variable, expect assignment. + if (TokenIs (tkDollarSign)) + { + mLexer->MustGetNext (tkSymbol); + ScriptVariable* var = FindGlobalVariable (GetTokenString()); - // If it's a variable, expect assignment. - if (ScriptVariable* var = FindGlobalVariable (GetTokenString())) + if (var == null) + Error ("unknown variable $%1", var->name); + return ParseAssignment (var); + } return null; } @@ -1249,17 +1233,6 @@ // ============================================================================ // -ConstantInfo* BotscriptParser::FindConstant (const String& tok) -{ - for (int i = 0; i < mConstants.Size(); i++) - if (mConstants[i].name == tok) - return &mConstants[i]; - - return null; -} - -// ============================================================================ -// bool BotscriptParser::TokenIs (EToken a) { return (mLexer->GetTokenType() == a);