Upload
geraldine-cole
View
44
Download
0
Embed Size (px)
DESCRIPTION
コンパイラ 2012 年 10 月 18 日. 酒居敬一@A468 ( [email protected] ) http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/COMP/2012/index.html. 構文解析. 字句の列を入力とする。 字句の列は字句解析器から出力される。 字句の列として表されたプログラムが、文法のどの部分 に対応するかを解析する。 今回の内容 構文解析の概論 下向き構文解析法の説明 下向き構文解析法の問題点と解決法. 構文解析の役割. - PowerPoint PPT Presentation
Citation preview
コンパイラ2012 年 10 月 18 日
酒居敬一@A468 ([email protected])http://www.info.kochi-tech.ac.jp/k1sakai/Lecture/COMP/2012/index.html
1
構文解析 字句の列を入力とする。
字句の列は字句解析器から出力される。 字句の列として表されたプログラムが、文法のどの
部分に対応するかを解析する。
今回の内容 構文解析の概論 下向き構文解析法の説明 下向き構文解析法の問題点と解決法
2
構文解析の役割 プログラミング言語の文法はBNFなどで記述される
。 それに基づいてソースプログラムの字句が解析される
。 字句の列から文法で許される並びであるかどうか調べ
る。 許されなれない並びであればエラーとする。 許される並びであれば、解析木を生成し構文木を出力する
。 さらに変数や関数の名前は名前表に出力する。
3
ソースプログラム 構文解析字句解析
字句出力
字句要求構文木
名前表
構文規則(生成規則) この例では、乗算は加算よりも
先に行うことを示している。 演算順序を文法で規定している。
非終端記号 式・項・因子・名前
終端記号 a・b・c
→ 左辺の非終端記号を右辺に
書き換え可能であることを示す。
4
【式の構文規則】1.式 → 項|式+項2.項 → 因子|項*因子3.因子 → 名前|(式)
【文法G1】1.式 → 式+項2.式 → 項3.項 → 項*因子4.項 → 因子5.因子 → (式)6.因子 → 名前7.名前 → a|b|c
構文図式 BNFと記述力は変わらない。 直感的でわかりやすい。
5
要素型 識別子
[ プログラム ]
[ 関数定義 ]
[ 変数宣言 ]
[ ブロック ]
関数定義
変数宣言;
返戻型 ブロック識別子 ( ),
変数宣言
文{ }
6
[ 文 ]
[ 式 ]
[ 項 ]
式
return
条件式
ブロック
文
識別子
変数宣言
;(
=
ifwhile
)関数呼出し
;
条件式 文( )
式 ;
[ 関数呼出し ]
因数
因数 乗除演算子
識別子 式( ),
項
項 加減演算子
7
[ 条件式 ]
[ 乗除演算子 ][ 加減演算子 ]
[ 返戻型 ]
[ 識別子 ]
int[ 要素型 ][ 整数 ]数字
数字
英字
英字
式== != > <>= <=
式
+-
*
/
要素型
void
[ 数字 ] と [ 英字 ] は非終端記号なので、本来はそれらも終端記号に至るまでの定義が必要。しかし、省略されている。前回のBNFの例でも省略されている。
式a* ( b+c ) の解析木と構文木
8
項
因子
式
名前
a b c( )
式
因子
因子
因子 名前
名前
項
項
項
式
* +
a
*
b
+
c
解析木構文木
文法解析ではこれらの木を生成する。
解析木では葉に終端記号で末端以外が非終端記号
構文解析法 一般にはふた通りに分類可能。
上向き構文解析。 解析木を下から生成していく。 右辺と一致する入力列を左辺に置き換える。
下向き構文解析。 解析木を上から生成していく。 生成可能な解析木を仮定し、一致するかどうかで解析をすすめ
る。
9
【文法G1】1.式 → 式+項2.式 → 項3.項 → 項*因子4.項 → 因子5.因子 → (式)6.因子 → 名前7.名前 → a|b|c
上向き構文解析法
10
項
因子
式
名前
a b c
項
因子因子
名前名前
式
因子項
+ *
記号列: a+b*c
7を適用: 名前+名前*名前
6を適用: 因子+因子*因子
3,4を適用:
因子+項*因子 ⇒ 項+項*因子 ⇒ 項+項
1,2を適用:
式+項 ⇒ 式
解析木の下のほう、終端記号の非終端記号の置き換えから始まる解析法。
右辺が一致し左辺に置き換えることを還元という。
下向き構文解析法 解析木を根のほうから生成する。
木の形を仮定して葉に至るかどうかを調べる。 葉に至るまで木が完成しなければ、読み込んだ字句は戻
して別の形を探っていく。別の形が尽きたらエラーになる。 仮定⇔後戻り、を繰り返す。
11
void A(){a を読む ;B(); /* B を読む */c を読む ;
} 直接導出の例
void S(){a を読む ;A(); /* A を読む */b を読む ;d を読む ;
}void A(){
c を読む ;b を読む ;
または/* 解析が失敗して後戻りが発生したら */c を読む ;
}
c|cbAaAbdS
acbdの解析手順例
最も左にある非終端記号から解析を始めている。 最左導出という。
文法の展開に失敗したら後戻りがある。
12
解析手順 入力記号 文法の適用 解析結果
a c b d S → a A b d1 a c b d a A b d ○
2 c b d A → c b | c3 c b d c b ○
4 d a A b d ×5 c b d A → c b | c6 c b d c ○
7 b d a A b d ○
下向き構文解析の問題点 再帰的なプログラムで実現できない文法がある。
左再帰性の問題という。 再帰呼び出しが無限ループする。
左辺の非終端記号に対し、右辺に複数の生成規則があるときに、どれを仮定すべきか一意に決まらない。 バックトラック問題という。
前のページの3~6のところ。
13
void 式 (){式 ();+ を読む ;項 ();
}
問題のある文法。
これを次のように書き換える。
一般には次の形をとるときが問題で、
このように書き換える。
左再帰性の除去
14
|AA
|AAAA
nm ||||A||A|AA 2121
|A||A|AAA||A|AA
21
21
m
n
バックトラック法で解は求まるが、やはり速いほうがいい。
そこで、共通部分がある場合にくくりだす。
次のように書き換える。
バックトラック
15
c|cbA
|bAAcA
void A(){c を読む ;
b を読む ; または
/* 解析が失敗してバックトラックが発生したら */何も読まない ;
}
を に置き換えて解析。
16
解析手順 入力記号 文法の適用 解析結果
a c b d S → a A b d1 a c b d a A b d ○
2 c b d A → c A'3 c b d c A' ○
4 b d A' → b |ε5 b d b ○
6 d a A b d ×7 b d A' → b |ε8 b d a A b d ○
nm |||||||A 2121
m
n
|||A||||AA
21
21
c|cbAaAbdS
|bAAcAaAbdS
の形の場合、
という形に文法を変形する。バックトラックがなくなるわけではない。