🙌

【No.2】ミニ字句解析器をつくる

2023/02/07に公開

字句解析器の仕様

字句解析器と言っても、ここで作成するものは極めて簡単なものです。

以下の2つの機能を持ちます。

  1. ソースコードを1つの文字列として読み込み、
    その文字列を「トークン」と呼ばれる最小単位に分割する。
    作成した「トークン」の集合は、コレクションとして保持する。
  2. 外部からの要求に応じて「トークン」を提供する。

字句解析器の実装

上記の使用をプログラムで表現すると、以下のようになるでしょう。

  1. コンストラクタの引数として文字列(ソースコード)を受け取り、
    これを「トークン」に分割する。
    「トークン」の集合は、配列として保持。

  2. getTokenメソッドは、トークンを提供する。
    indexフィールドは、次に提供するトークンの場所を保持。

この観点から作成した単体テストです。

LexerTest
package lexer;

import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;

class LexerTest {

   @Test
   void testLex() {
   	String sourceCode = "go right left";
   	
   	Lexer lexer = new Lexer(sourceCode);
   	assertEquals(lexer.getToken(), "go");	
   	
   	lexer.nextToken();
   	assertEquals(lexer.getToken(),"right");
   	
   }
}

以下が実装です。

Lexer
package lexer;

public class Lexer {
	
	private String[] tokens;
	private int index;
	
	public Lexer(String code){
		tokens = code.split("\\s+");
	}
	
	public String getToken() {
		return tokens[index];
	}
	
	public void nextToken() {
		index ++ ;
	}
}

課題

現時点のプログラムには、以下のような課題があります。

  • プログラムの終端をindexが超過した場合に、良い感じの例外が投げられない。

  • 字句解析の機能とトークン提供の機能が、同一のクラスに存在している。
    別のクラスに分離すべき。(単一責任の原則)

Discussion