diff --git a/src/coders/commons.cpp b/src/coders/commons.cpp index 50538a50..81639499 100644 --- a/src/coders/commons.cpp +++ b/src/coders/commons.cpp @@ -154,8 +154,13 @@ void BasicParser::expectNewLine() { } } -void BasicParser::goBack() { - if (pos) pos--; +void BasicParser::goBack(size_t count) { + if (pos < count) { + throw std::runtime_error("pos < jump"); + } + if (pos) { + pos -= count; + } } char BasicParser::peek() { diff --git a/src/coders/commons.hpp b/src/coders/commons.hpp index c45d4f28..a9609c08 100644 --- a/src/coders/commons.hpp +++ b/src/coders/commons.hpp @@ -86,7 +86,7 @@ protected: void expect(const std::string& substring); bool isNext(const std::string& substring); void expectNewLine(); - void goBack(); + void goBack(size_t count=1); int64_t parseSimpleInt(int base); dynamic::Value parseNumber(int sign); diff --git a/src/logic/CommandsInterpreter.cpp b/src/logic/CommandsInterpreter.cpp index 7f5ff3a2..47a44307 100644 --- a/src/logic/CommandsInterpreter.cpp +++ b/src/logic/CommandsInterpreter.cpp @@ -11,7 +11,7 @@ inline bool is_cmd_identifier_part(char c) { return is_identifier_part(c) || c == '.' || c == '$' || c == '@'; } -class SchemeParser : BasicParser { +class CommandParser : BasicParser { std::string parseIdentifier() { char c = peek(); if (!is_identifier_start(c) && c != '$') { @@ -36,7 +36,7 @@ class SchemeParser : BasicParser { {"enum", ArgType::enumvalue}, }; public: - SchemeParser(std::string_view filename, std::string_view source) + CommandParser(std::string_view filename, std::string_view source) : BasicParser(filename, source) { } @@ -84,7 +84,9 @@ public: throw error("empty enumeration is not allowed"); } auto enumvalue = std::string(readUntil(']')); - if (enumvalue.find(' ') != std::string::npos) { + size_t offset = enumvalue.find(' '); + if (offset != std::string::npos) { + goBack(enumvalue.length()-offset); throw error("use '|' as separator, not a space"); } nextChar(); @@ -130,7 +132,7 @@ public: return Argument {name, type, optional, def, origin, enumname}; } - Command parse(executor_func executor) { + Command parseScheme(executor_func executor) { std::string name = parseIdentifier(); std::vector args; std::unordered_map kwargs; @@ -150,8 +152,31 @@ public: } return Command(name, std::move(args), std::move(kwargs), executor); } + + CommandInput parsePrompt() { + std::string name = parseIdentifier(); + + return CommandInput {name, nullptr, nullptr}; + } }; Command Command::create(std::string_view scheme, executor_func executor) { - return SchemeParser("", scheme).parse(executor); + return CommandParser("", scheme).parseScheme(executor); +} + +void CommandsRepository::add(std::string_view scheme, executor_func executor) { + Command command = Command::create(scheme, executor); + commands[command.getName()] = command; +} + +Command* CommandsRepository::get(const std::string& name) { + auto found = commands.find(name); + if (found == commands.end()) { + return nullptr; + } + return &found->second; +} + +CommandInput CommandsInterpreter::parse(std::string_view text) { + return CommandParser("", text).parsePrompt(); } diff --git a/src/logic/CommandsInterpreter.hpp b/src/logic/CommandsInterpreter.hpp index 6f656451..7bc80dd6 100644 --- a/src/logic/CommandsInterpreter.hpp +++ b/src/logic/CommandsInterpreter.hpp @@ -23,6 +23,7 @@ namespace cmd { }; struct CommandInput { + std::string name; // command name dynamic::List_sptr args; // positional arguments list dynamic::Map_sptr kwargs; // keyword arguments table }; @@ -38,6 +39,8 @@ namespace cmd { std::unordered_map kwargs; executor_func executor; public: + Command() {} + Command( std::string name, std::vector args, @@ -52,10 +55,27 @@ namespace cmd { return executor(input.args, input.kwargs); } + const std::string& getName() const { + return name; + } + static Command create(std::string_view scheme, executor_func); }; + class CommandsRepository { + std::unordered_map commands; + public: + void add(std::string_view scheme, executor_func); + Command* get(const std::string& name); + }; + class CommandsInterpreter { + std::unique_ptr repository; + public: + CommandsInterpreter(std::unique_ptr repository) + : repository(std::move(repository)){} + + CommandInput parse(std::string_view text); }; }