561 // mark1: // end mark |
558 // mark1: // end mark |
562 |
559 |
563 CheckNotToplevel(); |
560 CheckNotToplevel(); |
564 PushScope(); |
561 PushScope(); |
565 mLexer->MustGetNext (tkParenStart); |
562 mLexer->MustGetNext (tkParenStart); |
566 mLexer->MustGetNext(); |
|
567 buffer()->MergeAndDestroy (ParseExpression (EIntType)); |
563 buffer()->MergeAndDestroy (ParseExpression (EIntType)); |
568 mLexer->MustGetNext (tkParenEnd); |
564 mLexer->MustGetNext (tkParenEnd); |
569 mLexer->MustGetNext (tkBraceStart); |
565 mLexer->MustGetNext (tkBraceStart); |
570 SCOPE (0).type = eSwitchScope; |
566 SCOPE (0).type = eSwitchScope; |
571 SCOPE (0).mark1 = buffer()->AddMark (""); // end mark |
567 SCOPE (0).mark1 = buffer()->AddMark (""); // end mark |
737 |
733 |
738 case eDoScope: |
734 case eDoScope: |
739 { |
735 { |
740 mLexer->MustGetNext (tkWhile); |
736 mLexer->MustGetNext (tkWhile); |
741 mLexer->MustGetNext (tkParenStart); |
737 mLexer->MustGetNext (tkParenStart); |
742 mLexer->MustGetNext(); |
|
743 DataBuffer* expr = ParseExpression (EIntType); |
738 DataBuffer* expr = ParseExpression (EIntType); |
744 mLexer->MustGetNext (tkParenEnd); |
739 mLexer->MustGetNext (tkParenEnd); |
745 mLexer->MustGetNext (tkSemicolon); |
740 mLexer->MustGetNext (tkSemicolon); |
746 |
741 |
747 // If the condition runs true, go back to the start. |
742 // If the condition runs true, go back to the start. |
1017 |
1012 |
1018 if (curarg >= comm->maxargs) |
1013 if (curarg >= comm->maxargs) |
1019 Error ("too many arguments passed to %1\n\tusage is: %2", |
1014 Error ("too many arguments passed to %1\n\tusage is: %2", |
1020 comm->name, comm->GetSignature()); |
1015 comm->name, comm->GetSignature()); |
1021 |
1016 |
1022 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type)); |
1017 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
1023 mLexer->MustGetNext(); |
1018 mLexer->MustGetNext(); |
1024 |
1019 |
1025 if (curarg < comm->numargs - 1) |
1020 if (curarg < comm->numargs - 1) |
1026 { |
1021 { |
1027 mLexer->TokenMustBe (tkComma); |
1022 mLexer->TokenMustBe (tkComma); |
1059 |
1054 |
1060 return r; |
1055 return r; |
1061 } |
1056 } |
1062 |
1057 |
1063 // ============================================================================ |
1058 // ============================================================================ |
1064 // Is the given operator an assignment operator? |
|
1065 // |
|
1066 static bool IsAssignmentOperator (int oper) |
|
1067 { |
|
1068 switch (oper) |
|
1069 { |
|
1070 case OPER_ASSIGNADD: |
|
1071 case OPER_ASSIGNSUB: |
|
1072 case OPER_ASSIGNMUL: |
|
1073 case OPER_ASSIGNDIV: |
|
1074 case OPER_ASSIGNMOD: |
|
1075 case OPER_ASSIGNLEFTSHIFT: |
|
1076 case OPER_ASSIGNRIGHTSHIFT: |
|
1077 case OPER_ASSIGN: |
|
1078 return true; |
|
1079 } |
|
1080 |
|
1081 return false; |
|
1082 } |
|
1083 |
|
1084 // ============================================================================ |
|
1085 // Finds an operator's corresponding dataheader |
|
1086 // |
|
1087 static word GetDataHeaderByOperator (ScriptVariable* var, int oper) |
|
1088 { |
|
1089 if (IsAssignmentOperator (oper)) |
|
1090 { |
|
1091 if (var == null) |
|
1092 Error ("operator %d requires left operand to be a variable\n", oper); |
|
1093 |
|
1094 // TODO: At the moment, vars only are global |
|
1095 // OPER_ASSIGNLEFTSHIFT and OPER_ASSIGNRIGHTSHIFT do not |
|
1096 // have data headers, instead they are expanded out in |
|
1097 // the operator Parser |
|
1098 switch (oper) |
|
1099 { |
|
1100 case OPER_ASSIGNADD: return dhAddGlobalVar; |
|
1101 case OPER_ASSIGNSUB: return dhSubtractGlobalVar; |
|
1102 case OPER_ASSIGNMUL: return dhMultiplyGlobalVar; |
|
1103 case OPER_ASSIGNDIV: return dhDivideGlobalVar; |
|
1104 case OPER_ASSIGNMOD: return dhModGlobalVar; |
|
1105 case OPER_ASSIGN: return dhAssignGlobalVar; |
|
1106 |
|
1107 default: Error ("bad assignment operator!\n"); |
|
1108 } |
|
1109 } |
|
1110 |
|
1111 switch (oper) |
|
1112 { |
|
1113 case OPER_ADD: return dhAdd; |
|
1114 case OPER_SUBTRACT: return dhSubtract; |
|
1115 case OPER_MULTIPLY: return dhMultiply; |
|
1116 case OPER_DIVIDE: return dhDivide; |
|
1117 case OPER_MODULUS: return dhModulus; |
|
1118 case OPER_EQUALS: return dhEquals; |
|
1119 case OPER_NOTEQUALS: return dhNotEquals; |
|
1120 case OPER_LESSTHAN: return dhLessThan; |
|
1121 case OPER_GREATERTHAN: return dhGreaterThan; |
|
1122 case OPER_LESSTHANEQUALS: return dhAtMost; |
|
1123 case OPER_GREATERTHANEQUALS: return dhAtLeast; |
|
1124 case OPER_LEFTSHIFT: return dhLeftShift; |
|
1125 case OPER_RIGHTSHIFT: return dhRightShift; |
|
1126 case OPER_OR: return dhOrLogical; |
|
1127 case OPER_AND: return dhAndLogical; |
|
1128 case OPER_BITWISEOR: return dhOrBitwise; |
|
1129 case OPER_BITWISEEOR: return dhEorBitwise; |
|
1130 case OPER_BITWISEAND: return dhAndBitwise; |
|
1131 } |
|
1132 |
|
1133 Error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); |
|
1134 return 0; |
|
1135 } |
|
1136 |
|
1137 // ============================================================================ |
|
1138 // |
1059 // |
1139 String BotscriptParser::ParseFloat() |
1060 String BotscriptParser::ParseFloat() |
1140 { |
1061 { |
1141 mLexer->TokenMustBe (tkNumber); |
1062 mLexer->TokenMustBe (tkNumber); |
1142 String floatstring = GetTokenString(); |
1063 String floatstring = GetTokenString(); |
1153 |
1074 |
1154 return floatstring; |
1075 return floatstring; |
1155 } |
1076 } |
1156 |
1077 |
1157 // ============================================================================ |
1078 // ============================================================================ |
|
1079 // |
|
1080 // Parses an assignment operator. |
|
1081 // |
|
1082 EAssignmentOperator BotscriptParser::ParseAssignmentOperator() |
|
1083 { |
|
1084 const List<EToken> tokens = |
|
1085 { |
|
1086 tkAssign, |
|
1087 tkAddAssign, |
|
1088 tkSubAssign, |
|
1089 tkMultiplyAssign, |
|
1090 tkDivideAssign, |
|
1091 tkModulusAssign |
|
1092 }; |
|
1093 |
|
1094 mLexer->MustGetAnyOf (tokens); |
|
1095 |
|
1096 switch (mLexer->GetTokenType()) |
|
1097 { |
|
1098 case tkAssign: return EAssign; |
|
1099 case tkAddAssign: return EAssignAdd; |
|
1100 case tkSubAssign: return EAssignSub; |
|
1101 case tkMultiplyAssign: return EAssignMul; |
|
1102 case tkDivideAssign: return EAssignDiv; |
|
1103 case tkModulusAssign: return EAssignMod; |
|
1104 default: break; |
|
1105 } |
|
1106 |
|
1107 assert (false); |
|
1108 return (EAssignmentOperator) 0; |
|
1109 } |
|
1110 |
|
1111 // ============================================================================ |
|
1112 // |
|
1113 EDataHeader BotscriptParser::GetAssigmentDataHeader (EAssignmentOperator op, ScriptVariable* var) |
|
1114 { |
|
1115 if (var->IsGlobal()) |
|
1116 { |
|
1117 switch (op) |
|
1118 { |
|
1119 case EAssign: return dhAssignGlobalVar; |
|
1120 case EAssignAdd: return dhAddGlobalVar; |
|
1121 case EAssignSub: return dhSubtractGlobalVar; |
|
1122 case EAssignMul: return dhMultiplyGlobalVar; |
|
1123 case EAssignDiv: return dhDivideGlobalVar; |
|
1124 case EAssignMod: return dhModGlobalVar; |
|
1125 } |
|
1126 } |
|
1127 |
|
1128 switch (op) |
|
1129 { |
|
1130 case EAssign: return dhAssignLocalVar; |
|
1131 case EAssignAdd: return dhAddLocalVar; |
|
1132 case EAssignSub: return dhSubtractLocalVar; |
|
1133 case EAssignMul: return dhMultiplyLocalVar; |
|
1134 case EAssignDiv: return dhDivideLocalVar; |
|
1135 case EAssignMod: return dhModLocalVar; |
|
1136 } |
|
1137 |
|
1138 assert (false); |
|
1139 return (EDataHeader) 0; |
|
1140 } |
|
1141 |
|
1142 // ============================================================================ |
|
1143 // |
1158 // Parses an assignment. An assignment starts with a variable name, followed |
1144 // Parses an assignment. An assignment starts with a variable name, followed |
1159 // by an assignment operator, followed by an expression value. Expects current |
1145 // by an assignment operator, followed by an expression value. Expects current |
1160 // token to be the name of the variable, and expects the variable to be given. |
1146 // token to be the name of the variable, and expects the variable to be given. |
1161 // |
1147 // |
1162 DataBuffer* BotscriptParser::ParseAssignment (ScriptVariable* var) |
1148 DataBuffer* BotscriptParser::ParseAssignment (ScriptVariable* var) |
1163 { |
1149 { |
1164 // Get an operator |
1150 // Get an operator |
1165 mLexer->MustGetNext(); |
1151 EAssignmentOperator oper = ParseAssignmentOperator(); |
1166 int oper = ParseOperator(); |
|
1167 |
|
1168 if (IsAssignmentOperator (oper) == false) |
|
1169 Error ("expected assignment operator"); |
|
1170 |
1152 |
1171 if (mCurrentMode == ETopLevelMode) |
1153 if (mCurrentMode == ETopLevelMode) |
1172 Error ("can't alter variables at top level"); |
1154 Error ("can't alter variables at top level"); |
1173 |
1155 |
1174 // Parse the right operand |
1156 // Parse the right operand |
1175 mLexer->MustGetNext(); |
|
1176 DataBuffer* retbuf = new DataBuffer; |
1157 DataBuffer* retbuf = new DataBuffer; |
1177 DataBuffer* expr = ParseExpression (var->type); |
1158 DataBuffer* expr = ParseExpression (var->type); |
1178 |
1159 |
|
1160 #if 0 |
1179 // <<= and >>= do not have data headers. Solution: expand them. |
1161 // <<= and >>= do not have data headers. Solution: expand them. |
1180 // a <<= b -> a = a << b |
1162 // a <<= b -> a = a << b |
1181 // a >>= b -> a = a >> b |
1163 // a >>= b -> a = a >> b |
1182 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) |
1164 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) |
1183 { |
1165 { |
1188 retbuf->WriteDWord (var->IsGlobal() ? dhAssignGlobalVar : dhAssignLocalVar); |
1170 retbuf->WriteDWord (var->IsGlobal() ? dhAssignGlobalVar : dhAssignLocalVar); |
1189 retbuf->WriteDWord (var->index); |
1171 retbuf->WriteDWord (var->index); |
1190 } |
1172 } |
1191 else |
1173 else |
1192 { |
1174 { |
|
1175 #endif |
1193 retbuf->MergeAndDestroy (expr); |
1176 retbuf->MergeAndDestroy (expr); |
1194 long dh = GetDataHeaderByOperator (var, oper); |
1177 EDataHeader dh = GetAssigmentDataHeader (oper, var); |
1195 retbuf->WriteDWord (dh); |
1178 retbuf->WriteDWord (dh); |
1196 retbuf->WriteDWord (var->index); |
1179 retbuf->WriteDWord (var->index); |
1197 } |
1180 #if 0 |
|
1181 } |
|
1182 #endif |
1198 |
1183 |
1199 return retbuf; |
1184 return retbuf; |
1200 } |
1185 } |
1201 |
1186 |
1202 // ============================================================================ |
1187 // ============================================================================ |
1223 } |
1208 } |
1224 } |
1209 } |
1225 |
1210 |
1226 // ============================================================================ |
1211 // ============================================================================ |
1227 // |
1212 // |
1228 void BotscriptParser::ParseExpression (EType reqtype) |
1213 DataBuffer* BotscriptParser::ParseExpression (EType reqtype, bool fromhere) |
1229 { |
1214 { |
1230 Expression expr (this, reqtype, mLexer); |
1215 // hehe |
|
1216 if (fromhere == true) |
|
1217 mLexer->Skip (-1); |
|
1218 |
|
1219 Expression expr (this, mLexer, reqtype); |
1231 expr.GetResult()->ConvertToBuffer(); |
1220 expr.GetResult()->ConvertToBuffer(); |
1232 buffer()->MergeAndDestroy (expr.GetResult()->GetBuffer()); |
1221 |
|
1222 // The buffer will be destroyed once the function ends so we need to |
|
1223 // clone it now. |
|
1224 return expr.GetResult()->GetBuffer()->Clone(); |
1233 } |
1225 } |
1234 |
1226 |
1235 // ============================================================================ |
1227 // ============================================================================ |
1236 // |
1228 // |
1237 DataBuffer* BotscriptParser::ParseStatement() |
1229 DataBuffer* BotscriptParser::ParseStatement() |