src/Parser.cc

changeset 101
9ffae10ef76f
parent 100
e0392814ee31
child 102
28f89ca1a236
--- 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);

mercurial