言語理論とコンパイラ
第九回:
上向き構文解析、yacc 系ツールの使い方
2012 年 6 月 15 日
http://www.sw.it.aoyama.ac.jp/2012/Compiler/lecture9.html
Martin J. Dürst
© 2005-12 Martin
J. Dürst 青山学院大学
今日の予定
前回のまとめ
- 下向き構文解析とバックトラック
- 再帰的下向き構文解析
- 概要: 日終端記号ごとの関数
- 左再起への対応
- 下向き構文解析の限界: 先読み
前回の文法の発展
- 出発点 (parser.c):
- E → T '+' T | T
T → number
- 三つ以上の被演算子への対応 (parserA.c):
- E → T '+' E | T
T → number
- 引き算の追加 (parserB.c):
- E → T '+' E | T '-' E | T
T → number
- 右結合から左結合への変更 (parserC.c):
- E → E '+' T | E '-' T | T
T → number
- 左再帰への対応 (parserD.c):
- E → T ME
ME → '+' T ME | '-' T ME | ε
T → number
更なる文法の発展
上向き構文解析の単純な実装: Dynamic Programming
(lecture7 の Cocke–Younger–Kasami
アルゴリズムを参照)
bison の概要
- yacc: yet another compiler compiler
- Unix とともに普及
- compiler compiler: コンパイラを作るコンパイラ
- yet another: もう一つ
(当時compiler compiler が流行、名前に困った)
- bison: yacc の gnu 版
演習例: 簡単な電卓
スタートのためのファイル: makefile,
calc.y, calc.lex
上向き構文解析の利点と問題点
- 左再起の心配がない
- 代わりに曖昧性に気を付けないといけない
曖昧な文法
- 文法の例:
E → E '-' E | integer
- 具体例:
5 - 3 - 7
は (5-3) - 7
か 5
- (3-7)
か
- 文法が両方の解釈を許す
- (形式) 言語の定義には問題ないが
- ある入力に対して複数の解析木を許す文法は曖昧な文法
(ambiguous grammar) と言う
- 一部の文法の場合、変換によって曖昧性が取り除かれる
- 変換のアルゴリズムや変換が可能かどうかを決めるアルゴリズムは存在しない
- 曖昧な文法は言語の構文だけの定義には使えるが、プログラム言語やデータ形式には向いてない
- 文法の曖昧性とプッシュダウンオートマトンの非決定性は同じものではない
(例: 左右対称の文字列)
文法の曖昧性の除去
問題の例:
E → E '-' E | integer
入力 4 - 5 - 7
に対して複数の解析木が作れる
解析木によって計算結果が違う
解決方法: 文法の書き換え (左結合の場合)
E → E '-' integer | integer
bison のマニュアル
bison の仕組みとデバッグ
bison -v
で作った機械の明細のファイルを作成
(例: calc.output)
#define YYDEBUG 1
でデバッグを ON
bison の開発のコツ
- テストの入力ファイルを用意
- テストの正解ファイルを用意
- 自動的にプログラムを実行、
diff
コマンドで比較
diff
から出力がなかったらテスト成功
- テストファースト:
テストを追加して、失敗を確認してから実装
calc 用テストファイル: test.in, test.check
属性文法
(attribute(d) grammar(s))
- 単純な構文解析は「受理」の有無のみ
- 終端記号、被終端記号に「属性」を付ける
- 文法規則ごとに、その属性の割り出しを追加情報で定義
- 属性を解析木の下から上へと計算するのが普通が、
両方向に計算する仕組みも存在
- 例:
E0 → E1 '-' E3
S(E0
) = S(E1
) -
S(E3
)
bison の場合: $$ = $1 - $3
- 典型的な属性:
木の高さ、入力の長さ、式の評価値、部分解析木・構文木、生成されたコード
flex と bison の使い方の概要
- bison でトークンの種類を記述:
%token NUM PLUS ASTERISK
...
- bison で属性値の型の定義
#define YYSTYPE int
- flex でそれぞれのトークン用のルールの定義
- bison で文法規則の定義
- bison で文法の属性の規則の定義
- コンパイルとテスト
(全項目と合わせて行った方がよい)
make の活用
flex
, bison
, gcc
などを忘れず使うのが難しい
make
コマンドは makefile
の指定に従い、必要最小限の処理を実行
- 必要に応じて、make コマンドを cygwin で追加
- make ファイルの書き方 (→はタブの意味;
タブでないとだめ!):
target: input1 input2
input3 ...
→target 作成命令
- make だけ打つと makefile 内の最初の target が作られる
宿題
提出: 来週の木曜日 (6 月 21日) 19 時 00 分、O 棟 529
号室の前
calc.y を、test.in
から test.checkになるように完成
calc.y
を A4
(両面印刷、表紙なし、左上ホチキス止め、名前と学生番号をコメントに記述)
で提出