some WIP commit

This commit is contained in:
MihailRis 2024-05-10 01:08:00 +03:00
parent 0836457c17
commit bdd1055073
2 changed files with 65 additions and 11 deletions

View File

@ -87,7 +87,7 @@ public:
if (peek() == ']') {
throw error("empty enumeration is not allowed");
}
auto enumvalue = std::string(readUntil(']'));
auto enumvalue = "|"+std::string(readUntil(']'))+"|";
size_t offset = enumvalue.find(' ');
if (offset != std::string::npos) {
goBack(enumvalue.length()-offset);
@ -157,22 +157,64 @@ public:
return Command(name, std::move(args), std::move(kwargs), executor);
}
CommandInput parsePrompt() {
bool typeCheck(Argument* arg, const dynamic::Value& value) {
switch (arg->type) {
case ArgType::enumvalue: {
auto& enumname = arg->enumname;
if (auto* string = std::get_if<std::string>(&value)) {
if (enumname.find("|"+*string+"|") == std::string::npos) {
throw error("invalid enumeration value");
}
} else {
if (arg->optional) {
return false;
}
throw error("enumeration value expected");
}
break;
}
case ArgType::number: {
// FIXME
}
}
return true;
}
Prompt parsePrompt(CommandsRepository* repo) {
std::string name = parseIdentifier();
auto command = repo->get(name);
if (command == nullptr) {
throw error("unknown command "+util::quote(name));
}
auto args = dynamic::create_list();
auto kwargs = dynamic::create_map();
int arg_index = 0;
while (hasNext()) {
auto value = parseValue();
if (hasNext() && peek() == '=') {
auto key = std::get<std::string>(value);
nextChar();
kwargs->put(key, parseValue());
} else {
Argument* arg;
do {
arg = command->getArgument(arg_index++);
if (arg == nullptr) {
throw error("extra positional argument");
}
} while (!typeCheck(arg, value));
args->put(value);
}
args->put(value);
}
return CommandInput {name, args, kwargs};
while (auto arg = command->getArgument(arg_index++)) {
if (!arg->optional) {
throw error("missing argument "+util::quote(arg->name));
}
}
return Prompt {command, args, kwargs};
}
};
@ -193,6 +235,6 @@ Command* CommandsRepository::get(const std::string& name) {
return &found->second;
}
CommandInput CommandsInterpreter::parse(std::string_view text) {
return CommandParser("<string>", text).parsePrompt();
Prompt CommandsInterpreter::parse(std::string_view text) {
return CommandParser("<string>", text).parsePrompt(repository.get());
}

View File

@ -22,8 +22,10 @@ namespace cmd {
std::string enumname;
};
struct CommandInput {
std::string name; // command name
class Command;
struct Prompt {
Command* command;
dynamic::List_sptr args; // positional arguments list
dynamic::Map_sptr kwargs; // keyword arguments table
};
@ -50,9 +52,15 @@ namespace cmd {
args(std::move(args)),
kwargs(std::move(kwargs)),
executor(executor) {}
Argument* getArgument(size_t index) {
if (index >= args.size())
return nullptr;
return &args[index];
}
dynamic::Value execute(const CommandInput& input) {
return executor(input.args, input.kwargs);
dynamic::Value execute(const Prompt& prompt) {
return executor(prompt.args, prompt.kwargs);
}
const std::string& getName() const {
@ -75,7 +83,11 @@ namespace cmd {
CommandsInterpreter(std::unique_ptr<CommandsRepository> repository)
: repository(std::move(repository)){}
CommandInput parse(std::string_view text);
Prompt parse(std::string_view text);
CommandsRepository* getRepository() const {
return repository.get();
}
};
}