(Translated by https://www.hiragana.jp/)
LL法 - Wikipedia

LLほうまたはLL構文こうぶん解析かいせきとは、文脈ぶんみゃく自由じゆう文法ぶんぽうのサブセットのためのトップダウン構文こうぶん解析かいせきほう一種いっしゅである。入力にゅうりょく文字もじれつひだり (Left) から構文こうぶん解析かいせきしていき、左端ひだりはし導出どうしゅつ (Leftmost Derivation) をおこなう(このため、LLほうぶ。LRほう参照さんしょうされたい)。この方式ほうしき構文こうぶん解析かいせき可能かのう文法ぶんぽうのクラスを LL文法ぶんぽうぶ。

以下いかでは、おもて駆動くどうがた構文こうぶん解析かいせき解説かいせつする。手法しゅほうとして、個々ここ構文こうぶん規則きそく対応たいおうするサブルーチンしから再帰さいき下降かこう構文こうぶん解析かいせきもある。おもて駆動くどうがた計算けいさんによる生成せいせいき、再帰さいき下降かこう構文こうぶん解析かいせきはコードの手書てがきにいている(しかし、再帰さいき下降かこう構文こうぶん解析かいせきのコードを自動じどう生成せいせいする ANTLR のようなツールもある)。

k 字句じく(トークン)を先読さきよする場合ばあい、LL(k) と表記ひょうきする。ある文法ぶんぽうについて LL(k) 構文こうぶん解析かいせき存在そんざいし、バックトラッキングなしで構文こうぶん解析かいせきできる場合ばあい、その文法ぶんぽうを LL(k) 文法ぶんぽうであるという。LL(1) 文法ぶんぽう機能きのう限定げんていされるが、つぎのトークンだけを先読さきよみすればよいため、構文こうぶん解析かいせき生成せいせい容易よういであり、よく使つかわれている。一般いっぱん設計せっけい問題もんだいがある言語げんごおおきな k必要ひつようとなる傾向けいこうがあり(kおおきいということは、ひとがプログラムを場合ばあいにも、たくさんまないと意味いみ把握はあくできないということである)、構文こうぶん解析かいせき大変たいへんになる。

アーキテクチャ

編集へんしゅう

以下いかでは、構文こうぶん解析かいせきひょうもとづいたトップダウン構文こうぶん解析かいせきによる左端ひだりはし導出どうしゅつについて解説かいせつする。

一般いっぱんケース

編集へんしゅう

構文こうぶん解析かいせき特定とくてい形式けいしき文法ぶんぽうしたがった文字もじれつあつかう。

構文こうぶん解析かいせき以下いか要素ようそから構成こうせいされる。

  • 入力にゅうりょくバッファ: 入力にゅうりょくトークンれつ格納かくのうする。
  • スタック: 解析かいせき対象たいしょう文法ぶんぽう終端しゅうたん記号きごう非終端ひしゅうたん記号きごう格納かくのうする。
  • 構文こうぶん解析かいせきひょう: スタックのトップにある記号きごうつぎ入力にゅうりょくトークンにしたがって適用てきようすべき文法ぶんぽう規則きそくしめす。

構文こうぶん解析かいせきはスタックのトップにある記号きごう入力にゅうりょくバッファじょう現在げんざい記号きごうから適用てきようすべき規則きそく決定けっていする。

構文こうぶん解析かいせき動作どうさ開始かいししたとき、すで以下いかの2つの記号きごうがスタックにある。

[ S, $ ]

ここで、'$' は特殊とくしゅ終端しゅうたん記号きごうで、スタックのそこ入力にゅうりょくバッファの最後さいごしめす。'S' はその文法ぶんぽう開始かいし記号きごうである。構文こうぶん解析かいせきはスタックの内容ないよう入力にゅうりょくバッファの内容ないようしたがってえていく。しかし、えが必要ひつようかどうかはスタックじょう内容ないようだけで決定けっていされる。

具体ぐたいれい

編集へんしゅう

設定せってい

編集へんしゅう

れいしめすため、つぎのような規則きそく1から3のちいさなLL(1)文法ぶんぽう想定そうていする:

(1) S → F
(2) S → ( S + F )
(3) F → 1

そして、つぎ入力にゅうりょく構文こうぶん解析かいせきおこなう:

( 1 + 1 )

この文法ぶんぽう構文こうぶん解析かいせきひょうつぎのようになる:

( ) 1 + $
S 2 - 1 - -
F - - 3 - -

$ という特殊とくしゅ終端しゅうたん記号きごうかんするくだりがあることに注意ちゅういされたい。$ は入力にゅうりょくわりをしめす。

構文こうぶん解析かいせき手続てつづ

編集へんしゅう

最初さいしょに、構文こうぶん解析かいせき入力にゅうりょくバッファから '(' をみ、スタックから 'S' をむ。ひょう参照さんしょうすると、規則きそく2を適用てきようすべきであることがわかる。規則きそく2はスタックじょうの 'S' を '( S + F )' にえ、規則きそく番号ばんごう出力しゅつりょくする。スタックの内容ないようつぎのようになる。

[ (, S, +, F, ), $ ]

つぎに、入力にゅうりょくバッファとスタック双方そうほうから '(' をのぞく。

[ S, +, F, ), $ ]

つぎに、入力にゅうりょくバッファには '1' があり、スタックのトップが 'S' であることから規則きそく1が適用てきようされて、スタックのトップが 'F' にえられ、さらに規則きそく3が適用てきようされる(適用てきようした規則きそく番号ばんごうとして 1 と 3 が出力しゅつりょくされる)。スタックはつぎのようになる。

[ F, +, F, ), $ ]
[ 1, +, F, ), $ ]

さらに、入力にゅうりょくバッファの先頭せんとうの '1' と '+' はスタックのトップとおなじなので、これらが双方そうほうからのぞかれる。スタックは以下いかのようになる。

[ F, ), $ ]

つぎに、スタックじょうの 'F' が '1' にえられ、規則きそく番号ばんごう3が出力しゅつりょくされる。そして、'1' と ')' は入力にゅうりょくバッファとスタックじょうでマッチするのでのぞかれる。この時点じてん入力にゅうりょくバッファもスタックも '$' だけとなり、構文こうぶん解析かいせき完了かんりょうする。

このれいでは、入力にゅうりょく文字もじれつ受容じゅようされ、以下いか規則きそくじゅん適用てきようされたことが出力しゅつりょくされる。

[ 2, 1, 3, 3 ]

以上いじょう左端ひだりはし導出どうしゅつである。ここでの左端ひだりはし導出どうしゅつ以下いかのようにおこなわれた。

S → ( S + F ) → ( F + F ) → ( 1 + F ) → ( 1 + 1 )

注意ちゅうい

編集へんしゅう

れいしめすように、LLほう構文こうぶん解析かいせきはスタックのトップが終端しゅうたん記号きごう場合ばあい非終端ひしゅうたん記号きごう場合ばあい特殊とくしゅ記号きごう $ の場合ばあいの3種類しゅるいのステップを実行じっこうする。

  • トップが非終端ひしゅうたん記号きごう場合ばあい構文こうぶん解析かいせきひょう参照さんしょうし、適用てきようすべき文法ぶんぽう規則きそく決定けっていして実行じっこうし(スタックをえ)、適用てきようした規則きそく番号ばんごう出力しゅつりょくする。構文こうぶん解析かいせきひょうにおいて、その非終端ひしゅうたん記号きごう入力にゅうりょくバッファじょうのトークンのわせで適用てきようすべき規則きそくしるされていない場合ばあい、エラーを通知つうちして停止ていしする。
  • トップが終端しゅうたん記号きごう場合ばあい入力にゅうりょくバッファとスタックの記号きごう比較ひかくし、それらがおなじである場合ばあいのぞく。ちがっていた場合ばあい、エラーを通知つうちして停止ていしする。
  • トップが $ の場合ばあい入力にゅうりょくバッファも $ なら、構文こうぶん解析かいせき成功せいこう通知つうちする。入力にゅうりょくがまだある場合ばあい、エラーを通知つうちする。いずれの場合ばあい構文こうぶん解析かいせき停止ていしする。

これらのステップは構文こうぶん解析かいせき停止ていしするまでかえされ、構文こうぶん解析かいせき成功せいこうして左端ひだりはし導出どうしゅつ出力しゅつりょくするか、さもなくばエラーを通知つうちする。

LL(1)構文こうぶん解析かいせきひょう作成さくせい

編集へんしゅう

