From b1da06dc11f358f0180f0776a92f3f3579a9d963 Mon Sep 17 00:00:00 2001 From: Mauro Junior <45118493+jetrotal@users.noreply.github.com> Date: Fri, 10 Nov 2023 09:18:03 -0300 Subject: [PATCH] Multiline interpreter + major refactor Managed to make it work, but the code is a bit messy and its syntax is not very flexible; Update dynrpg_easyrpg.cpp --- src/dynrpg_easyrpg.cpp | 81 ++++++++++++++++++++++++++++++++---------- src/game_dynrpg.cpp | 39 +++++++++++++++++++- 2 files changed, 100 insertions(+), 20 deletions(-) diff --git a/src/dynrpg_easyrpg.cpp b/src/dynrpg_easyrpg.cpp index 57f24aad01a..726e181bb6b 100644 --- a/src/dynrpg_easyrpg.cpp +++ b/src/dynrpg_easyrpg.cpp @@ -17,6 +17,7 @@ // Headers #include +#include #include "dynrpg_easyrpg.h" #include "string_view.h" @@ -99,42 +100,84 @@ bool DynRpg::EasyRpgPlugin::EasyRaw(dyn_arg_list args, Game_Interpreter* interpr Constants constList; const std::string func = "easyrpg_raw"; - bool okay = false; + int codeArgIndex = 0; int stringArgIndex = 1; + int indentArgIndex = -1; + + std::string tempArg; bool endOfLine = false; + bool okay = false; lcf::rpg::EventCommand cmd; + lcf::rpg::EventCommand _cmd; std::vector outputArgs; std::vector cmdList; for (size_t i = 0; i < args.size(); ++i) { - if (i == args.size() - 1) { - if (args[i].back() == ';') args[i] = args[i].substr(0, args[i].length() - 1); - endOfLine = true; + + bool valid = !args[i].empty(); + + if (valid && args[i].front() == '[') args[i] = args[i].substr(1); + if (valid && args[i].back() == ']') { + args[i] = args[i].substr(0, args[i].length() - 1); + indentArgIndex = i + 1; } - // TODO: Implement multi-line command interpretation split by ';'. + if (i == args.size() - 1) endOfLine = true; + - if (i == codeArgIndex) { - if (args[i].front() == '@') args[i] = constList.get("EventCode", args[i].substr(1)); - std::tie(cmd.code) = DynRpg::ParseArgs(func, args, &okay); - } - else if (i == stringArgIndex) { - auto [stringArg] = DynRpg::ParseArgs(func, args.subspan(i), &okay); - cmd.string = lcf::DBString(stringArg); - } - else { - if (args[i].front() == '@') args[i] = constList.get("DestinyScript", args[i].substr(1)); - auto [intArg] = DynRpg::ParseArgs(func, args.subspan(i), &okay); - outputArgs.push_back(intArg); + else if (args[i] == ";") { + endOfLine = !args[i + 1].empty(); + valid = 0; } + if (valid) { + if (i == codeArgIndex) + { + size_t start_pos = args[i].find_first_not_of(" \t\r\n"); + if (start_pos != std::string::npos) + args[i] = args[i].substr(start_pos); + + Output::Debug("code ----> {}", args[i]); + + if (args[i].front() == '@') + args[i] = constList.get("EventCode", args[i].substr(1)); + std::tie(cmd.code) = DynRpg::ParseArgs(func, args.subspan(i), &okay); + } + else if (i == stringArgIndex) + { + Output::Debug("str ----> {}", args[i]); + auto [stringArg] = DynRpg::ParseArgs(func, args.subspan(i), &okay); + cmd.string = lcf::DBString(stringArg); + } + else + { + if (args[i].front() == '@') + args[i] = constList.get("DestinyScript", args[i].substr(1)); + auto [intArg] = DynRpg::ParseArgs(func, args.subspan(i), &okay); + + if (indentArgIndex == i) { + Output::Debug("idt ----> {}", args[i]); + indentArgIndex = -1; + cmd.indent = intArg; + } + else + Output::Debug("pls ----> {}", args[i]), outputArgs.push_back(intArg); + } + } if (endOfLine) { - codeArgIndex = i + 1; - stringArgIndex = i + 2; + Output::Debug("com ----> {}\n\n", cmd.code); cmd.parameters = lcf::DBArray(outputArgs.begin(), outputArgs.end()); cmdList.push_back(cmd); + outputArgs.clear(); + + cmd = _cmd; + + codeArgIndex = i + 1; + stringArgIndex = i + 2; + + endOfLine = false; } if (!okay) return true; diff --git a/src/game_dynrpg.cpp b/src/game_dynrpg.cpp index 2b9e65e8d7a..68ba7087a08 100644 --- a/src/game_dynrpg.cpp +++ b/src/game_dynrpg.cpp @@ -314,7 +314,44 @@ std::string DynRpg::ParseCommand(std::string command, std::vector& token.str(""); break; } - } else { + } + else if (chr == ';') { + switch (mode) { + case ParseMode_Function: + // End of function token + function_name = Utils::LowerCase(token.str()); + if (function_name.empty()) { + // empty function name + Output::Warning("Empty DynRPG function name"); + return {}; + } + token.str(""); + // Empty arg + args.emplace_back(""); + mode = ParseMode_WaitForArg; + break; + case ParseMode_WaitForComma: + mode = ParseMode_WaitForArg; + break; + case ParseMode_WaitForArg: + + // Empty arg + args.emplace_back(""); + break; + case ParseMode_String: + token << chr; + break; + case ParseMode_Token: + tmp = ParseToken(token.str(), function_name); + args.emplace_back(tmp); + if (function_name == "easyrpg_raw") args.emplace_back(";"); + // already on a comma + mode = ParseMode_WaitForArg; + token.str(""); + break; + } + } + else { // Anything else that isn't special purpose switch (mode) { case ParseMode_Function: