src/Parser.cc

changeset 107
55c2bcd8ed5c
parent 106
9174be9ac686
child 108
6409ece8297c
--- a/src/Parser.cc	Sun Feb 09 22:43:58 2014 +0200
+++ b/src/Parser.cc	Tue Feb 11 03:29:03 2014 +0200
@@ -178,6 +178,9 @@
 				ParseFuncdef();
 				break;
 
+			case tkSemicolon:
+				break;
+
 			default:
 			{
 				// Check for labels
@@ -206,12 +209,15 @@
 				DataBuffer* b = ParseStatement();
 
 				if (b == false)
+				{
+					mLexer->GetNext();
 					Error ("unknown token `%1`", GetTokenString());
+				}
 
 				buffer()->MergeAndDestroy (b);
 				mLexer->MustGetNext (tkSemicolon);
+				break;
 			}
-			break;
 		}
 	}
 
@@ -328,6 +334,7 @@
 {
 	Variable* var = new Variable;
 	var->origin = mLexer->DescribeCurrentPosition();
+	var->isarray = false;
 	const bool isconst = mLexer->GetNext (tkConst);
 	mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid});
 
@@ -338,6 +345,15 @@
 	mLexer->MustGetNext (tkSymbol);
 	String name = GetTokenString();
 
+	if (mLexer->GetNext (tkBracketStart))
+	{
+		mLexer->MustGetNext (tkBracketEnd);
+		var->isarray = true;
+
+		if (isconst)
+			Error ("arrays cannot be const");
+	}
+
 	for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables)
 	{
 		if (var->name == name)
@@ -368,7 +384,7 @@
 		else
 		{
 			// TODO: might need a VM-wise oninit for this...
-			Error ("const variables must be constexpr for now");
+			Error ("const variables must be constexpr");
 		}
 	}
 
@@ -989,11 +1005,10 @@
 					comm->name, comm->GetSignature());
 
 			break;
-			curarg++;
 		}
 
 		if (curarg >= comm->args.Size())
-			Error ("too many arguments passed to %1\n\tusage is: %2",
+			Error ("too many arguments (%3) passed to %1\n\tusage is: %2",
 				comm->name, comm->GetSignature());
 
 		r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true));
@@ -1096,36 +1111,43 @@
 
 // ============================================================================
 //
+struct AssignmentDataHeaderInfo
+{
+	EAssignmentOperator	op;
+	EDataHeader			local;
+	EDataHeader			global;
+	EDataHeader			array;
+};
+
+const AssignmentDataHeaderInfo gAssignmentDataHeaders[] =
+{
+	{ EAssign,			dhAssignLocalVar,	dhAssignGlobalVar,		dhAssignGlobalArray },
+	{ EAssignAdd,		dhAddLocalVar,		dhAddGlobalVar,			dhAddGlobalArray },
+	{ EAssignSub,		dhSubtractLocalVar,	dhSubtractGlobalVar,	dhSubtractGlobalArray },
+	{ EAssignMul,		dhMultiplyLocalVar,	dhMultiplyGlobalVar,	dhMultiplyGlobalArray },
+	{ EAssignDiv,		dhDivideLocalVar,	dhDivideGlobalVar,		dhDivideGlobalArray },
+	{ EAssignMod,		dhModLocalVar,		dhModGlobalVar,			dhModGlobalArray },
+	{ EAssignIncrement,	dhIncreaseLocalVar,	dhIncreaseGlobalVar,	dhIncreaseGlobalArray },
+	{ EAssignDecrement,	dhDecreaseLocalVar,	dhDecreaseGlobalVar,	dhDecreaseGlobalArray },
+};
+
 EDataHeader BotscriptParser::GetAssigmentDataHeader (EAssignmentOperator op, Variable* var)
 {
-	if (var->IsGlobal())
+	for (const auto& a : gAssignmentDataHeaders)
 	{
-		switch (op)
-		{
-			case EAssign:			return dhAssignGlobalVar;
-			case EAssignAdd:		return dhAddGlobalVar;
-			case EAssignSub:		return dhSubtractGlobalVar;
-			case EAssignMul:		return dhMultiplyGlobalVar;
-			case EAssignDiv:		return dhDivideGlobalVar;
-			case EAssignMod:		return dhModGlobalVar;
-			case EAssignIncrement:	return dhIncreaseGlobalVar;
-			case EAssignDecrement:	return dhDecreaseGlobalVar;
-		}
+		if (a.op != op)
+			continue;
+
+		if (var->isarray)
+			return a.array;
+
+		if (var->IsGlobal())
+			return a.global;
+
+		return a.local;
 	}
 
-	switch (op)
-	{
-		case EAssign:			return dhAssignLocalVar;
-		case EAssignAdd:		return dhAddLocalVar;
-		case EAssignSub:		return dhSubtractLocalVar;
-		case EAssignMul:		return dhMultiplyLocalVar;
-		case EAssignDiv:		return dhDivideLocalVar;
-		case EAssignMod:		return dhModLocalVar;
-		case EAssignIncrement:	return dhIncreaseLocalVar;
-		case EAssignDecrement:	return dhDecreaseLocalVar;
-	}
-
-	assert (false);
+	Error ("WTF: couldn't find data header for operator #%1", op);
 	return (EDataHeader) 0;
 }
 
@@ -1137,14 +1159,23 @@
 //
 DataBuffer* BotscriptParser::ParseAssignment (Variable* var)
 {
+	DataBuffer* retbuf = new DataBuffer;
+	DataBuffer* arrayindex = null;
+
 	if (var->writelevel != Variable::WRITE_Mutable)
+		Error ("cannot alter read-only variable $%1", var->name);
+
+	if (var->isarray)
 	{
-		Error ("cannot alter read-only variable $%1", var->name);
+		mLexer->MustGetNext (tkBracketStart);
+		Expression expr (this, mLexer, EIntType);
+		expr.GetResult()->ConvertToBuffer();
+		arrayindex = expr.GetResult()->GetBuffer()->Clone();
+		mLexer->MustGetNext (tkBracketEnd);
 	}
 
 	// Get an operator
 	EAssignmentOperator oper = ParseAssignmentOperator();
-	DataBuffer* retbuf = new DataBuffer;
 
 	if (mCurrentMode == ETopLevelMode)
 		Error ("can't alter variables at top level");
@@ -1156,6 +1187,9 @@
 		retbuf->MergeAndDestroy (expr);
 	}
 
+	if (var->isarray)
+		retbuf->MergeAndDestroy (arrayindex);
+
 #if 0
 	// <<= and >>= do not have data headers. Solution: expand them.
 	// a <<= b -> a = a << b

mercurial