From 6ba3334681fb9962ddd66d3aed797592f30c80f0 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 9 May 2024 17:03:48 +0300 Subject: [PATCH] CommandsInterpreter scheme parsing --- src/logic/CommandsInterpreter.cpp | 121 +++++++++++++++++++++++++++++- src/logic/CommandsInterpreter.hpp | 11 ++- 2 files changed, 127 insertions(+), 5 deletions(-) diff --git a/src/logic/CommandsInterpreter.cpp b/src/logic/CommandsInterpreter.cpp index 25c76362..16e979ce 100644 --- a/src/logic/CommandsInterpreter.cpp +++ b/src/logic/CommandsInterpreter.cpp @@ -1,13 +1,128 @@ #include "CommandsInterpreter.hpp" #include "../coders/commons.hpp" +#include "../util/stringutil.hpp" + +#include using namespace cmd; +inline bool is_cmd_identifier_part(char c) { + return is_identifier_part(c) || c == '.' || c == '$'; +} + class SchemeParser : BasicParser { - + std::string parseIdentifier() { + char c = peek(); + if (!is_identifier_start(c) && c != '$') { + if (c == '"') { + pos++; + return parseString(c); + } + throw error("identifier expected"); + } + int start = pos; + while (hasNext() && is_cmd_identifier_part(source[pos])) { + pos++; + } + return std::string(source.substr(start, pos-start)); + } + + std::unordered_map types { + {"num", ArgType::number}, + {"int", ArgType::integer}, + {"str", ArgType::string}, + {"selector", ArgType::selector}, + }; +public: + SchemeParser(std::string_view filename, std::string_view source) + : BasicParser(filename, source) { + } + + ArgType parseType() { + std::string name = parseIdentifier(); + std::cout << "type.name: " << name << std::endl; + auto found = types.find(name); + if (found != types.end()) { + return found->second; + } else { + throw error("unknown type "+util::quote(name)); + } + } + + dynamic::Value parseValue() { + char c = peek(); + if (is_cmd_identifier_part(c)) { + auto str = parseIdentifier(); + if (str == "true") { + return true; + } else if (str == "false") { + return false; + } else if (str == "none" || str == "nil" || str == "null") { + return std::monostate(); + } + return str; + } + if (c == '"') { + return parseIdentifier(); + } + if (c == '+' || c == '-' || is_digit(c)) { + return parseNumber(c == '-' ? -1 : 1); + } + throw error("invalid character '"+std::string({c})+"'"); + } + + Argument parseArgument() { + std::string name = parseIdentifier(); + expect(':'); + std::cout << "arg.name: " << name << std::endl; + ArgType type = parseType(); + bool optional = false; + dynamic::Value def {}; + dynamic::Value origin {}; + bool loop = true; + while (hasNext() && loop) { + char c = peek(); + switch (c) { + case '=': + nextChar(); + optional = true; + def = parseValue(); + break; + case '~': + nextChar(); + origin = parseValue(); + break; + default: + loop = false; + break; + } + } + return Argument {name, type, optional, def, origin}; + } + + Command parse(executor_func executor) { + std::string name = parseIdentifier(); + std::vector args; + std::unordered_map kwargs; + + std::cout << "command.name: " << name << std::endl; + while (hasNext()) { + if (peek() == '{') { + nextChar(); + while (peek() != '}') { + Argument arg = parseArgument(); + kwargs[arg.name] = arg; + } + nextChar(); + } else { + args.push_back(parseArgument()); + } + } + return Command(name, std::move(args), std::move(kwargs), executor); + } }; -Command Command::create(std::string_view scheme) { - +Command Command::create(std::string_view scheme, executor_func executor) { + return SchemeParser("", scheme).parse(executor); } diff --git a/src/logic/CommandsInterpreter.hpp b/src/logic/CommandsInterpreter.hpp index 8cf93fac..2a1332fc 100644 --- a/src/logic/CommandsInterpreter.hpp +++ b/src/logic/CommandsInterpreter.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace cmd { enum class ArgType { @@ -17,6 +18,7 @@ namespace cmd { ArgType type; bool optional; dynamic::Value def; + dynamic::Value origin; }; struct CommandInput { @@ -32,19 +34,24 @@ namespace cmd { class Command { std::string name; std::vector args; + std::unordered_map kwargs; executor_func executor; public: Command( std::string name, std::vector args, + std::unordered_map kwargs, executor_func executor - ); + ) : name(name), + args(std::move(args)), + kwargs(std::move(kwargs)), + executor(executor) {} dynamic::Value execute(const CommandInput& input) { return executor(input.args, input.kwargs); } - static Command create(std::string_view scheme); + static Command create(std::string_view scheme, executor_func); }; class CommandsInterpreter {