204 // If nothing else, parse it as a statement |
207 // If nothing else, parse it as a statement |
205 mLexer->Skip (-1); |
208 mLexer->Skip (-1); |
206 DataBuffer* b = ParseStatement(); |
209 DataBuffer* b = ParseStatement(); |
207 |
210 |
208 if (b == false) |
211 if (b == false) |
|
212 { |
|
213 mLexer->GetNext(); |
209 Error ("unknown token `%1`", GetTokenString()); |
214 Error ("unknown token `%1`", GetTokenString()); |
|
215 } |
210 |
216 |
211 buffer()->MergeAndDestroy (b); |
217 buffer()->MergeAndDestroy (b); |
212 mLexer->MustGetNext (tkSemicolon); |
218 mLexer->MustGetNext (tkSemicolon); |
|
219 break; |
213 } |
220 } |
214 break; |
|
215 } |
221 } |
216 } |
222 } |
217 |
223 |
218 // =============================================================================== |
224 // =============================================================================== |
219 // Script file ended. Do some last checks and write the last things to main buffer |
225 // Script file ended. Do some last checks and write the last things to main buffer |
326 // |
332 // |
327 void BotscriptParser::ParseVar() |
333 void BotscriptParser::ParseVar() |
328 { |
334 { |
329 Variable* var = new Variable; |
335 Variable* var = new Variable; |
330 var->origin = mLexer->DescribeCurrentPosition(); |
336 var->origin = mLexer->DescribeCurrentPosition(); |
|
337 var->isarray = false; |
331 const bool isconst = mLexer->GetNext (tkConst); |
338 const bool isconst = mLexer->GetNext (tkConst); |
332 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); |
339 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); |
333 |
340 |
334 EType vartype = (TokenIs (tkInt)) ? EIntType : |
341 EType vartype = (TokenIs (tkInt)) ? EIntType : |
335 (TokenIs (tkStr)) ? EStringType : |
342 (TokenIs (tkStr)) ? EStringType : |
336 EBoolType; |
343 EBoolType; |
337 |
344 |
338 mLexer->MustGetNext (tkSymbol); |
345 mLexer->MustGetNext (tkSymbol); |
339 String name = GetTokenString(); |
346 String name = GetTokenString(); |
|
347 |
|
348 if (mLexer->GetNext (tkBracketStart)) |
|
349 { |
|
350 mLexer->MustGetNext (tkBracketEnd); |
|
351 var->isarray = true; |
|
352 |
|
353 if (isconst) |
|
354 Error ("arrays cannot be const"); |
|
355 } |
340 |
356 |
341 for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) |
357 for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) |
342 { |
358 { |
343 if (var->name == name) |
359 if (var->name == name) |
344 Error ("Variable $%1 is already declared on this scope; declared at %2", |
360 Error ("Variable $%1 is already declared on this scope; declared at %2", |
987 if (curarg < comm->minargs) |
1003 if (curarg < comm->minargs) |
988 Error ("too few arguments passed to %1\n\tusage is: %2", |
1004 Error ("too few arguments passed to %1\n\tusage is: %2", |
989 comm->name, comm->GetSignature()); |
1005 comm->name, comm->GetSignature()); |
990 |
1006 |
991 break; |
1007 break; |
992 curarg++; |
|
993 } |
1008 } |
994 |
1009 |
995 if (curarg >= comm->args.Size()) |
1010 if (curarg >= comm->args.Size()) |
996 Error ("too many arguments passed to %1\n\tusage is: %2", |
1011 Error ("too many arguments (%3) passed to %1\n\tusage is: %2", |
997 comm->name, comm->GetSignature()); |
1012 comm->name, comm->GetSignature()); |
998 |
1013 |
999 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
1014 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
1000 mLexer->MustGetNext (tkAny); |
1015 mLexer->MustGetNext (tkAny); |
1001 |
1016 |
1094 return (EAssignmentOperator) 0; |
1109 return (EAssignmentOperator) 0; |
1095 } |
1110 } |
1096 |
1111 |
1097 // ============================================================================ |
1112 // ============================================================================ |
1098 // |
1113 // |
|
1114 struct AssignmentDataHeaderInfo |
|
1115 { |
|
1116 EAssignmentOperator op; |
|
1117 EDataHeader local; |
|
1118 EDataHeader global; |
|
1119 EDataHeader array; |
|
1120 }; |
|
1121 |
|
1122 const AssignmentDataHeaderInfo gAssignmentDataHeaders[] = |
|
1123 { |
|
1124 { EAssign, dhAssignLocalVar, dhAssignGlobalVar, dhAssignGlobalArray }, |
|
1125 { EAssignAdd, dhAddLocalVar, dhAddGlobalVar, dhAddGlobalArray }, |
|
1126 { EAssignSub, dhSubtractLocalVar, dhSubtractGlobalVar, dhSubtractGlobalArray }, |
|
1127 { EAssignMul, dhMultiplyLocalVar, dhMultiplyGlobalVar, dhMultiplyGlobalArray }, |
|
1128 { EAssignDiv, dhDivideLocalVar, dhDivideGlobalVar, dhDivideGlobalArray }, |
|
1129 { EAssignMod, dhModLocalVar, dhModGlobalVar, dhModGlobalArray }, |
|
1130 { EAssignIncrement, dhIncreaseLocalVar, dhIncreaseGlobalVar, dhIncreaseGlobalArray }, |
|
1131 { EAssignDecrement, dhDecreaseLocalVar, dhDecreaseGlobalVar, dhDecreaseGlobalArray }, |
|
1132 }; |
|
1133 |
1099 EDataHeader BotscriptParser::GetAssigmentDataHeader (EAssignmentOperator op, Variable* var) |
1134 EDataHeader BotscriptParser::GetAssigmentDataHeader (EAssignmentOperator op, Variable* var) |
1100 { |
1135 { |
1101 if (var->IsGlobal()) |
1136 for (const auto& a : gAssignmentDataHeaders) |
1102 { |
1137 { |
1103 switch (op) |
1138 if (a.op != op) |
1104 { |
1139 continue; |
1105 case EAssign: return dhAssignGlobalVar; |
1140 |
1106 case EAssignAdd: return dhAddGlobalVar; |
1141 if (var->isarray) |
1107 case EAssignSub: return dhSubtractGlobalVar; |
1142 return a.array; |
1108 case EAssignMul: return dhMultiplyGlobalVar; |
1143 |
1109 case EAssignDiv: return dhDivideGlobalVar; |
1144 if (var->IsGlobal()) |
1110 case EAssignMod: return dhModGlobalVar; |
1145 return a.global; |
1111 case EAssignIncrement: return dhIncreaseGlobalVar; |
1146 |
1112 case EAssignDecrement: return dhDecreaseGlobalVar; |
1147 return a.local; |
1113 } |
1148 } |
1114 } |
1149 |
1115 |
1150 Error ("WTF: couldn't find data header for operator #%1", op); |
1116 switch (op) |
|
1117 { |
|
1118 case EAssign: return dhAssignLocalVar; |
|
1119 case EAssignAdd: return dhAddLocalVar; |
|
1120 case EAssignSub: return dhSubtractLocalVar; |
|
1121 case EAssignMul: return dhMultiplyLocalVar; |
|
1122 case EAssignDiv: return dhDivideLocalVar; |
|
1123 case EAssignMod: return dhModLocalVar; |
|
1124 case EAssignIncrement: return dhIncreaseLocalVar; |
|
1125 case EAssignDecrement: return dhDecreaseLocalVar; |
|
1126 } |
|
1127 |
|
1128 assert (false); |
|
1129 return (EDataHeader) 0; |
1151 return (EDataHeader) 0; |
1130 } |
1152 } |
1131 |
1153 |
1132 // ============================================================================ |
1154 // ============================================================================ |
1133 // |
1155 // |
1135 // by an assignment operator, followed by an expression value. Expects current |
1157 // by an assignment operator, followed by an expression value. Expects current |
1136 // token to be the name of the variable, and expects the variable to be given. |
1158 // token to be the name of the variable, and expects the variable to be given. |
1137 // |
1159 // |
1138 DataBuffer* BotscriptParser::ParseAssignment (Variable* var) |
1160 DataBuffer* BotscriptParser::ParseAssignment (Variable* var) |
1139 { |
1161 { |
|
1162 DataBuffer* retbuf = new DataBuffer; |
|
1163 DataBuffer* arrayindex = null; |
|
1164 |
1140 if (var->writelevel != Variable::WRITE_Mutable) |
1165 if (var->writelevel != Variable::WRITE_Mutable) |
1141 { |
|
1142 Error ("cannot alter read-only variable $%1", var->name); |
1166 Error ("cannot alter read-only variable $%1", var->name); |
|
1167 |
|
1168 if (var->isarray) |
|
1169 { |
|
1170 mLexer->MustGetNext (tkBracketStart); |
|
1171 Expression expr (this, mLexer, EIntType); |
|
1172 expr.GetResult()->ConvertToBuffer(); |
|
1173 arrayindex = expr.GetResult()->GetBuffer()->Clone(); |
|
1174 mLexer->MustGetNext (tkBracketEnd); |
1143 } |
1175 } |
1144 |
1176 |
1145 // Get an operator |
1177 // Get an operator |
1146 EAssignmentOperator oper = ParseAssignmentOperator(); |
1178 EAssignmentOperator oper = ParseAssignmentOperator(); |
1147 DataBuffer* retbuf = new DataBuffer; |
|
1148 |
1179 |
1149 if (mCurrentMode == ETopLevelMode) |
1180 if (mCurrentMode == ETopLevelMode) |
1150 Error ("can't alter variables at top level"); |
1181 Error ("can't alter variables at top level"); |
1151 |
1182 |
1152 // Parse the right operand |
1183 // Parse the right operand |
1153 if (oper != EAssignIncrement && oper != EAssignDecrement) |
1184 if (oper != EAssignIncrement && oper != EAssignDecrement) |
1154 { |
1185 { |
1155 DataBuffer* expr = ParseExpression (var->type); |
1186 DataBuffer* expr = ParseExpression (var->type); |
1156 retbuf->MergeAndDestroy (expr); |
1187 retbuf->MergeAndDestroy (expr); |
1157 } |
1188 } |
|
1189 |
|
1190 if (var->isarray) |
|
1191 retbuf->MergeAndDestroy (arrayindex); |
1158 |
1192 |
1159 #if 0 |
1193 #if 0 |
1160 // <<= and >>= do not have data headers. Solution: expand them. |
1194 // <<= and >>= do not have data headers. Solution: expand them. |
1161 // a <<= b -> a = a << b |
1195 // a <<= b -> a = a << b |
1162 // a >>= b -> a = a >> b |
1196 // a >>= b -> a = a >> b |