2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

REPL(Read-eval-print loop)を作る。

Posted at

REPL(Read-eval-print loop)を作る。

Kotlinソースのコードリーディングで、JLineというコンソール入出力ハンドリングライブラリを知りました。

JLine:http://jline.sourceforge.net/
Kotlin GitHub:https://github.com/JetBrains/kotlin

KotlinのREPLに使用されています。
JLineでやっていることをコーディングした記憶があり、ちょっとショック。
やはり、知らないという事は悪なのです。
今回はKotlinは使っていません。Javaで作りました。

とはいえ、REPLの構文解析/構文実行等は作っていません。言語仕様も決めていませんので。
起動、コマンド(Kotlin REPLの:〜)、構文入力受け付け的な所まで。
KotlinのREPLを真似してみました。

Kotlin REPL起動
replkt1.png

Kotlin REPLコマンド実行
replkt2.png

package replbase;

import java.io.IOException;
import java.io.PrintWriter;
import jline.ConsoleReader;

public class REPLBase {

    private final String COMMAND = ":";
    private final String PROMPT_READLINE = ">>> ";
    private final String PROMPT_INCOMPLETE = "... ";
    private ConsoleReader consoleReader;

    enum STATUS {
        READLINE,
        INCOMPLETE,
        QUIT
    }
    private STATUS status = STATUS.READLINE;

    public static void main(String[] args) {
        REPLBase replBase = new REPLBase();
        replBase.start();
    }

    private void start() {
        try(PrintWriter printwriter = new PrintWriter(System.out);) {
            consoleReader = new ConsoleReader(System.in, printwriter);
            consoleReader.printString("Welcome to REPLBase.(JRE " + System.getProperty("java.runtime.version") + ")\n");
            consoleReader.printString("Type :help for help, :quit for quit\n");
            while(status != STATUS.QUIT) {
                String input = readLine();
                analyze(input);
            }
        }
        catch(IOException exception) {
            System.err.printf(exception.toString());
        }
    }

    private String readLine() throws IOException{
        String prompt = status == STATUS.READLINE ? PROMPT_READLINE : PROMPT_INCOMPLETE;
        String input = consoleReader.readLine(prompt);
        return input;
    }

    private void analyze(String input) throws IOException {
        if((status != STATUS.INCOMPLETE) &&
           (input.startsWith(COMMAND) == true)) {
            command(input);
        }
        else {
            compile(input);
        }
    }

    private void compile(String input) {
        if(input.endsWith("}") != true) {
            status = STATUS.INCOMPLETE;
        }
        else {
            status = STATUS.READLINE;
        }
    }

    private void command(String input) throws IOException {
        String command = input.replaceFirst(COMMAND, "");
        switch(command) {
            case "help":
                consoleReader.printString("Available commands:\n" +
                                             ":help    show this help\n" +
                                             ":quit    exit the interpreter\n");
                break;
            case "quit":
                status = STATUS.QUIT;
                break;
            default:
                consoleReader.printString("Unknown command\n" +
                                              "Type :help for help\n");
                break;
        }
    }

}

これをベースに拡張出来ます。
REPLBaseをベースクラスにすれば色々使えます。

start()メソッド内のConsoleReaderがJLineです。
readline()メソッドでプロンプト表示/入力待ち/入力ライン受け取りです。
受け取った結果をanalyze()内でコマンド処理(command())と構文解析以降処理(compile())に振り分けています。
command()メソッドを拡張すれば、コマンドを追加/変更出来ます。
compile()メソッドを拡張すれば、REPLの本体を実装出来ます。
analyze()/command()/compile()を派生側で実装出来るようにすることで拡張可能になります。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?