言語理論とコンパイラ
第九回:
上向き構文解析、yacc 系ツールの使い方
2011 年 6 月 10 日
http://www.sw.it.aoyama.ac.jp/2011/Compiler/lecture9.html
Martin J. Dürst
© 2005-11 Martin
J. Dürst 青山学院大学
今日の予定
前回の文法の発展
- 出発点 (parser1.c):
- E → T '+' T | T
T → number
- 三つ以上の被演算子への対応 (parser2.c):
- E → T '+' E | T
T → number
- 引き算の追加 (parser3.c):
- E → T '+' E | T '-' E | T
T → number
- 右結合から左結合への変更 (parser4.c):
- E → E '+' T | E '-' T | T
T → number
- 左再帰への対応 (parser5.c):
- E → T ME
ME → '+' T ME | '-' T ME | ε
T → number
上向き構文解析の単純な実装: Dynamic Programming
- トークンの部分列を構文規則と比較、可能なところを書き換える
- 繰り返しトークンと被終端記号のあらゆる部分列を構文規則と比較、可能なところを書き換える
- 全体のトークン列を初期記号に書き換えられたら終了
- 三つ以上のトークンの列を考量しないため、文法を書き換え規則の右側に二つ以下の記号になるように書き換える
- 長所: あらゆる文法に適用可能
- 短所: 膨大な時間が必要 (入力の長さの3乗)
bison とは
- yacc: yet another compiler compiler
- Unix の普及とともに広がった
- compiler compiler: コンパイラを作るコンパイラ
- yet another: もう一つ、できた当時に compiler compiler
が流行りで、他に名前が浮かんで来なかった
- bison: yacc の gnu 版
演習例: 簡単な電卓
スタートのためのファイル: makefile,
calc.y, calc.lex
flex と bison の使い方の概要
- bison でトークンの種類を記述:
%token NUM PLUS ASTERISK
...
- bison で属性値の型の定義
#define YYSTYPE int
- flex でそれぞれのトークン用のルールの定義
- bison で文法規則の定義
- bison で文法の属性の規則の定義
- コンパイルとテスト
(全項目と合わせて行った方がよい)
bison のマニュアル
make の活用
flex
, bison
, gcc
などを忘れず使うのが難しい
make
コマンドは makefile
の指定に従い、必要最小限の処理を実行
- 必要に応じて、make コマンドを cygwin で追加
- make ファイルの書き方 (→はタブの意味;
タブでないとだめ!):
target: input1 input2
input3 ...
→target 作成命令
- make だけ打つと makefile 内の最初の target が作られる
bison の仕組みとデバッグ
bison -v
で作った機械の明細のファイルを作成
(例: calc.output)
#define YYDEBUG 1
でデバッグを ON
bison の開発のコツ
- テストの入力ファイルを用意
- テストの正解ファイルを用意
- 自動的にプログラムを実行、
diff
コマンドで比較
diff
から出力がなかったらテスト成功
- テストファースト:
テストを追加して、失敗を確認してから実装
calc 用テストファイル: test.in, test.check
宿題
提出: 再来週の木曜日 (6 月 23日) 19 時 00 分、O 棟 529
号室の前
簡単な電卓を有理数の電卓に拡張してください。
有理数の表現方法として、[分子,分母] を追加
してください。
[]
内には割り算は許されないように文法を設計してください。
.lex
と .y
のファイルを印刷して提出。A4
両面印刷、表紙なし、左上ホチキス止め、名前と学生番号をコメントに記述。
優先度と結合規則は文法で定義 (%left
,
%right
など使わないこと)
来週質問が可能なので、よく準備して質問できるようにすること!
flex の演習の正解例
読みやすさのため、コメントを
/x x/
にし、スペースを使用第一案:
/x .* x/
問題:/xx/ /xx/
をまとめて認識第二案:
/x [^x]* x/
問題:/xxx/
を認識しない第三案:
/x ([^x]|x[^/])* x/
問題:/x xx/ /x x/
をまとめて認識第四案:
/x ([^x]|x+[^/])* x/
問題: 以前と同様第五案:
/x ([^x]|x+[^/x])* x/
問題:/x xx/
を認識しない第六案:
/x ([^x]|x+[^/x])* x+/
完成!参考: Mastering Regular Expressions, Jeffrey E.F. Friedl, pp. 168,...