From f54cba92aedd305b2acd512a57fa5fe43ca4905e 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; --- src/dynrpg_easyrpg.cpp | 63 ++++++++++++++++++++++++++++++++++-------- src/game_dynrpg.cpp | 39 +++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/dynrpg_easyrpg.cpp b/src/dynrpg_easyrpg.cpp index 57f24aad01a..f512702526f 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,82 @@ 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) { + + 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; + } + if (i == args.size() - 1) { - if (args[i].back() == ';') args[i] = args[i].substr(0, args[i].length() - 1); endOfLine = true; } - // TODO: Implement multi-line command interpretation split by ';'. + else if (args[i] == ";") { + endOfLine = true; + valid = 0; + } + + if (valid && 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 (i == codeArgIndex) { if (args[i].front() == '@') args[i] = constList.get("EventCode", args[i].substr(1)); - std::tie(cmd.code) = DynRpg::ParseArgs(func, args, &okay); + std::tie(cmd.code) = DynRpg::ParseArgs(func, args.subspan(i), &okay); } - else if (i == stringArgIndex) { + else if (valid && 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)); + else if (valid){ + + if (valid && 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); + + 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.code = 0; + cmd.string = ""; + cmd.parameters = lcf::DBArray(outputArgs.begin(), outputArgs.end()); + + 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: