0

Java で一種のコマンドラインをプログラムするタスクがあります。

コンパイラの一部をテストするためのものです。「read_source」、「parse」、「build_ast」、「ast2cfg」、「print_cfg」などのコマンドを入力できるプロンプトが表示されます。

インタープリター (または repl ?) の構築を支援する Java のライブラリーはありますか? 私は自分がやりたいことをするpythonモジュールを知っていますcmd

私は自分で似たようなことを書きました:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;

interface Command {
    public abstract void action(String[] parameters);
}

public class Repl {
    private String prompt = "\n$ ";

    private HashMap<String, Command> commands;

    private Command nullCommand = null;

    private Command defaultCommand = null;

    public Repl() {
        commands = new HashMap<String, Command>();
    }

    public void setPrompt(String prompt) {
        this.prompt = prompt;
    }

    public void setDefaultCommand(Command defaultCommand) {
        this.defaultCommand = defaultCommand;
    }

    public void setNullCommand(Command nullCommand) {
        this.nullCommand = nullCommand;
    }

    public void addCommand(String name, Command command) {
        commands.put(name, command);
    }

    public void runRepl() {

        if (nullCommand == null) {
            System.err.println("There is no 'nullCommand' specified");
            return;
        }
        if (defaultCommand == null) {
            System.err.println("There is no 'defaultCommand' specified");
            return;
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    System.in));

            String commandName;
            String[] parameters;

            while (true) {
                System.out.print(prompt);

                commandName = reader.readLine();

                if (commandName == null) {
                    nullCommand.action(null);
                } else {
                    parameters = commandName.trim().split("\\s+");

                    Command com = commands.get(parameters[0]);
                    if (com != null) {
                        com.action(parameters);
                    } else {
                        defaultCommand.action(parameters);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Internal error within compiler: stopping compilation");
            System.exit(1);
        }
    }

    /**
     * Exapmpe:
     */
    public static void main(String[] args) {
        Repl repl = new Repl();

        repl.addCommand("printparams", new Command() {
            @Override
            public void action(String[] parameters) {
                System.out.println(Arrays.toString(parameters));
            }
        });

        repl.addCommand("add", new Command() {
            @Override
            public void action(String[] parameters) {
                if (parameters.length == 3) { // {"add", "2", "3"}
                    try {
                        int x = Integer.parseInt(parameters[1]);
                        int y = Integer.parseInt(parameters[2]);
                        System.out.println("Ergebnis: " + (x + y));
                    } catch (NumberFormatException e) {
                        System.out.println("Arguments have to be integers");
                    }
                } else {
                    System.out.println("There have to be two arguments");
                }
            }
        });

        Command helpcommand = new Command() {
            @Override
            public void action(String[] parameters) {
                System.out.println("There is: 'help', 'printparams [PARAMS...]', 'exit' and 'add INTEGER INTEGER'");
            }
        };
        repl.addCommand("help", helpcommand);
        repl.setDefaultCommand(helpcommand);

        Command exitcommand = new Command() {
            @Override
            public void action(String[] parameters) {
                System.out.println("Bye!");
                System.exit(0);
            }
        };
        repl.addCommand("exit", exitcommand);
        repl.setNullCommand(exitcommand);

        repl.runRepl();
    }
}

それは機能しますが、たとえば、「usage: add INTEGER INTEGER [INTEGER...]」などの使用パターンが、パラメーターが解析される方法に従って生成され、さらに 2 つの数値が追加されると便利です。新しいコマンドを追加し、それらが常に一貫していることを保証するのは簡単です。

また、それが過度に設計されているかどうかを自問しています。このようなループを書くことをお勧めしますか?:

while(true) {
    String command = getUserInput();
    if (command.equals("dothis")) {
        dothis1();
        someMember = dothis2();
    } else if (command.equals("dothat"))
        dothat();
    } else {
        printHelp();
    }
}
4

2 に答える 2

0

最初の答え複雑すぎるようです。私はあなたのように多くの登録コードを使用しますが、通常、これはあるクラスが別のクラスに登録しているときです。クラスが自分自身を登録するという考えは、多数if {} else if {}のコマンドがあり、チェーンに長い時間がかかることを心配している場合にのみ、パフォーマンス上の理由から使用します。

ここでは単純な解決策(セクシーではありませんが)が最適だと思います。

while(true) {
    String command = getUserInput();
    if (command.equals("dothis")) {
        dothis1();
    } else if (command.equals("dothat"))
        dothat();
    }
    ...
}

ここでは、パフォーマンスへの影響を考慮して、常に KISS メソッドを選択します複雑なコードは、あなたのコードを維持しようとする他の誰かをつまずかせるだけでなく、3 か月後に戻ってきたときに頭を悩ませることにもなります。:-)

于 2012-05-22T23:38:02.100 に答える
0

if else ラダーの代わりに switch case を使用して、より洗練されたコードを作成し、タイプミスを回避します。

例えば:

while(true){

  Scanner scan = new Scanner(System.in);
  String s = scan.nextLine()

    switch(s){

         case "Dothis" :
                           break;

         case "Dothat" :
                           break;




    }
于 2012-05-22T17:30:06.767 に答える