削除された内容 追加された内容
DumZiBoT (会話 | 投稿記録)
m ロボットによる 変更: ru:LL-анализатор
Yuichirou (会話 | 投稿記録)
m カッコと表組みのスタイルを修正
1行目:
'''LL法'''または'''LL構文解析器'''とは、[[文脈自由文法]]のサブセットのための[[トップダウン構文解析|トップダウン]][[構文解析器]]の一種である。入力文字列を左(Left) (Left) から構文解析していき、[[文脈自由文法#導出と構文木|左端導出]](Leftmost Derivation)(Leftmost Derivation) を行う(このため、LL法と呼ぶ。[[LR法]]も参照されたい)。この方式で構文解析可能な文法のクラスを ''LL文法'' と呼ぶ。
 
以下では、表を使った構文解析を解説する。他の手法として手でコードを書く[[再帰下降構文解析]]もある(ただし、再帰下降構文解析のコードを自動生成する [[ANTLR]] のようなツールもある)。
40行目:
この文法の構文解析表は次のようになる:
 
:{| border="1" align="center" cellspacing="3" padding="5" class="wikitable" alignstyle="text-align: center"
!
|----- align="center"
|! || '''(''' !! || ''')''' ||!! '''1''' !! + ||!! '''+'''$
| -
| '''$'''
! S
|----- align="center"
| '''S''' || 2 || - || 1 || - || -
| -
! F
|----- align="center"
| '''F'''- || - || - 3 || 3 - || -
| -
|}
 
91 ⟶ 90行目:
 
== LL(1)構文解析表の作成 ==
構文解析表を作成するためには、非終端記号 'A' がスタックのトップにあり、記号 'a' が入力バッファの先頭にある場合に適用すべき文法規則を決定しなければならない。''A'' → ''w'' という形式の規則が存在し、''w'' という文字列の先頭に 'a' がありうる場合は簡単である。このため、文字列 ''w'' の先頭になりうる終端記号の集合(First (First-set)set) を '''Fi'''(''w'') で表す。また、''w'' が空文字列の可能性もある場合は ε で表す。''A''<sub>1</sub> → ''w''<sub>1</sub>, ..., ''A''<sub>''n''</sub> → ''w''<sub>''n''</sub> という規則群から構成される文法があるとき、'''Fi'''(''w''<sub>''i''</sub>) と '''Fi'''(''A''<sub>''i''</sub>) を各規則について以下のように求める。
# 各 '''Fi'''(''w''<sub>''i''</sub>) と '''Fi'''(''A''<sub>''i''</sub>) を空集合で初期化する。
# 各規則 ''A''<sub>''i''</sub> → ''w''<sub>i</sub> について、''Fi''(''w''<sub>''i''</sub>) を '''Fi'''(''A''<sub>''i''</sub>) に追加する。ここで、''Fi'' は以下のように定義される:
101 ⟶ 100行目:
# ステップ2と3を全 '''Fi''' 集合が変化しなくなるまで繰り返す。
 
残念なことに、First-set だけでは構文解析表は完成しない。これは、規則の右側の ''w'' が空文字列で書き換えられる可能性があるためである。従って構文解析器はεが'''Fi'''(''w'')に含まれるとき、規則 ''A'' → ''w'' を使い ''A'' の後に続く可能性のある記号を考慮しなければならない。つまり ''A'' に続く記号の集合(Follow (Follow-set) も必要で、これを '''Fo'''(''A'') と表記する。これは、記号列が ''αAaβ'' となるような終端記号 ''a'' の集合であり、開始記号から規則を適用していくことで導出される。各非終端記号についての Follow-set は以下のように求められる:
 
# 各 '''Fo'''(''A''<sub>''i''</sub>) を空集合で初期化する。
# ''A''<sub>''j''</sub> → ''wA<sub>i</sub>w' '' という形式の規則がある場合、
#* 終端記号 ''a'' が ''Fi''(''w' '') に含まれるなら、''a'' を '''Fo'''(''A''<sub>''i''</sub>) に追加する。
#* ε が ''Fi''(''w' '') に含まれるなら、'''Fo'''(''A''<sub>''j''</sub>) を '''Fo'''(''A''<sub>''i''</sub>) に追加する。
# ステップ2を全ての '''Fo''' 集合が変化しなくなるまで繰り返す。