mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-12 18:31:41 +01:00
Separate the dispatcher from the parsing algorithm
This commit is contained in:
parent
86908fbd0e
commit
e9d91fd21e
@ -4,6 +4,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.command.builder.parser.CommandParser;
|
||||
import net.minestom.server.command.builder.parser.CommandSuggestionHolder;
|
||||
import net.minestom.server.command.builder.parser.ValidSyntaxHolder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -152,111 +155,7 @@ public class CommandDispatcher {
|
||||
Int2ObjectRBTreeMap<CommandSuggestionHolder> syntaxesSuggestions = new Int2ObjectRBTreeMap<>(Collections.reverseOrder());
|
||||
|
||||
for (CommandSyntax syntax : syntaxes) {
|
||||
// List of all arguments in the current syntax
|
||||
final Argument<?>[] arguments = syntax.getArguments();
|
||||
// Empty object containing the maximum amount of argument results of the syntax.
|
||||
final List<Object> argsValues = new ArrayList<>(arguments.length);
|
||||
|
||||
boolean syntaxCorrect = true;
|
||||
// The current index in the raw command string arguments
|
||||
int splitIndex = 0;
|
||||
|
||||
boolean useRemaining = false;
|
||||
// Check the validity of the arguments...
|
||||
for (int argCount = 0; argCount < arguments.length; argCount++) {
|
||||
final boolean lastArgumentIteration = argCount + 1 == arguments.length;
|
||||
final Argument<?> argument = arguments[argCount];
|
||||
useRemaining = argument.useRemaining();
|
||||
|
||||
// the parsed argument value, null if incorrect
|
||||
Object parsedValue;
|
||||
// the argument exception, null if the input is correct
|
||||
ArgumentSyntaxException argumentSyntaxException = null;
|
||||
// true if the arg is valid, false otherwise
|
||||
boolean correct = false;
|
||||
// the raw string representing the correct argument syntax
|
||||
StringBuilder argValue = new StringBuilder();
|
||||
|
||||
if (useRemaining) {
|
||||
final boolean hasArgs = args.length > splitIndex;
|
||||
// Verify if there is any string part available
|
||||
if (hasArgs) {
|
||||
// Argument is supposed to take the rest of the command input
|
||||
for (int i = splitIndex; i < args.length; i++) {
|
||||
final String arg = args[i];
|
||||
if (argValue.length() > 0)
|
||||
argValue.append(StringUtils.SPACE);
|
||||
argValue.append(arg);
|
||||
}
|
||||
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
try {
|
||||
parsedValue = argument.parse(argValueString);
|
||||
correct = true;
|
||||
argsValues.add(parsedValue);
|
||||
} catch (ArgumentSyntaxException exception) {
|
||||
argumentSyntaxException = exception;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Argument is either single-word or can accept optional delimited space(s)
|
||||
for (int i = splitIndex; i < args.length; i++) {
|
||||
final String rawArg = args[i];
|
||||
|
||||
argValue.append(rawArg);
|
||||
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
try {
|
||||
parsedValue = argument.parse(argValueString);
|
||||
|
||||
// Prevent quitting the parsing too soon if the argument
|
||||
// does not allow space
|
||||
if (lastArgumentIteration && i + 1 < args.length) {
|
||||
if (!argument.allowSpace())
|
||||
break;
|
||||
argValue.append(StringUtils.SPACE);
|
||||
continue;
|
||||
}
|
||||
|
||||
correct = true;
|
||||
argsValues.add(parsedValue);
|
||||
splitIndex = i + 1;
|
||||
break;
|
||||
} catch (ArgumentSyntaxException exception) {
|
||||
argumentSyntaxException = exception;
|
||||
|
||||
if (!argument.allowSpace())
|
||||
break;
|
||||
argValue.append(StringUtils.SPACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!correct) {
|
||||
// Argument is not correct, add it to the syntax suggestion with the number
|
||||
// of correct argument(s) and do not check the next syntax argument
|
||||
syntaxCorrect = false;
|
||||
CommandSuggestionHolder suggestionHolder = new CommandSuggestionHolder();
|
||||
suggestionHolder.syntax = syntax;
|
||||
suggestionHolder.argumentSyntaxException = argumentSyntaxException;
|
||||
suggestionHolder.argIndex = argCount;
|
||||
syntaxesSuggestions.put(argCount, suggestionHolder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the syntax to the list of valid syntaxes if correct
|
||||
if (syntaxCorrect) {
|
||||
if (arguments.length == argsValues.size() || useRemaining) {
|
||||
ValidSyntaxHolder validSyntaxHolder = new ValidSyntaxHolder();
|
||||
validSyntaxHolder.syntax = syntax;
|
||||
validSyntaxHolder.argumentsValue = argsValues;
|
||||
|
||||
validSyntaxes.add(validSyntaxHolder);
|
||||
}
|
||||
}
|
||||
CommandParser.parse(syntax, syntax.getArguments(), args, validSyntaxes, syntaxesSuggestions);
|
||||
}
|
||||
|
||||
// Check if there is at least one correct syntax
|
||||
@ -319,7 +218,7 @@ public class CommandDispatcher {
|
||||
|
||||
final Argument<?>[] arguments = syntax.getArguments();
|
||||
final int argumentsCount = arguments.length;
|
||||
final List<Object> argsValues = validSyntaxHolder.argumentsValue;
|
||||
final Map<Argument<?>, Object> argsValues = validSyntaxHolder.argumentsValue;
|
||||
|
||||
final int argsSize = argsValues.size();
|
||||
|
||||
@ -329,9 +228,9 @@ public class CommandDispatcher {
|
||||
|
||||
// Fill arguments map
|
||||
Arguments syntaxValues = new Arguments();
|
||||
for (int i = 0; i < argumentsCount; i++) {
|
||||
final Argument<?> argument = arguments[i];
|
||||
final Object argumentValue = argsValues.get(i);
|
||||
for (Map.Entry<Argument<?>, Object> entry : argsValues.entrySet()) {
|
||||
final Argument<?> argument = entry.getKey();
|
||||
final Object argumentValue = entry.getValue();
|
||||
|
||||
syntaxValues.setArg(argument.getId(), argumentValue);
|
||||
}
|
||||
@ -346,24 +245,4 @@ public class CommandDispatcher {
|
||||
|
||||
return finalSyntax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the data of a validated syntax.
|
||||
*/
|
||||
private static class ValidSyntaxHolder {
|
||||
private CommandSyntax syntax;
|
||||
/**
|
||||
* (Argument index/Argument parsed object)
|
||||
*/
|
||||
private List<Object> argumentsValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the data of an invalidated syntax.
|
||||
*/
|
||||
private static class CommandSuggestionHolder {
|
||||
private CommandSyntax syntax;
|
||||
private ArgumentSyntaxException argumentSyntaxException;
|
||||
private int argIndex;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ public class ArgumentType {
|
||||
return new ArgumentLiteral(id);
|
||||
}
|
||||
|
||||
public static ArgumentGroup Group(@NotNull String id, @NotNull Argument<?>... arguments) {
|
||||
return new ArgumentGroup(id, arguments);
|
||||
}
|
||||
|
||||
public static ArgumentBoolean Boolean(@NotNull String id) {
|
||||
return new ArgumentBoolean(id);
|
||||
}
|
||||
|
@ -0,0 +1,128 @@
|
||||
package net.minestom.server.command.builder.parser;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
|
||||
import net.minestom.server.command.builder.CommandSyntax;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandParser {
|
||||
|
||||
public static void parse(@NotNull CommandSyntax syntax, @NotNull Argument<?>[] commandArguments, @NotNull String[] inputArguments,
|
||||
@Nullable List<ValidSyntaxHolder> validSyntaxes,
|
||||
@Nullable Int2ObjectRBTreeMap<CommandSuggestionHolder> syntaxesSuggestions) {
|
||||
final Map<Argument<?>, Object> argsValues = new HashMap<>();
|
||||
|
||||
boolean syntaxCorrect = true;
|
||||
// The current index in the raw command string arguments
|
||||
int splitIndex = 0;
|
||||
|
||||
boolean useRemaining = false;
|
||||
// Check the validity of the arguments...
|
||||
for (int argCount = 0; argCount < commandArguments.length; argCount++) {
|
||||
final boolean lastArgumentIteration = argCount + 1 == commandArguments.length;
|
||||
final Argument<?> argument = commandArguments[argCount];
|
||||
useRemaining = argument.useRemaining();
|
||||
|
||||
// the parsed argument value, null if incorrect
|
||||
Object parsedValue;
|
||||
// the argument exception, null if the input is correct
|
||||
ArgumentSyntaxException argumentSyntaxException = null;
|
||||
// true if the arg is valid, false otherwise
|
||||
boolean correct = false;
|
||||
// the raw string representing the correct argument syntax
|
||||
StringBuilder argValue = new StringBuilder();
|
||||
|
||||
if (useRemaining) {
|
||||
final boolean hasArgs = inputArguments.length > splitIndex;
|
||||
// Verify if there is any string part available
|
||||
if (hasArgs) {
|
||||
// Argument is supposed to take the rest of the command input
|
||||
for (int i = splitIndex; i < inputArguments.length; i++) {
|
||||
final String arg = inputArguments[i];
|
||||
if (argValue.length() > 0)
|
||||
argValue.append(StringUtils.SPACE);
|
||||
argValue.append(arg);
|
||||
}
|
||||
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
try {
|
||||
parsedValue = argument.parse(argValueString);
|
||||
correct = true;
|
||||
argsValues.put(argument, parsedValue);
|
||||
} catch (ArgumentSyntaxException exception) {
|
||||
argumentSyntaxException = exception;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Argument is either single-word or can accept optional delimited space(s)
|
||||
for (int i = splitIndex; i < inputArguments.length; i++) {
|
||||
final String rawArg = inputArguments[i];
|
||||
|
||||
argValue.append(rawArg);
|
||||
|
||||
final String argValueString = argValue.toString();
|
||||
|
||||
try {
|
||||
parsedValue = argument.parse(argValueString);
|
||||
|
||||
// Prevent quitting the parsing too soon if the argument
|
||||
// does not allow space
|
||||
if (lastArgumentIteration && i + 1 < inputArguments.length) {
|
||||
if (!argument.allowSpace())
|
||||
break;
|
||||
argValue.append(StringUtils.SPACE);
|
||||
continue;
|
||||
}
|
||||
|
||||
correct = true;
|
||||
argsValues.put(argument, parsedValue);
|
||||
splitIndex = i + 1;
|
||||
break;
|
||||
} catch (ArgumentSyntaxException exception) {
|
||||
argumentSyntaxException = exception;
|
||||
|
||||
if (!argument.allowSpace())
|
||||
break;
|
||||
argValue.append(StringUtils.SPACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!correct) {
|
||||
// Argument is not correct, add it to the syntax suggestion with the number
|
||||
// of correct argument(s) and do not check the next syntax argument
|
||||
syntaxCorrect = false;
|
||||
if (syntaxesSuggestions != null) {
|
||||
CommandSuggestionHolder suggestionHolder = new CommandSuggestionHolder();
|
||||
suggestionHolder.syntax = syntax;
|
||||
suggestionHolder.argumentSyntaxException = argumentSyntaxException;
|
||||
suggestionHolder.argIndex = argCount;
|
||||
syntaxesSuggestions.put(argCount, suggestionHolder);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the syntax to the list of valid syntaxes if correct
|
||||
if (syntaxCorrect) {
|
||||
if (commandArguments.length == argsValues.size() || useRemaining) {
|
||||
if (validSyntaxes != null) {
|
||||
ValidSyntaxHolder validSyntaxHolder = new ValidSyntaxHolder();
|
||||
validSyntaxHolder.syntax = syntax;
|
||||
validSyntaxHolder.argumentsValue = argsValues;
|
||||
|
||||
validSyntaxes.add(validSyntaxHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package net.minestom.server.command.builder.parser;
|
||||
|
||||
import net.minestom.server.command.builder.CommandSyntax;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
|
||||
/**
|
||||
* Holds the data of an invalidated syntax.
|
||||
*/
|
||||
public class CommandSuggestionHolder {
|
||||
public CommandSyntax syntax;
|
||||
public ArgumentSyntaxException argumentSyntaxException;
|
||||
public int argIndex;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package net.minestom.server.command.builder.parser;
|
||||
|
||||
import net.minestom.server.command.builder.CommandSyntax;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Holds the data of a validated syntax.
|
||||
*/
|
||||
public class ValidSyntaxHolder {
|
||||
public CommandSyntax syntax;
|
||||
public Map<Argument<?>, Object> argumentsValue;
|
||||
}
|
Loading…
Reference in New Issue
Block a user