04 REPLを作成し字句解析を行う [オリジナル言語インタプリタを作る]

04 REPLを作成し字句解析を行う [オリジナル言語インタプリタを作る]

REPLを作成し字句解析を行う

前回までで字句解析器の実装はひとまず完了となりました。ただ、ここまではエントリポイントとなる main() の実装を行っていません。

字句解析器を作成し、その動作をテストコードで確認しただけでした。なのでデフォルトのメイン関数の実装が残ったままで、おそらく実行すると “Hello World” が出力されるだけです。

今回は REPL を作成して字句解析を main() から呼び出せるようにします。

REPL とは

REPL とは、Read-Eval-Print Loop の略称です。入力を読み取り(Read)、評価(Eval)し、出力(Print)し、これらを繰り返す(loop)、という処理を行う機能を指します。

主にインタプリタ言語において、対話的にプログラムを実行するためのものです。例えばブラウザの開発者ツールにはREPLが搭載されており、そこから対話的にJavascriptのプログラムを実行することが可能です。

インタプリタの実装を進めていますが、対話的にプログラムを実行できるようにREPLを作成していきます。

REPL を実装する

ここでは REPL を作成しますが、ここまでで実装したのは字句解析器のみです。今後プログラムの実行ができるようになれば、処理の実行までを行う REPL を実装しなおしますが、ここでは、字句解析器を使って入力を評価し、得られたトークン列を出力として返す REPL を実装してみます。

Repl.cs

さっそく REPL を実装していきます。処理の流れは以下の通りです。

  1. 入力待ち
  2. 入力文字列字句解析する
  3. 得られたトークン列を表示
  4. 1に戻る

処理を終了するには Ctrl + C を使います。

Repl.cs

using Gorilla.Lexing;
using System;

namespace Gorilla
{
    public class Repl
    {
        const string PROMPT = ">> ";

        public void Start()
        {
            while (true)
            {
                Console.Write(PROMPT);

                var input = Console.ReadLine();
                if (string.IsNullOrEmpty(input)) return;

                var lexer = new Lexer(input);
                for (var token = lexer.NextToken(); token.Type != TokenType.EOF; token = lexer.NextToken())
                {
                    Console.WriteLine($"{{ Type: {token.Type.ToString()}, Literal: {token.Literal} }}");
                }
            }
        }
    }
}

Replクラスはの Start() は、入力を待機し、入力された文字列を字句解析してその結果得られたトークン列を表示しています。

表示後再び入力を待機するように無限ループでくるんでいます。

処理自体は大したものではありません。これを main() から呼び出すようにします。

Program.cs

using System;

namespace Gorilla
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello Gorilla Script!");

            var repl = new Repl();
            repl.Start();
        }
    }
}

動かしてみる

ようやくプログラムを動かせるようになりました。実行して確認してみましょう。

Hello Gorilla Script!
>> let a = 10;
{ Type: LET, Literal: let }
{ Type: IDENT, Literal: a }
{ Type: ASSIGN, Literal: = }
{ Type: INT, Literal: 10 }
{ Type: SEMICOLON, Literal: ; }
>>

上のような感じで動けばOKです。自分でコードを入力して字句解析器の動きを確認できるようになりました。

ただし複数行の入力が現時点ではできないので使い勝手はいまいちです。ただいい感じに動いています。達成感もありますね。

今回はここまでとし、次は構文解析に移ります。

ここまでのソース

mntm0/Gorilla at 663cfaecf9f7d33916f04d1e452faade14735175

開発いろいろカテゴリの最新記事