構文こうぶん解析かいせきひょう作成さくせいするためには、非終端ひしゅうたん記号きごう 'A' がスタックのトップにあり、記号きごう 'a' が入力にゅうりょくバッファの先頭せんとうにある場合ばあい適用てきようすべき文法ぶんぽう規則きそく決定けっていしなければならない。そのような規則きそくAw という形式けいしきであり、さらにw対応たいおうする言語げんごに、先頭せんとうが 'a' の文字もじれつすくなくとも1つ存在そんざいする場合ばあいかぎられることは簡単かんたんかる。このため、文字もじれつ w先頭せんとうになりうる終端しゅうたん記号きごう集合しゅうごう (First-set) を Fi(w) であらわす。また、w空文字くうもじれつ可能かのうせいもある場合ばあいFi(w)に εいぷしろんくわえる。A1w1, ..., Anwn という規則きそくぐんから構成こうせいされる文法ぶんぽうがあるとき、Fi(wi) と Fi(Ai) をかく規則きそくについて以下いかのようにもとめる。

  1. かく Fi(wi) と Fi(Ai) をそら集合しゅうごう初期しょきする。
  2. かく規則きそく Aiwi について、Fi(wi) を Fi(Ai) に追加ついかする。ここで、Fi以下いかのように定義ていぎされる:
    • Fi(a w' ) = { a } 、a は すべての終端しゅうたん記号きごう
    • Fi(A w' ) = Fi(A)、A非終端ひしゅうたん記号きごうで、Fi(A) には εいぷしろんふくまれない。
    • Fi(A w' ) = Fi(A) \ { εいぷしろん } ∪ Fi(w' )、A非終端ひしゅうたん記号きごうで、Fi(A) には εいぷしろんふくまれる。
    • Fi(εいぷしろん) = { εいぷしろん }
  3. かく規則きそく Aiwi について Fi(wi) を Fi(Ai) に追加ついかする。
  4. ステップ2と3をちょん Fi 集合しゅうごう変化へんかしなくなるまでかえす。

なお、First-set だけでは構文こうぶん解析かいせきひょう完成かんせいしない。これは、規則きそく右側みぎがわw空文字くうもじれつえられる可能かのうせいがあるためである。したがって構文こうぶん解析かいせきεいぷしろんFi(w)にふくまれるとき、規則きそく Aw使つかAのちつづ可能かのうせいのある記号きごう考慮こうりょしなければならない。つまり Aつづ記号きごう集合しゅうごう (Follow-set) も必要ひつようで、これを Fo(A) と表記ひょうきする。これは、記号きごうれつαあるふぁAaβべーた となるような終端しゅうたん記号きごう a集合しゅうごうであり、開始かいし記号きごうから規則きそく適用てきようしていくことで導出どうしゅつされる。かく非終端ひしゅうたん記号きごうについての Follow-set は以下いかのようにもとめられる:

  1. かく Fo(Ai) をそら集合しゅうごう初期しょきする。
  2. AjwAiw' という形式けいしき規則きそくがある場合ばあい
    • 終端しゅうたん記号きごう aFi(w' ) にふくまれるなら、aFo(Ai) に追加ついかする。
    • εいぷしろんFi(w' ) にふくまれるなら、Fo(Aj) を Fo(Ai) に追加ついかする。
  3. ステップ2をすべての Fo 集合しゅうごう変化へんかしなくなるまでかえす。

以上いじょう構文こうぶん解析かいせきひょうかくマスにどの規則きそくれるかが決定けっていされる。非終端ひしゅうたん記号きごう A終端しゅうたん記号きごう a対応たいおうするひょうのマスを T[A, a] であらわしたとき、以下いかつ。

T[A,a] に規則きそく Awはいるのは以下いか場合ばあいだけである。
aFi(w) にふくまれるか、または
εいぷしろんFi(w) にふくまれ、aFo(A) にふくまれる。

構文こうぶん解析かいせきひょうかくマスに高々たかだか1つの規則きそくだけがはい場合ばあい構文こうぶん解析かいせきはバックトラッキングなしでつねにどの規則きそく適用てきようすべきかを判断はんだんできる。正確せいかくには、そのような場合ばあい文法ぶんぽうを「LL(1)文法ぶんぽう」とぶ。

LL(k)構文こうぶん解析かいせきひょう作成さくせい

編集へんしゅう

1990年代ねんだいちゅうごろまで、k が 1 よりおおきい LL(k) の構文こうぶん解析かいせきはほとんど実用じつようされなかった。というのも、kえると指数しすう関数かんすうてき構文こうぶん解析かいせきひょうおおきくなるためである。この状況じょうきょうえたのは1992ねんPCCTS登場とうじょうである(現在げんざいではANTLRばれている)。PCCTS はおおくのプログラミング言語げんごを LL(k)構文こうぶん解析かいせき効率こうりつてき構文こうぶん解析かいせきでき、最悪さいあくケースの問題もんだい発生はっせいしないことをしめした。さらに、先読さきよみが限定げんていされていてもLLほう有効ゆうこう場合ばあいもあることがしめされた。一方いっぽう従来じゅうらいからの構文こうぶん解析かいせき生成せいせいツール(yaccbison)はLALR(1)構文こうぶん解析かいせきひょうもとづいており、限定げんていされた先読さきよみによるLRほう使つかっている。

LL(k) 構文こうぶん解析かいせき生成せいせいツール

編集へんしゅう

複数ふくすうトークンの先読さきよみをするLLほう構文こうぶん解析かいせき生成せいせいする実装じっそうれいパーサジェネレータ#実装じっそう参照さんしょう

外部がいぶリンク

編集へんしゅう