LR(1)パーサーで使用される先読みは、次のように計算されます。まず、開始状態には次の形式のアイテムがあります
S -> .w ($)
すべてのプロダクションS->wに対して、ここでSは開始記号です。ここで、$マーカーは入力の終わりを示します。
次に、A-> x.By(t)の形式のアイテムを含む状態の場合、xは終端記号と非終端記号の任意の文字列であり、Bは非終端記号であり、B->.wの形式のアイテムを追加します。 (s)すべてのプロダクションB-> wおよびセットFIRST(yt)内のすべての端末。(ここで、FIRSTとは、LLパーサーについて話すときに通常紹介されるFIRSTセットを指します。これまでに見たことがない場合は、これらの講義ノートを確認するのに数分かかります)。
これを文法で試してみましょう。まず、以下を含むアイテムセットを作成します。
S -> .AB ($)
次に、2番目のルールを使用して、Aのすべてのプロダクションに対して、そのプロダクションに対応し、FIRST(B $)のすべての端末の先読みを使用して新しいアイテムを追加します。Bは常に文字列dを生成するため、FIRST(B $)= dであるため、ここで紹介するすべての生成には先読みdがあります。これは与える
S -> .AB ($)
A -> .aAb (d)
A -> .a (d)
それでは、この初期状態での「a」の表示に対応する状態を構築しましょう。まず、以下で始まるプロダクションごとに1つのステップにドットを移動します。
A -> a.Ab (d)
A -> a. (d)
ここで、最初のアイテムには非終端記号の前にドットがあるため、ルールを使用して、Aの生成ごとに1つのアイテムを追加し、それらのアイテムに先読みFIRST(bd)=bを与えます。これは与える
A -> a.Ab (d)
A -> a. (d)
A -> .aAb (b)
A -> .a (b)
このプロセスを続行すると、最終的に、このLR(1)パーサーのすべてのLR(1)状態が構築されます。これはここに示されています:
[0]
S -> .AB ($)
A -> .aAb (d)
A -> .a (d)
[1]
A -> a.Ab (d)
A -> a. (d)
A -> .aAb (b)
A -> .a (b)
[2]
A -> a.Ab (b)
A -> a. (b)
A -> .aAb (b)
A -> .a (b)
[3]
A -> aA.b (d)
[4]
A -> aAb. (d)
[5]
S -> A.B ($)
B -> .d ($)
[6]
B -> d. ($)
[7]
S -> AB. ($)
[8]
A -> aA.b (b)
[9]
A -> aAb. (b)
それが役立つ場合に備えて、私は昨年の夏にコンパイラコースを教え、すべての講義スライドをオンラインで利用できるようにしました。ボトムアップ解析のスライドは、LR解析と解析テーブルの構築の詳細をすべて網羅しているはずです。これらがお役に立てば幸いです。
お役に立てれば!