LR法
この文法のための2つの LR(0) 構文解析表は次のようになる:
アクション表は状態と終端記号でインデックス付けされている(特殊な終端記号 $ は入力ストリームの終わりを示す)。各マスには以下のようなアクションが記述されている:
shift(sn): 次の状態遷移先を n で示す。
reduce(rm): m番の文法規則を実行する。
accept(acc): 入力ストリームにある文字列を受容する。
GOTO表は状態と非終端記号でインデックス付けされており、各マスには非終端記号を解釈し終えたときの次に遷移すべき状態を示す。
表に基づいたボトムアップ構文解析器の構成を右図に示す。構文解析器には、「入力バッファ」、状態を保持するための「スタック」、次に遷移すべき状態や現在の状態で読み込んだ終端記号や非終端記号に適用すべき文法規則を示す「アクション表」と「GOTO表」を持つ。これらの動きを示すため、以下の簡単な文法を使って説明する:
(1) E → E * B
(2) E → E + B
(3) E → B
(4) B → 0
(5) B → 1
上記手続きのステップ4 だけが reduce アクションを生成する。つまり、reduce アクションは必ずアクション表の1つの行で共通となるため、次の入力記号が何であっても文法規則による還元が起きる。これは LR(0) の構文解析表の特徴であり、適用すべき文法規則を決定する前に先読みをしない方式であるためである。あいまいさを排除するために先読みが必要となる文法では、1つの行に複数種類の reduce アクションが存在する可能性があり、上記手続きではそのような表を作成できない。
SLR法やLALR法のようなより洗練された方式では行全体が同じ reduce アクションとはならないような表構築手続きを実施する。つまり、これらの構文解析では LR(0) よりも適用可能な文法の範囲が広い。
ところで、構築されたオートマトンは常に決定性オートマトンである。しかし、reduce アクションを表に追記しようとすると、1つのマスに shift アクションと reduce アクションが共に存在してしまう場合がある。これは shift-reduce 衝突と呼ぶ。あるいは、2つの reduce アクションが衝突する場合もある。これを reduce-reduce 衝突と呼ぶ。しかし、これが発生するということは、その文法が LR(0) では扱えないことを示している。
非常に単純な LR(0) で扱えない文法(shift-reduce衝突が発生する)の例を示す。
(1) E → 1 E
(2) E → 1
ここから次のようなアイテム集合が得られる:
アイテム集合 1
E → 1 • E
E → 1 •
+ E → • 1 E
+ E → • 1