some WIP commit
This commit is contained in:
@@ -87,7 +87,7 @@ public:
|
|||||||
if (peek() == ']') {
|
if (peek() == ']') {
|
||||||
throw error("empty enumeration is not allowed");
|
throw error("empty enumeration is not allowed");
|
||||||
}
|
}
|
||||||
auto enumvalue = std::string(readUntil(']'));
|
auto enumvalue = "|"+std::string(readUntil(']'))+"|";
|
||||||
size_t offset = enumvalue.find(' ');
|
size_t offset = enumvalue.find(' ');
|
||||||
if (offset != std::string::npos) {
|
if (offset != std::string::npos) {
|
||||||
goBack(enumvalue.length()-offset);
|
goBack(enumvalue.length()-offset);
|
||||||
@@ -157,22 +157,64 @@ public:
|
|||||||
return Command(name, std::move(args), std::move(kwargs), executor);
|
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();
|
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 args = dynamic::create_list();
|
||||||
auto kwargs = dynamic::create_map();
|
auto kwargs = dynamic::create_map();
|
||||||
|
|
||||||
|
int arg_index = 0;
|
||||||
|
|
||||||
while (hasNext()) {
|
while (hasNext()) {
|
||||||
auto value = parseValue();
|
auto value = parseValue();
|
||||||
if (hasNext() && peek() == '=') {
|
if (hasNext() && peek() == '=') {
|
||||||
auto key = std::get<std::string>(value);
|
auto key = std::get<std::string>(value);
|
||||||
nextChar();
|
nextChar();
|
||||||
kwargs->put(key, parseValue());
|
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;
|
return &found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandInput CommandsInterpreter::parse(std::string_view text) {
|
Prompt CommandsInterpreter::parse(std::string_view text) {
|
||||||
return CommandParser("<string>", text).parsePrompt();
|
return CommandParser("<string>", text).parsePrompt(repository.get());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ namespace cmd {
|
|||||||
std::string enumname;
|
std::string enumname;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandInput {
|
class Command;
|
||||||
std::string name; // command name
|
|
||||||
|
struct Prompt {
|
||||||
|
Command* command;
|
||||||
dynamic::List_sptr args; // positional arguments list
|
dynamic::List_sptr args; // positional arguments list
|
||||||
dynamic::Map_sptr kwargs; // keyword arguments table
|
dynamic::Map_sptr kwargs; // keyword arguments table
|
||||||
};
|
};
|
||||||
@@ -50,9 +52,15 @@ namespace cmd {
|
|||||||
args(std::move(args)),
|
args(std::move(args)),
|
||||||
kwargs(std::move(kwargs)),
|
kwargs(std::move(kwargs)),
|
||||||
executor(executor) {}
|
executor(executor) {}
|
||||||
|
|
||||||
|
Argument* getArgument(size_t index) {
|
||||||
|
if (index >= args.size())
|
||||||
|
return nullptr;
|
||||||
|
return &args[index];
|
||||||
|
}
|
||||||
|
|
||||||
dynamic::Value execute(const CommandInput& input) {
|
dynamic::Value execute(const Prompt& prompt) {
|
||||||
return executor(input.args, input.kwargs);
|
return executor(prompt.args, prompt.kwargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& getName() const {
|
const std::string& getName() const {
|
||||||
@@ -75,7 +83,11 @@ namespace cmd {
|
|||||||
CommandsInterpreter(std::unique_ptr<CommandsRepository> repository)
|
CommandsInterpreter(std::unique_ptr<CommandsRepository> repository)
|
||||||
: repository(std::move(repository)){}
|
: repository(std::move(repository)){}
|
||||||
|
|
||||||
CommandInput parse(std::string_view text);
|
Prompt parse(std::string_view text);
|
||||||
|
|
||||||
|
CommandsRepository* getRepository() const {
|
||||||
|
return repository.get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user