38 #define SCOPE(n) (mScopeStack[mScopeCursor - n]) |
38 #define SCOPE(n) (mScopeStack[mScopeCursor - n]) |
39 |
39 |
40 // ============================================================================ |
40 // ============================================================================ |
41 // |
41 // |
42 BotscriptParser::BotscriptParser() : |
42 BotscriptParser::BotscriptParser() : |
43 mReadOnly (false), |
43 mIsReadOnly (false), |
44 mMainBuffer (new DataBuffer), |
44 mMainBuffer (new DataBuffer), |
45 mOnEnterBuffer (new DataBuffer), |
45 mOnEnterBuffer (new DataBuffer), |
46 mMainLoopBuffer (new DataBuffer), |
46 mMainLoopBuffer (new DataBuffer), |
47 mLexer (new Lexer), |
47 mLexer (new Lexer), |
48 mNumStates (0), |
48 mNumStates (0), |
88 { |
88 { |
89 // Lex and preprocess the file |
89 // Lex and preprocess the file |
90 mLexer->ProcessFile (fileName); |
90 mLexer->ProcessFile (fileName); |
91 PushScope(); |
91 PushScope(); |
92 |
92 |
93 while (mLexer->GetNext()) |
93 while (mLexer->Next()) |
94 { |
94 { |
95 // Check if else is potentically valid |
95 // Check if else is potentically valid |
96 if (TokenIs (TK_Else) && mCanElse == false) |
96 if (TokenIs (TK_Else) && mCanElse == false) |
97 Error ("else without preceding if"); |
97 Error ("else without preceding if"); |
98 |
98 |
99 if (TokenIs (TK_Else) == false) |
99 if (TokenIs (TK_Else) == false) |
100 mCanElse = false; |
100 mCanElse = false; |
101 |
101 |
102 switch (mLexer->GetToken()->type) |
102 switch (mLexer->Token()->type) |
103 { |
103 { |
104 case TK_State: |
104 case TK_State: |
105 ParseStateBlock(); |
105 ParseStateBlock(); |
106 break; |
106 break; |
107 |
107 |
307 void BotscriptParser::ParseVar() |
307 void BotscriptParser::ParseVar() |
308 { |
308 { |
309 Variable* var = new Variable; |
309 Variable* var = new Variable; |
310 var->origin = mLexer->DescribeCurrentPosition(); |
310 var->origin = mLexer->DescribeCurrentPosition(); |
311 var->isarray = false; |
311 var->isarray = false; |
312 const bool isconst = mLexer->GetNext (TK_Const); |
312 const bool isconst = mLexer->Next (TK_Const); |
313 mLexer->MustGetAnyOf ({TK_Int,TK_Str,TK_Void}); |
313 mLexer->MustGetAnyOf ({TK_Int,TK_Str,TK_Void}); |
314 |
314 |
315 DataType vartype = (TokenIs (TK_Int)) ? TYPE_Int : |
315 DataType vartype = (TokenIs (TK_Int)) ? TYPE_Int : |
316 (TokenIs (TK_Str)) ? TYPE_String : |
316 (TokenIs (TK_Str)) ? TYPE_String : |
317 TYPE_Bool; |
317 TYPE_Bool; |
318 |
318 |
319 mLexer->MustGetNext (TK_Symbol); |
319 mLexer->MustGetNext (TK_Symbol); |
320 String name = GetTokenString(); |
320 String name = GetTokenString(); |
321 |
321 |
322 if (mLexer->GetNext (TK_BracketStart)) |
322 if (mLexer->Next (TK_BracketStart)) |
323 { |
323 { |
324 mLexer->MustGetNext (TK_BracketEnd); |
324 mLexer->MustGetNext (TK_BracketEnd); |
325 var->isarray = true; |
325 var->isarray = true; |
326 |
326 |
327 if (isconst) |
327 if (isconst) |
348 mLexer->MustGetNext (TK_Assign); |
348 mLexer->MustGetNext (TK_Assign); |
349 Expression expr (this, mLexer, vartype); |
349 Expression expr (this, mLexer, vartype); |
350 |
350 |
351 // If the expression was constexpr, we know its value and thus |
351 // If the expression was constexpr, we know its value and thus |
352 // can store it in the variable. |
352 // can store it in the variable. |
353 if (expr.GetResult()->IsConstexpr()) |
353 if (expr.Result()->IsConstexpr()) |
354 { |
354 { |
355 var->writelevel = WRITE_Constexpr; |
355 var->writelevel = WRITE_Constexpr; |
356 var->value = expr.GetResult()->GetValue(); |
356 var->value = expr.Result()->Value(); |
357 } |
357 } |
358 else |
358 else |
359 { |
359 { |
360 // TODO: might need a VM-wise oninit for this... |
360 // TODO: might need a VM-wise oninit for this... |
361 Error ("const variables must be constexpr"); |
361 Error ("const variables must be constexpr"); |
575 Error ("case label outside switch"); |
575 Error ("case label outside switch"); |
576 |
576 |
577 // Get a literal value for the case block. Zandronum does not support |
577 // Get a literal value for the case block. Zandronum does not support |
578 // expressions here. |
578 // expressions here. |
579 mLexer->MustGetNext (TK_Number); |
579 mLexer->MustGetNext (TK_Number); |
580 int num = mLexer->GetToken()->text.ToLong(); |
580 int num = mLexer->Token()->text.ToLong(); |
581 mLexer->MustGetNext (TK_Colon); |
581 mLexer->MustGetNext (TK_Colon); |
582 |
582 |
583 for (const CaseInfo& info : SCOPE(0).cases) |
583 for (const CaseInfo& info : SCOPE(0).cases) |
584 if (info.number == num) |
584 if (info.number == num) |
585 Error ("multiple case %1 labels in one switch", num); |
585 Error ("multiple case %1 labels in one switch", num); |
805 // Data header must be written before mode is changed because |
805 // Data header must be written before mode is changed because |
806 // onenter and mainloop go into special buffers, and we want |
806 // onenter and mainloop go into special buffers, and we want |
807 // the closing data headers into said buffers too. |
807 // the closing data headers into said buffers too. |
808 buffer()->WriteDWord (dataheader); |
808 buffer()->WriteDWord (dataheader); |
809 mCurrentMode = PARSERMODE_TopLevel; |
809 mCurrentMode = PARSERMODE_TopLevel; |
810 mLexer->GetNext (TK_Semicolon); |
810 mLexer->Next (TK_Semicolon); |
811 } |
811 } |
812 |
812 |
813 // ============================================================================= |
813 // ============================================================================= |
814 // |
814 // |
815 void BotscriptParser::ParseEventdef() |
815 void BotscriptParser::ParseEventdef() |
818 |
818 |
819 mLexer->MustGetNext (TK_Number); |
819 mLexer->MustGetNext (TK_Number); |
820 e->number = GetTokenString().ToLong(); |
820 e->number = GetTokenString().ToLong(); |
821 mLexer->MustGetNext (TK_Colon); |
821 mLexer->MustGetNext (TK_Colon); |
822 mLexer->MustGetNext (TK_Symbol); |
822 mLexer->MustGetNext (TK_Symbol); |
823 e->name = mLexer->GetToken()->text; |
823 e->name = mLexer->Token()->text; |
824 mLexer->MustGetNext (TK_ParenStart); |
824 mLexer->MustGetNext (TK_ParenStart); |
825 mLexer->MustGetNext (TK_ParenEnd); |
825 mLexer->MustGetNext (TK_ParenEnd); |
826 mLexer->MustGetNext (TK_Semicolon); |
826 mLexer->MustGetNext (TK_Semicolon); |
827 AddEvent (e); |
827 AddEvent (e); |
828 } |
828 } |
834 CommandInfo* comm = new CommandInfo; |
834 CommandInfo* comm = new CommandInfo; |
835 comm->origin = mLexer->DescribeCurrentPosition(); |
835 comm->origin = mLexer->DescribeCurrentPosition(); |
836 |
836 |
837 // Return value |
837 // Return value |
838 mLexer->MustGetAnyOf ({TK_Int,TK_Void,TK_Bool,TK_Str}); |
838 mLexer->MustGetAnyOf ({TK_Int,TK_Void,TK_Bool,TK_Str}); |
839 comm->returnvalue = GetTypeByName (mLexer->GetToken()->text); // TODO |
839 comm->returnvalue = GetTypeByName (mLexer->Token()->text); // TODO |
840 assert (comm->returnvalue != -1); |
840 assert (comm->returnvalue != -1); |
841 |
841 |
842 // Number |
842 // Number |
843 mLexer->MustGetNext (TK_Number); |
843 mLexer->MustGetNext (TK_Number); |
844 comm->number = mLexer->GetToken()->text.ToLong(); |
844 comm->number = mLexer->Token()->text.ToLong(); |
845 mLexer->MustGetNext (TK_Colon); |
845 mLexer->MustGetNext (TK_Colon); |
846 |
846 |
847 // Name |
847 // Name |
848 mLexer->MustGetNext (TK_Symbol); |
848 mLexer->MustGetNext (TK_Symbol); |
849 comm->name = mLexer->GetToken()->text; |
849 comm->name = mLexer->Token()->text; |
850 |
850 |
851 // Arguments |
851 // Arguments |
852 mLexer->MustGetNext (TK_ParenStart); |
852 mLexer->MustGetNext (TK_ParenStart); |
853 comm->minargs = 0; |
853 comm->minargs = 0; |
854 |
854 |
857 if (comm->args.IsEmpty() == false) |
857 if (comm->args.IsEmpty() == false) |
858 mLexer->MustGetNext (TK_Comma); |
858 mLexer->MustGetNext (TK_Comma); |
859 |
859 |
860 CommandArgument arg; |
860 CommandArgument arg; |
861 mLexer->MustGetAnyOf ({TK_Int,TK_Bool,TK_Str}); |
861 mLexer->MustGetAnyOf ({TK_Int,TK_Bool,TK_Str}); |
862 DataType type = GetTypeByName (mLexer->GetToken()->text); // TODO |
862 DataType type = GetTypeByName (mLexer->Token()->text); // TODO |
863 assert (type != -1 && type != TYPE_Void); |
863 assert (type != -1 && type != TYPE_Void); |
864 arg.type = type; |
864 arg.type = type; |
865 |
865 |
866 mLexer->MustGetNext (TK_Symbol); |
866 mLexer->MustGetNext (TK_Symbol); |
867 arg.name = mLexer->GetToken()->text; |
867 arg.name = mLexer->Token()->text; |
868 |
868 |
869 // If this is an optional parameter, we need the default value. |
869 // If this is an optional parameter, we need the default value. |
870 if (comm->minargs < comm->args.Size() || mLexer->PeekNextType (TK_Assign)) |
870 if (comm->minargs < comm->args.Size() || mLexer->PeekNextType (TK_Assign)) |
871 { |
871 { |
872 mLexer->MustGetNext (TK_Assign); |
872 mLexer->MustGetNext (TK_Assign); |
973 // |
973 // |
974 String BotscriptParser::ParseFloat() |
974 String BotscriptParser::ParseFloat() |
975 { |
975 { |
976 mLexer->TokenMustBe (TK_Number); |
976 mLexer->TokenMustBe (TK_Number); |
977 String floatstring = GetTokenString(); |
977 String floatstring = GetTokenString(); |
978 Lexer::Token tok; |
978 Lexer::TokenInfo tok; |
979 |
979 |
980 // Go after the decimal point |
980 // Go after the decimal point |
981 if (mLexer->PeekNext (&tok) && tok.type ==TK_Dot) |
981 if (mLexer->PeekNext (&tok) && tok.type ==TK_Dot) |
982 { |
982 { |
983 mLexer->Skip(); |
983 mLexer->Skip(); |
1007 TK_DoubleMinus, |
1007 TK_DoubleMinus, |
1008 }; |
1008 }; |
1009 |
1009 |
1010 mLexer->MustGetAnyOf (tokens); |
1010 mLexer->MustGetAnyOf (tokens); |
1011 |
1011 |
1012 switch (mLexer->GetTokenType()) |
1012 switch (mLexer->TokenType()) |
1013 { |
1013 { |
1014 case TK_Assign: return ASSIGNOP_Assign; |
1014 case TK_Assign: return ASSIGNOP_Assign; |
1015 case TK_AddAssign: return ASSIGNOP_Add; |
1015 case TK_AddAssign: return ASSIGNOP_Add; |
1016 case TK_SubAssign: return ASSIGNOP_Subtract; |
1016 case TK_SubAssign: return ASSIGNOP_Subtract; |
1017 case TK_MultiplyAssign: return ASSIGNOP_Multiply; |
1017 case TK_MultiplyAssign: return ASSIGNOP_Multiply; |
1084 |
1084 |
1085 if (var->isarray) |
1085 if (var->isarray) |
1086 { |
1086 { |
1087 mLexer->MustGetNext (TK_BracketStart); |
1087 mLexer->MustGetNext (TK_BracketStart); |
1088 Expression expr (this, mLexer, TYPE_Int); |
1088 Expression expr (this, mLexer, TYPE_Int); |
1089 expr.GetResult()->ConvertToBuffer(); |
1089 expr.Result()->ConvertToBuffer(); |
1090 arrayindex = expr.GetResult()->GetBuffer()->Clone(); |
1090 arrayindex = expr.Result()->Buffer()->Clone(); |
1091 mLexer->MustGetNext (TK_BracketEnd); |
1091 mLexer->MustGetNext (TK_BracketEnd); |
1092 } |
1092 } |
1093 |
1093 |
1094 // Get an operator |
1094 // Get an operator |
1095 AssignmentOperator oper = ParseAssignmentOperator(); |
1095 AssignmentOperator oper = ParseAssignmentOperator(); |
1167 // hehe |
1167 // hehe |
1168 if (fromhere == true) |
1168 if (fromhere == true) |
1169 mLexer->Skip (-1); |
1169 mLexer->Skip (-1); |
1170 |
1170 |
1171 Expression expr (this, mLexer, reqtype); |
1171 Expression expr (this, mLexer, reqtype); |
1172 expr.GetResult()->ConvertToBuffer(); |
1172 expr.Result()->ConvertToBuffer(); |
1173 |
1173 |
1174 // The buffer will be destroyed once the function ends so we need to |
1174 // The buffer will be destroyed once the function ends so we need to |
1175 // clone it now. |
1175 // clone it now. |
1176 return expr.GetResult()->GetBuffer()->Clone(); |
1176 return expr.Result()->Buffer()->Clone(); |
1177 } |
1177 } |
1178 |
1178 |
1179 // ============================================================================ |
1179 // ============================================================================ |
1180 // |
1180 // |
1181 DataBuffer* BotscriptParser::ParseStatement() |
1181 DataBuffer* BotscriptParser::ParseStatement() |
1182 { |
1182 { |
1183 // If it's a variable, expect assignment. |
1183 // If it's a variable, expect assignment. |
1184 if (mLexer->GetNext (TK_DollarSign)) |
1184 if (mLexer->Next (TK_DollarSign)) |
1185 { |
1185 { |
1186 mLexer->MustGetNext (TK_Symbol); |
1186 mLexer->MustGetNext (TK_Symbol); |
1187 Variable* var = FindVariable (GetTokenString()); |
1187 Variable* var = FindVariable (GetTokenString()); |
1188 |
1188 |
1189 if (var == null) |
1189 if (var == null) |
1220 info->casecursor++; |
1220 info->casecursor++; |
1221 } |
1221 } |
1222 |
1222 |
1223 // ============================================================================ |
1223 // ============================================================================ |
1224 // |
1224 // |
1225 bool BotscriptParser::TokenIs (TokenType a) |
1225 bool BotscriptParser::TokenIs (ETokenType a) |
1226 { |
1226 { |
1227 return (mLexer->GetTokenType() == a); |
1227 return (mLexer->TokenType() == a); |
1228 } |
1228 } |
1229 |
1229 |
1230 // ============================================================================ |
1230 // ============================================================================ |
1231 // |
1231 // |
1232 String BotscriptParser::GetTokenString() |
1232 String BotscriptParser::GetTokenString() |
1233 { |
1233 { |
1234 return mLexer->GetToken()->text; |
1234 return mLexer->Token()->text; |
1235 } |
1235 } |
1236 |
1236 |
1237 // ============================================================================ |
1237 // ============================================================================ |
1238 // |
1238 // |
1239 String BotscriptParser::DescribePosition() const |
1239 String BotscriptParser::DescribePosition() const |
1240 { |
1240 { |
1241 Lexer::Token* tok = mLexer->GetToken(); |
1241 Lexer::TokenInfo* tok = mLexer->Token(); |
1242 return tok->file + ":" + String (tok->line) + ":" + String (tok->column); |
1242 return tok->file + ":" + String (tok->line) + ":" + String (tok->column); |
1243 } |
1243 } |
1244 |
1244 |
1245 // ============================================================================ |
1245 // ============================================================================ |
1246 // |
1246 // |
1312 |
1312 |
1313 if (fp == null) |
1313 if (fp == null) |
1314 Error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1314 Error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1315 |
1315 |
1316 // First, resolve references |
1316 // First, resolve references |
1317 for (MarkReference* ref : mMainBuffer->GetReferences()) |
1317 for (MarkReference* ref : mMainBuffer->References()) |
1318 for (int i = 0; i < 4; ++i) |
1318 for (int i = 0; i < 4; ++i) |
1319 mMainBuffer->GetBuffer()[ref->pos + i] = (ref->target->pos >> (8 * i)) & 0xFF; |
1319 mMainBuffer->Buffer()[ref->pos + i] = (ref->target->pos >> (8 * i)) & 0xFF; |
1320 |
1320 |
1321 // Then, dump the main buffer to the file |
1321 // Then, dump the main buffer to the file |
1322 fwrite (mMainBuffer->GetBuffer(), 1, mMainBuffer->GetWrittenSize(), fp); |
1322 fwrite (mMainBuffer->Buffer(), 1, mMainBuffer->WrittenSize(), fp); |
1323 Print ("-- %1 byte%s1 written to %2\n", mMainBuffer->GetWrittenSize(), outfile); |
1323 Print ("-- %1 byte%s1 written to %2\n", mMainBuffer->WrittenSize(), outfile); |
1324 fclose (fp); |
1324 fclose (fp); |
1325 } |
1325 } |
1326 |
1326 |
1327 // ============================================================================ |
1327 // ============================================================================ |
1328 // |
1328 // |