Java - 如何实现应用程序控制台解析器
Java - how to implement application console parser
所以我正在尝试编写一个具有程序内控制台界面的应用程序(即您不必每次都使用不同的命令从控制台 运行 程序),并且我想要一个解析器对象来解析来自用户的 commands/options。结构类似这样-
ArrayList<String> example = new ArrayList<>();
/* PARSING */
ConsoleParser parser = new ConsoleParser();
Scanner input = new Scanner(System.in);
String parserArgs = input.nextLine();
while (parserArgs != "quit")
{
execute(parser.parse(parserArgs));
parserArgs = input.nextLine();
}
所以我的想法是有一个控制台(在应用程序中),我可以在其中键入 'add x' 或 'contains x' 之类的命令,然后将其分配给 'parserArgs.' 然后命令string 将被传递到 ConsoleParser,在那里它将被分解并搜索有效命令。如果命令有效(并且有必要 options/arguments),ConsoleParser 的 parse() 方法将以某种方式 return 方法(或方法名称)到 main,以及该方法需要的任何参数。因此,如果我想将字符串 "foo" 添加到我的 ArrayList,那么我可以在控制台键入 'add foo' 并将其传递给解析器,然后解析器将 return 用于某种类型的主需要使用参数 'foo.' 在 'example' 上调用 ArrayList 的 add() 方法的说明我知道这可以使用 arraylist 轻松完成,但为了简单起见,我只是在这里使用它。
从你的问题来看,我不确定你想要一个简单的解决方案还是一个优雅的解决方案。
这是一个优雅的解决方案的草图。
您定义了一个功能接口,即只有一个方法的接口,该方法由您的解析器返回。
赞:
// I the Input type
// R the result type
public interface Fn<I,R> {
R apply (I input);
}
第二个输入仅提供执行方法
public interface Cmd<R> {
R execute ();
}
您定义控制台命令
public class CliCommand<A> {
// constructor
public CliCommand(final String name, final Fn<String, A> parseFunct)
{
// TODO
}
}
// the parse function
public A parse(String arg) throws CliParseException {
// TODO
}
}
添加命令
public class Add implements Cmd<Integer> {
public Add(Integer i) {
}
}
以及添加
的解析函数
public class ParseAdd implements Fn<String, Cmd<Integer>> {
public Cmd<Integer> apply(String option) {
// parse the input and return the command with the arguments in there
// if (option == "add" and args exist )
// try parse args
// i = Integer.parse(substring);
return new Add(i);
}
}
然后是 ConsoleParser
public class ConsoleParser<A> {
public static <A> ConsoleParser<A> cli(CliCommand <A> command) {
...
}
public ConsoleParser <A> or (CliCommand <A> command) {
...
}
public A parse(String arg) throws CliParseException {
//
}
}
之后你的程序可以这样写
ConsoleParser<Cmd<Object>> parser = cli("add",new ParseAdd())
.or(...)
.or("quit", new ParseQuit();
Scanner input = new Scanner(System.in);
String parserArgs = input.nextLine();
while (true)
{
try {
parser.parse(parserArgs).execute();
} catch (CliParseException e) {
// handle it somehow
}
parserArgs = input.nextLine();
}
在这个例子中,Add 太简单了,我想你实际上想要将 String 添加到一个列表或两个 Numbers 中,所以实际的 ParseAdd 方法需要一些上下文(比如一个已经存在的列表),就像我的简单示例中一样。
所以我正在尝试编写一个具有程序内控制台界面的应用程序(即您不必每次都使用不同的命令从控制台 运行 程序),并且我想要一个解析器对象来解析来自用户的 commands/options。结构类似这样-
ArrayList<String> example = new ArrayList<>();
/* PARSING */
ConsoleParser parser = new ConsoleParser();
Scanner input = new Scanner(System.in);
String parserArgs = input.nextLine();
while (parserArgs != "quit")
{
execute(parser.parse(parserArgs));
parserArgs = input.nextLine();
}
所以我的想法是有一个控制台(在应用程序中),我可以在其中键入 'add x' 或 'contains x' 之类的命令,然后将其分配给 'parserArgs.' 然后命令string 将被传递到 ConsoleParser,在那里它将被分解并搜索有效命令。如果命令有效(并且有必要 options/arguments),ConsoleParser 的 parse() 方法将以某种方式 return 方法(或方法名称)到 main,以及该方法需要的任何参数。因此,如果我想将字符串 "foo" 添加到我的 ArrayList,那么我可以在控制台键入 'add foo' 并将其传递给解析器,然后解析器将 return 用于某种类型的主需要使用参数 'foo.' 在 'example' 上调用 ArrayList 的 add() 方法的说明我知道这可以使用 arraylist 轻松完成,但为了简单起见,我只是在这里使用它。
从你的问题来看,我不确定你想要一个简单的解决方案还是一个优雅的解决方案。 这是一个优雅的解决方案的草图。
您定义了一个功能接口,即只有一个方法的接口,该方法由您的解析器返回。
赞:
// I the Input type
// R the result type
public interface Fn<I,R> {
R apply (I input);
}
第二个输入仅提供执行方法
public interface Cmd<R> {
R execute ();
}
您定义控制台命令
public class CliCommand<A> {
// constructor
public CliCommand(final String name, final Fn<String, A> parseFunct)
{
// TODO
}
}
// the parse function
public A parse(String arg) throws CliParseException {
// TODO
}
}
添加命令
public class Add implements Cmd<Integer> {
public Add(Integer i) {
}
}
以及添加
的解析函数 public class ParseAdd implements Fn<String, Cmd<Integer>> {
public Cmd<Integer> apply(String option) {
// parse the input and return the command with the arguments in there
// if (option == "add" and args exist )
// try parse args
// i = Integer.parse(substring);
return new Add(i);
}
}
然后是 ConsoleParser
public class ConsoleParser<A> {
public static <A> ConsoleParser<A> cli(CliCommand <A> command) {
...
}
public ConsoleParser <A> or (CliCommand <A> command) {
...
}
public A parse(String arg) throws CliParseException {
//
}
}
之后你的程序可以这样写
ConsoleParser<Cmd<Object>> parser = cli("add",new ParseAdd())
.or(...)
.or("quit", new ParseQuit();
Scanner input = new Scanner(System.in);
String parserArgs = input.nextLine();
while (true)
{
try {
parser.parse(parserArgs).execute();
} catch (CliParseException e) {
// handle it somehow
}
parserArgs = input.nextLine();
}
在这个例子中,Add 太简单了,我想你实际上想要将 String 添加到一个列表或两个 Numbers 中,所以实际的 ParseAdd 方法需要一些上下文(比如一个已经存在的列表),就像我的简单示例中一样。