Java-如何实现应用程序控制台解析器

Java-如何实现应用程序控制台解析器,java,command-line,console-application,command-line-interface,command-line-arguments,Java,Command Line,Console Application,Command Line Interface,Command Line Arguments,因此,我正在尝试编写一个具有程序内控制台接口的应用程序(即,您不必每次都使用不同的命令从控制台运行程序),我希望有一个解析器对象来解析来自用户的命令/选项。结构与此类似- ArrayList<String> example = new ArrayList<>(); /* PARSING */ ConsoleParser parser = new ConsoleParser(); Scanner input = new Scanner(System.in); Stri

因此,我正在尝试编写一个具有程序内控制台接口的应用程序(即,您不必每次都使用不同的命令从控制台运行程序),我希望有一个解析器对象来解析来自用户的命令/选项。结构与此类似-

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();
}
ArrayList示例=新建ArrayList();
/*解析*/
ConsoleParser=新的ConsoleParser();
扫描仪输入=新扫描仪(System.in);
字符串parserArgs=input.nextLine();
while(parserArgs!=“退出”)
{
执行(parser.parse(parserArgs));
parserArgs=input.nextLine();
}

因此,我们的想法是(在应用程序中)有一个控制台,在那里我可以键入诸如“add x”或“contains x”之类的命令,然后将这些命令分配给“parserArgs”。然后将命令字符串传递给ConsoleParser,在那里对其进行解析并搜索有效的命令。如果该命令有效(并且具有必要的选项/参数),ConsoleParser的parse()方法将以某种方式将该方法(或方法名称)连同该方法所需的任何参数一起返回main。因此,如果我想将字符串“foo”添加到我的ArrayList中,那么在控制台上我可以键入“add foo”并将其传递给解析器,然后解析器将返回main某种指令,需要在参数“foo”的“example”上调用ArrayList的add()方法,但我在这里只是为了简单起见。

从你的问题来看,我不确定你想要的是简单的解决方案还是优雅的解决方案。 下面是一个优雅解决方案的草图

定义一个函数接口,即只有一个方法的接口,由解析器返回

比如:

//I输入类型
//R结果类型
公共接口Fn{
R应用(I输入);
}
第二个是只提供执行方法的输入

public interface Cmd<R> {

  R execute ();
}  
公共接口Cmd{
R执行();
}  
您可以定义控制台命令

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类命令{
//建造师
public CliCommand(最终字符串名,最终Fn parseFunct)
{
//待办事项
}
} 
//解析函数
公共解析(字符串arg)引发CliParseException{
//待办事项
}
}
添加命令

 public class Add implements Cmd<Integer> { 
    public Add(Integer i) {
    }

 }
public类Add实现Cmd{
公共加法(整数i){
}
}
和Add的解析函数

 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); 
     }
 }
public类ParseAdd实现Fn{
public Cmd apply(字符串选项){
//解析输入并返回包含参数的命令
//如果(选项==“添加”和参数存在)
//尝试解析参数
//i=整数.parse(子字符串);
返回新的Add(i);
}
}
然后是控制台管理员

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 {
     // 
  }

}
公共类控制台管理员{
公共静态控制台资源管理器cli(CliCommand命令){
...
}
公用控制台资源管理器或(CLICOMAND命令){
...
}
公共解析(字符串arg)引发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();   
}
ConsoleParser parser=cli(“添加”,新的ParseAdd())
.或(…)
。或(“退出”,new ParseQuit();
扫描仪输入=新扫描仪(System.in);
字符串parserArgs=input.nextLine();
while(true)
{
试一试{
parser.parse(parserArgs.execute();
}捕获(clie){
//怎么办
}
parserArgs=input.nextLine();
}

在本例中,Add太简单了,我认为您实际上想要将字符串添加到一个或两个数字中,因此实际的ParseAdd方法需要一些上下文(比如已经存在的列表)如我的简单示例所示。

因此接口允许我调用一个类中的方法,而该类不知道它们调用的方法是哪个类?@BenGranger我不会这样表述,但我认为人们可以这样看。
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();   
}