【问题标题】:Java - how to implement application console parserJava - 如何实现应用程序控制台解析器
【发布时间】:2015-09-03 11:17:51
【问题描述】:

所以我正在尝试编写一个具有程序内控制台界面的应用程序(即您不必每次都使用不同的命令从控制台运行程序),并且我想要一个解析器对象解析来自用户的命令/选项。结构类似这样-

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();
}

所以我的想法是有一个控制台(在应用程序内),我可以在其中键入诸如“添加 x”或“包含 x”之类的命令,然后将其分配给“parserArgs”。然后命令字符串将被传递给 ConsoleParser,在那里它将被剖析并搜索有效命令。如果命令有效(并且具有必要的选项/参数),则 ConsoleParser 的 parse() 方法会以某种方式将方法(或方法名称)以及该方法所需的任何参数返回给 main。因此,如果我想将字符串“foo”添加到我的 ArrayList,那么我可以在控制台输入“add foo”并将其传递给解析器,然后解析器将返回到 main 某种指令,即 add() ArrayList 的方法需要在 'example' 上使用参数 'foo' 调用。我知道这可以通过 arraylist 轻松完成,但为了简单起见,我只是在这里使用它。

【问题讨论】:

    标签: java command-line console-application command-line-interface command-line-arguments


    【解决方案1】:

    根据您的问题,我不确定您想要一个简单的解决方案还是一个优雅的解决方案。 这是一个优雅的解决方案的草图。

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

    喜欢:

    // 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 添加到一个列表或两个数字中,所以实际的 ParseAdd 方法需要一些上下文(如一个已经存在的列表),就像我的简单示例一样。

    【讨论】:

    • 所以接口允许我调用一个类中的方法,而该类不知道它们正在调用的方法是哪个类?
    • @BenGranger 我不会这样表述,但我认为人们可以这样看。
    猜你喜欢
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 2023-03-28
    • 2012-01-01
    • 2015-10-06
    • 1970-01-01
    相关资源
    最近更新 更多