add basics of generic command parsing

This commit is contained in:
Luna 2020-05-30 17:48:14 -03:00
parent d86e9efe43
commit 27f499dfbb

View file

@ -318,32 +318,51 @@ pub const Lang = struct {
self.doError("No command given", .{}); self.doError("No command given", .{});
continue; continue;
} }
var command = cmd_opt.?; const command_string = cmd_opt.?;
var ctype_opt = self.getCommand(command); var found: bool = false;
var ctype: CommandType = undefined;
if (ctype_opt) |ctype_val| { inline for (@typeInfo(NewCommand).Struct.decls) |cmd_struct_decl| {
ctype = ctype_val; const struct_name = cmd_struct_decl.name;
} else { comptime var lowered_command_name = [_]u8{0} ** struct_name.len;
self.doError("Unknown command '{}' ({})", .{ command, command.len }); comptime {
for (struct_name) |c, i| {
lowered_command_name[i] = std.ascii.toLower(c);
}
}
if (std.mem.eql(u8, &lowered_command_name, command_string)) {
found = true;
// Based on the command struct fields, we need to decide
// how to actually get its arguments and creating the struct
// itself.
const command_struct = cmd_struct_decl.data.Type;
var cmd: command_struct = undefined;
inline for (@typeInfo(command_struct).Struct.fields) |cmd_field| {
// TODO: crash when no arguments are left but we still need
// arguments...
const argument = tok_it.next().?;
const argument_value = switch (cmd_field.field_type) {
usize => try std.fmt.parseInt(usize, arg, 10),
i32 => try std.fmt.parseInt(i32, arg, 10),
f32 => try std.fmt.parseFloat(f32, arg),
else => @panic("Invalid parameter type (" ++ @typeName(cmd_field.field_type) ++ ") left on command struct " ++ @typeName(command_struct) ++ "."),
};
@field(cmd, cmd_field.name) = argument_value;
}
}
}
if (!found) {
self.doError("Unknown command '{}' ({})", .{ command_string, command_string.len });
continue; continue;
} }
var args = ArgList.init(self.allocator); // try cmds.append(cmd);
errdefer args.deinit();
while (tok_it.next()) |arg| {
try args.append(arg);
}
// construct final Command based on command
var cmd = Command{ .command = ctype, .args = args };
self.validateCommand(cmd) catch |err| {
//self.doError("error validating command '{}': {}", command, err);
continue;
};
try cmds.append(cmd);
} }
if (self.has_error) return ParseError.ParseFail; if (self.has_error) return ParseError.ParseFail;