LoginSignup
5
5

More than 5 years have passed since last update.

Lexerを実装しよう(1)

Last updated at Posted at 2018-12-23

前置き

バージョン 環境
jdk-10 IntelliJ IDEA

たぶん上の環境で動きます。

前の記事:EAMを実装しよう
 EAMの結果帰ってくるchar[]を字句解析するLexerを作ります。
 昨日はかなりコードに欠陥があったのでかなり実力不足を感じ反省しました。迷惑かけた皆様申し訳ございませんでした。問題があったら遠慮なくいってください。

Lexerとは

 Lexerとは、字句解析器(Lexical Analyzer)のことです。Parserとも呼ばれることがあるようですが、ParserをParser Combinatorと言ったりややこしくなるので、こちらを用います。さっそく実装を見てみましょう。

実装

Lexer.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Lexer {
    static String s = "";
    static List<String> l= new ArrayList<>();

    //private static List<Character> brackets = Arrays.asList('(',')','{','}','[',']');
    private static List<Character> operators = Arrays.asList('=','+','-','*','/');

    public static Type getType(final Character c){
        if(Character.isLetter(c)) return Type.alphabet;
        else if(Character.isDigit(c)) return Type.digit;
        else if(Character.isWhitespace(c)) return Type.space;
        else if(operators.contains(c)) return Type.operator;
        //else if(brackets.contains(c)) return Type.brackets;
        return Type.other;
    }
    public static void analyze(char c){
        switch (getType(c)) {
            case other:
                System.out.println("This character cannot be accepted");
                break;
            case space:
                if(s != ""){
                    l.add(s);
                    s = "";
                }
                break;
            //case bracket:
            case operator:
                if(s != ""){
                    l.add(s);
                    l.add(""+c);
                    s = "";
                    break;
                }
            case alphabet:
            case digit:
                s += c;
            default: break;
        }
    }
    public static void addString(){
        l.add(s);
    }
    public static List<String> getList(){
        return l;
    }
}
Type.java
public enum Type{
    alphabet,
    digit,
    space,
    operator,
    //bracket,
    other
}

実装の説明

 いや、自分でも汚いコードだと思います。これから修正していくつもりです。いい案がある人はぜひ教えてください。
 bracketという文字がコメントでちらほら見えますが「かっこ」のことです。めんどくさいのでとりあえず後回しにしました。

public static Type getType(final Character c)
この部分で読んだ文字が何なのか調べます。
public static void addString()
ここでは、最後のトークンをリストに追加しています

実行

EAM.java
import java.util.*;
import java.io.*;

public class EAM{
    private final FileReader fr;

    private EAM(final String s) throws IOException{
        fr = new FileReader(s);
    }
    public static char[] use(final String s,final Use<EAM,char[],IOException> u) throws IOException{
        final EAM eam = new EAM(s);
        char[] c;
        try{
            c = u.apply(eam);
        }finally{
            eam.close();
        }
        return c;
    }
    private void close() throws IOException{
        System.out.println("close()");
        fr.close();
    }
    public char[] read() throws IOException {
        char[] c = new char[100];
        int length = fr.read(c);
        return Arrays.copyOfRange(c, 0, length);
    }
}
Use.java
@FunctionalInterface
public interface Use<T,R,X extends Throwable>{
    R apply(T t) throws X;
}
Main.java
import java.io.IOException;

public class Main{
    public static void main(String[] args) throws IOException{
        char[] array = EAM.use("lib\\test.txt", eam -> eam.read());
        System.out.println("\n--EAM");
        for(char c : array){
            System.out.print(c);
            Lexer.analyze(c);
        }
        FLexer.addString();
        System.out.println( "\n--Lexer\n" + Lexer.getList());
    }
}

前回のEAMを使って読んでいます。メソッドの内容がところどころ違います。char[]を返せるようにしようと思ってこうしました。

結果

close()

--EAM
a = 2 + 7 * 3
log a
--Lexer
[a, =, 2, +, 7, *, 3, log, a]

こんな感じになれば成功です。分からないことがあれば質問してください。

5
5
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
5
5