言語理論とコンパイラ
第七回:
上向き構文解析と下向き構文解析
2007 年 6月 1日
http://www.sw.it.aoyama.ac.jp/2007/Compiler/lecture7.html
© 2005-7 Martin
J. Dürst 青山学院大学
目次
- 宿題について
- 解析木と構文木
- 曖昧な文法
- 上向き構文解析
- 下向き構文解析
- 再帰的下向き構文解析
先週の宿題
(提出不要)
- C
プログラム言語など知っている言語やデータ形式の文法を調べなさい。
C プログラム言語の文法の例
(yacc 形式; typedef
に要注意)
Java プログラム言語の文法
(BNF 形式)
先週のまとめ
- 正規表現やそれと同等の表現力を持つツールには限界がある
(例: 括弧の入れ子構造など)
- 正規表現などは構文解析には使えないが、字句解析には使える
- コンパイラで字句解析と構文解析に分けると分かりやすい構造と速い実装になる
- (プログラム)
言語などの文法は文脈自由文法で記述可能
- 文脈自由文法はプッシュダウンオートマトンで受理可能
構文解析の結果: 解析木と構文木
- 解析木:
- 葉は終端記号と (分析の途中の場合) 被終端記号
- 節は非終端記号
- 文法や解析方法の研究に使われる
- 構文木:
- 葉は終端記号の一部 (識別子、定数など)
- 節は被終端記号の一部に相当するが、終端記号の一部
(演算子、予約語) などをラベルに使う
- 一部の終端記号は無視 (括弧類など)
解析木と構文木の例
文法:
E → E '+' E
(Expression, 式)
E → E '*' E
E → '(' E ')'
E → integer
入力の例:
5 + 3 * (7 + 2)
曖昧な文法
- 例:
5 + 3 * 7
は (5+3) * 7
か 5 +
(3*7)
か
- 文法が両方の解釈を許す
- ある入力に対して複数の解析木を許す文法は曖昧な文法
(ambiguous grammar) と言う
- 一部の文法の場合、変換によって曖昧性が取り除かれる
- 変換のアルゴリズムや変換が可能かどうかを決めるアルゴリズムは存在しない
- 曖昧な文法は言語の構文だけの定義には使えるが、プログラム言語やデータ形式には向いてない
- 文法の曖昧性とプッシュダウンオートマトンの非決定性は同じものではない
(例: 左右対称の文字列)
文法の曖昧性の除去
問題の例:
E → E '-' E | integer
入力 4 - 5 - 7
に対して複数の解析木が作れる
解析木によって計算結果が違う
解決方法: 文法の書き換え
E → E '-' integer | integer
解析の実装: 下向き解析と上向き解析
- 下向き構文解析 (top-down parsing):
- 解析木を上から (初期記号から) 作る
- 上向き構文解析 (bottom-up parsing):
- 解析木を下から (終端記号から) 作る
- 途中に複数の (小さな) 解析木がある
構文解析の単純な実装: Dynamic Programming
(bottom-up)
- トークンの部分列を構文規則と比較、可能なところを書き換える
- 繰り返しトークンと被終端記号のあらゆる部分列を構文規則と比較、可能なところを書き換える
- 全体のトークン列を初期記号に書き換えたら終了
- 長所: あらゆる文法に適用可能
- 短所: 膨大な時間が必要 (入力の長さの3乗)
下向き解析の一般概要
- 文法を初期記号から展開する
- 選択肢があれば順番に試してみる
- 終端記号まで展開したらこれを入力と比べる
- 合ったら続く
- 合わなかったら戻って
(バックトラック、backtracking)、違う選択を試す
バックトラックは時間がかかる上、避けた方がいいとされてきた
次のトークンしか見なくてよい文法に限定したい
再帰的下向き構文解析
- 下向き構文解析は非終端記号ごとに関数一つを作成
- 文法に再帰的な要素がある
例 (代入式/assignment operation): A → variable '=' A |
integer
文法規則と BNF
文法規則には色々な書き方がある:
- 一番単純な書き方: 矢印だけ
- 左側に同じ被終端記号を持つものを複数組み合わせて
| で選択を表す
⇒ 根本的に 1. と変わらない (syntactic sugar/糖衣構文)
- 正規表現の ? の様なもの (あり/無し) の追加 (よく
[...] で書く)
⇒ 二つの構文規則に分けることが可能
- 正規表現の * の様なもの (よく {...} で書く)
⇒ 書き換えが可能
上記の拡張を含む文法規則の書き方は BNF (Backus-Naur
Form), EBNF (Extended...), ABNF (Augmented...) などという
EBNF の書き換え
D → a E* b
⇒
D → a F b
F → F E | ε
下向き構文解析の実装: 簡単な手作りコンパイラ
プログラム: scanner.h, scanner.c, parser.c
下向き構文解析の問題点
来週への準備
宿題
(提出不要)
次の文法の曖昧性を除去し、曖昧性のない文法を作りなさい。曖昧性がないことを複数の例で確認してください。
E → E '+' E
(Expression, 式)
E → E '*' E
E → '(' E ')'
E → integer
ヒント: 非終端記号の追加が必要