コンパイラ演習資料(javacc) 担当:佐々木晃
□演習問題B0(締め切り=2009/06/15演習中の回収時)
問題番号: B0
課題名:コンパイラの作成準備
出題日:06/08
課題:JavaCCの設定と準備
本演習資料にしたがって、中置記法による算術式(四則演算、括弧が使える)を逆ポーランドによる式に変換するプログラム
をJavaCCを用いて作成せよ。
備考:コンパイラ作成演習のガイドラインに従って、アップロードしてください。
(参考、コンパイラ作成1)
http://cis.k.hosei.ac.jp/~asasaki/lect/compiler/2008A/problem/problem1.htm
0. javaccについて。
詳しくは、中田先生のページを参照
http://cis.k.hosei.ac.jp/~nakata/lectureCompiler/JavaCC/index.html
その他、http://cis.k.hosei.ac.jp/~asasaki/lect/compiler/のJavaCCの項目を参考にせよ。
1. javaccのインストール (Eclipse-pluginを利用)
説明は下記にある。
Eclipse JavaCC Plugin Home
http://eclipse-javacc.sourceforge.net/
下記からダウンロード
SourceForge.net: JavaCC Eclipse Plugin
http://sourceforge.net/projects/eclipse-javacc
←少し古いバージョン
インストール。アーカイブを展開(解凍)した中には、featuresとpluginsというフォルダが含まれる。
この中身を利用しているEclipseのルートフォルダにあるfeatures, pluginsのそれぞれに入れてやればよい。
展開したJavaCC
Eclipse-Pluginに含まれる、featuresと pluginsの中身を利用しているEclipseのフォルダにコピー ここにDrug and
Dropすればよい。
以上で終了
2. プロジェクトとJavaCCオプションの設定
ここではCompilerConstructionというプロジェクトを設定。通常と同じくJavaプロジェクトを指定。
JavaCCのオプションの設定。
自動セーブ機能をOFF(好みで)
Javaのバージョンを1.5 (必須)
3. コンパイラ(構文解析器)の作成の流れ
準備:テンプレート作成
(ただし、ここでは実際には作成されたテンプレートは全く使わない)
|
A:JJファイルを編集:
ここでは、テンプレートを完全に書き換えてプログラムを書く。
(本資料の「5:開発の流れ」のサンプルプログラム、あるいは配布プログラムのSample.jjの内容で説明する。)
B:コンパイラの自動生成: JavaCCでコンパイラ(構文解析器)を自動生成する。
C:生成されたコンパイラ(構文解析器)のコンパイル:
実際には、Sample.jjにはバグがあるので、自動生成の段階でエラーがでるので、直さないと先には進めない。(後述)
Sample.jjのバグを取り除いたあと、Sample.java(自動生成されたコンパイラ)をコンパイルする。下記のようなエラーになればコンパイルは一応成功している。(コンパイルするべきプログラムがmainの引数に与えられていないために出ているエラーである。)
Sample.jjから自動生成されたコンパイラ(構文解析器)のJavaファイル。うまく、自動生成できないときは、refreshする意味で、以前に生成されたものを削除すると良い。
D(1):ソースコードの作成
作成したコンパイラに読み込ませるソースコードを用意する。
ここではb0というフォルダを用意して、sample1.txtにソースコードを書く。
D(2) 作成したコンパイラを実際に動かす。
引数にコンパイルしたいファイル名を書く。(さきほどの1234 +2345をコンパイルする。)
コンソールに下記が表示されたら成功。
1234
2345 +
4. コンパイラ作成の流れ
A. jjファイルを編集、作成。(上の例ではSample.jj)
B. コンパイラの生成 (jjファイルに誤りがあると、先には進まないのでAにもどる。)
成功すると Sample.javaが作られる。
C. Sample.javaのコンパイルと実行
Sample.javaのコンパイルに成功すると、コンパイラが起動する。
ただし、Sample.jjのアクションの部分などに誤りがあった場合、Sample.javaをコンパイルすることはできないので、Aに戻る。
D. 実際にコンパイラの動きを試す。動きがおかしいときはAに戻る。
5. 開発の例:
○4A. サンプルプログラムSample.jj(わざと誤りが入れてある)の作成
options {
JDK_VERSION="1.5";
}
PARSER_BEGIN(Sample)
import java.io.*;
/*
Sample
Tokens:
<NUMBER> = {0|1|2|3|4|5|6|7|8|9}+
<PLUS> = "+"
Grammar:
E ::= E <PLUS> F | F
F ::= (E) | <NUMBER>
-> eliminating left recursion of the grammar
E ::= F E'
E' ::= <PLUS> E' F | epsilon
F ::= (E) | <NUMBER>
*/
public class Sample {
public static void main(String args[]) {
try {
Sample parser = new Sample( new FileReader(args[0] ));
parser.start();
}catch(Exception ex){
ex.printStackTrace();
System.err.println("Failed to parse:"+ex.getMessage());
}
}
}
PARSER_END(Sample)
SKIP:{
<SPACE: " "|"\t">
| <NL:"\n"|"\r"|"\r\n">
}
TOKEN:{
<NUMBER:(["0"-"9"])+>
<PLUS: "+">
}
void start(): {}
{
e()
}
void e():{}
{
f() e2()
}
void e2():{}
{
<PLUS> f() {System.out.pritn(" +");} e2() /* 誤り */
| {}
}
void f():{Token token;}
{
token=<NUMBER> {System.out.print(" "+ token.image);}
}
○4B. コンパイラの自動生成
→jjファイルの記述誤りがあるのでエラーがでる。
○4A→jjファイルを修正しVersion 2を作る。
「|」を加えると直る。上記43行目の <Plus>の前。
○4B:コンパイラの生成→成功
4C 生成されたコンパイラのコンパイルと実行
→ Sample.javaに赤×印がついているが、生成されたJavaファイルに誤りがある。printのつづりあやまり。もとのjjファイルを直す必要がある。
○4A→jjファイルを修正
○4B: コンパイラの自動生成→成功
→成功
○4C、4D 生成されたコンパイラのコンパイルと実行
「3.コンパイラ(構文解析器)の作成の流れ」のDの項に書いた方法で、ソースプログラムを用意した後、実際に作成したコンパイラを動かしてみる。
サンプルテキスト、sample1.txt
1234+2345
実行結果(コンソールに出力される)
1234 2345 +
6. 配布したサンプル
配布したサンプルに含まれるjavaccsamples以下のjjファイルおよびtxtファイルの説明
□字句解析のテスト→ScannerSample1.jj
このテストは、標準入力(System.in)から入力するので、実行する際には引数は必要なし。
実行するとコンソールで入力待ちになるので、テキストを入力する。(Enterを押さないと入力は処理されない。)
□算術式を逆ポーランドに翻訳するプログラム
l Sample.jj 上述のエラーのある例。修正したものがSample1.jj
l Sample1.jj 足し算その1
サンプルソースプログラムは、sample11.txt, sample12.txt
l Sample2.jj 足し算その2
サンプルソースプログラムは、sample11.txt, sample12.txt
l Sample3.jj 括弧を扱えるようにする。
サンプルソースプログラムは、sample11.txt, sample31.txt
l Sample4.jj 引き算を扱えるようにする。
サンプルソースプログラムは、sample11.txt, sample41.txt
l Sample5.jj 掛け算を扱えるようにする。
サンプルソースプログラムは、sample11.txt, sample51.txt