マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

LOOKAHEADを使ってみる

足し算だけじゃなくて他の演算も試したくなり、前回のプログラムを変更した。共通部分があるので、とりあえずLOOKAHEADを使ってChoice conflictを回避するようにした。LOOKAHEAD使わないとjavacc時にChoice conflictと表示されてしまう。そして、それを無視して先に進むと足し算以外の選択肢が選ばれなくなってしまう。なのでLOOKAHEADを使った。今回は先頭からの共通するTokenがのひとつっぽいので、LOOKAHEAD(2)を指定した。これで四則演算が可能になった。


実行結果

$ java Compiler "500 / 25"
20
$ java Compiler "0xFF - 0xF0"
15
$ java Compiler "0x100 + 0x100"
512
$ java Compiler "0x100 * 2"
512
options{
    STATIC = false;
    UNICODE_INPUT = true;
}

PARSER_BEGIN(Compiler)
import java.io.Reader;
import java.io.StringReader;

public class Compiler{
    public static void main(String[] args){
        for(String arg : args){
            try{
                System.out.println(evaluate(arg));
            }catch(ParseException ex){
                System.err.println(ex.getMessage());
            }
        }
    }

    public static long evaluate(String src) throws ParseException{
        Reader reader = new StringReader(src);
        return new Compiler(reader).expr();
    }

    private static long toLong(String str){
        long value = 0;

        if(str.startsWith("0x")){
            value = Long.parseLong(str.substring(2), 16);
        }else{
            value = Long.parseLong(str);
        }

        return value;
    }
}
PARSER_END(Compiler)

SKIP: {<[" ", "\t", "\r", "\n"]>}

TOKEN: {
    <INTEGER: ("-")? (["0"-"9"])+
            | ("-")? "0x" (["0" - "9", "a" - "f", "A" - "F"])+>
}

long expr():
{
    Token x, y;
}
{
    LOOKAHEAD(2) x = <INTEGER> "+" y = <INTEGER> <EOF>
        {
            return Compiler.toLong(x.image) + Compiler.toLong(y.image);
        }

    | LOOKAHEAD(2) x = <INTEGER> "-" y = <INTEGER> <EOF>
        {
            return Compiler.toLong(x.image) - Compiler.toLong(y.image);
        }

    | LOOKAHEAD(2) x = <INTEGER> "*" y = <INTEGER> <EOF>
        {
            return Compiler.toLong(x.image) * Compiler.toLong(y.image);
        }
    | x = <INTEGER> "/" y = <INTEGER> <EOF>
        {
            return Compiler.toLong(x.image) / Compiler.toLong(y.image);
        }
}