Skip to main content

LR Grammar

LL(1)LL(1) language has good enough properties for us to write a simple parser. However, LL(1)LL(1) still has too many restrictions and sometimes not expressive enough. An alternative approach would be to use LR(1)LR(1) grammar, which is left starting, rightmost derivation and look ahead of one symbol. Using LR(1)LR(1), for any given sequence, we can derivate a leftmost reduction path, thus constructing a parse tree using rightmost derivation.

However, LR(1)LR(1) is too complex sometimes, we may also use SLR(1)SLR(1), simplified version of LR(1)LR(1), or LALR(1)LALR(1), which is a combination of LR(1)LR(1) and SLR(1)SLR(1). We also introduce LR(0)LR(0).

OPG Parser

OPG Parser is a simplified, and in a sense, reversed PDA that has only one state. All CFG can be accepted by a single-node PDA.

info

In the last section, when converting from CFG to PDA, we constructed a single node PDA that can accept all CFG.

tip

When constructing PDA from CFG, we see that one-state PDA has the same expressive power as multiple-states. This is true with empty-stack-equals-acceptance. For accept state set, we need two states, one for the starting, one for the end, so that we can have the same expressive power.

Two states with accept state set basically have an extra rule that when the stack is empty, go to the accept state.

OPG parser is based on deduction. It has four possible actions,

  • Move to the next input symbol, and put it into its stack.
  • Pop a few elements from the stack, deduce it into a single non-terminal, then put the non-terminal into the stack.
  • If there only left start symbol in the stack and the inputs are exhausted, accept.
  • The inputs have exhausted but there are more signs in the stack other than the start symbol, and the machine can not do any more deduction, reject.

This basically is a PDA that walks backward from the end. But in another sense, similar to what we learnt back in the left linear grammar, this walking-backward can be converted into a normal PDA by tweaking the rules.

Nonetheless, we will not focus on how LR parser works as a PDA. It's not the focus.

Now, we have only one issue- how can we define which action the parser should take? Accept and reject are easy to judge, but when should a deduction or a move happen?

Operator Precedence Grammar

OPG is a grammar that, besides what common grammar possesses, it also has a relation, that for any two terminals, a,bVa, b \in \mathcal{V}, one of, aba \equiv b, aba \not < b, or aba \not < b exists.

tip

Our notion DOES NOT IMPLY PARTIAL ORDER. That is,

aba \not > b

DOES NOT IMPLY aba \not < b.

aaa \equiv a is also NOT ALWAYS TRUE.

We define the order as, (for grammar that doesn't produce λ\lambda),

  • aba \equiv b if and only if there exists rules like AabA \rightarrow \ldots ab \ldots or AaBbA \rightarrow \ldots aBb \ldots.
  • aba \not < b if and only if there exists AaBA \rightarrow \ldots aB \ldots and B+bB \Rightarrow^+ b \ldots or B+bCB \Rightarrow^+ bC \ldots.
  • aba \not > b if and only if there exists ABbA \rightarrow \ldots Bb \ldots and B+aB \Rightarrow^+ \ldots a or B+aCB \Rightarrow^+ \ldots aC.
tip

A bit hard to understand. This order is actually the order of reduction. If we have,

SBbBaCCcS \rightarrow Bb \\ B \rightarrow aC \\ C \rightarrow c

For any deduction, the aa is guaranteed to disappear into non-terminals after bb does, so that aba \not > b.

For example, consider deducting the string acbacb,

acbaCbBbSacb \Leftarrow aCb \\ \Leftarrow Bb \\ \Leftarrow S

aa always disappear before bb.

If aa and bb is never adjacent (ignoring the non-terminals) in any rules, we can assign arbitrary order to them.

If you can define two relations on one pair, then it means that the grammar isn't OPC, you should consider refactoring.

For example, consider the following grammar that yields mathematical expression with only multiplication and addition,

SEEE+EEEEE(E)E0123456789S \rightarrow E \\ E \rightarrow E + E \\ E \rightarrow E * E \\ E \rightarrow (E) \\ E \rightarrow 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Because of,

EE+EEEEE \rightarrow E + E \\ E \rightarrow E * E \\

So ++ \not > * and ++ \not < * is valid at the both time, so, it's not OPC.

However, we can rewrite it into,

SEEE+TTTTFFF(E)0123456789S \rightarrow E \\ E \rightarrow E + T | T \\ T \rightarrow T * F | F \\ F \rightarrow (E) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Here, ++ is always reduced after *, and thus +* \not > + is valid. Thus, it is an OPC.

Construct Precedence Table

FIRSTOP and LASTOP

We can't iterate through every rule to get the precedence. Here is a systematic algorithm.

Define the FIRSTOP\text{FIRSTOP} and LASTOP\text{LASTOP} of a non-terminal AA. The first being all possible terminals that can be the first terminals of all the sentences derivate from AA, and the latter is the last. To formulate it formally,

FIRSTOP(A)={bA+bA+BbBN,bV}LASTOP(A)={bA+bA+CbBN,bV}\text{FIRSTOP}(A) = \{b | A \Rightarrow^+ b \ldots \lor A \Rightarrow^+ Bb \ldots \quad B \in \mathcal{N}, b \in \mathcal{V} \} \\ \text{LASTOP}(A) = \{b | A \Rightarrow^+ \ldots b \lor A \Rightarrow^+ \ldots Cb \quad B \in \mathcal{N}, b \in \mathcal{V}\}

Then, for,

AabA \rightarrow \ldots ab \ldots

There must be aba \equiv b.

For,

AaBA \rightarrow \ldots aB \ldots

bFIRSTOP(B),ab\forall b \in \text{FIRSTOP}(B), a \not < b.

For,

ABaA \rightarrow \ldots Ba \ldots

bLASTOP(B),ab\forall b \in \text{LASTOP}(B), a \not > b.

Now the problem is how to obtain FIRSTOP\text{FIRSTOP} and LASTOP\text{LASTOP}.

Because we have,

If,

ABA \rightarrow B \ldots

Then, FIRSTOP(B)FIRSTOP(A)\text{FIRSTOP}(B) \subset \text{FIRSTOP}(A).

If,

ABA \rightarrow \ldots B

Then, LASTOP(B)LASTOP(A)\text{LASTOP}(B) \subset \text{LASTOP}(A).

That tells us that we should construct FIRSTOP\text{FIRSTOP} and LASTOP\text{LASTOP} in topological order.

For the grammar,

SEEE+TTTTFFF(E)0123456789S \rightarrow E \\ E \rightarrow E + T | T \\ T \rightarrow T * F | F \\ F \rightarrow (E) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

We shorten it into,

SEEE+TTTTFFF(E)nS \rightarrow E \\ E \rightarrow E + T | T \\ T \rightarrow T * F | F \\ F \rightarrow (E) | n

And treat nn as a terminal for convenience.

We draw a graph based on first-generate relationship. That is,

In the topological order, we first need FIRSTOP\text{FIRSTOP}.

FIRSTOP(F)={n,(}\text{FIRSTOP}(F) = \{n, (\}

And we walk up the graph, because there is the first terminals generated by TT is only *, and TFT \rightarrow F,

FIRSTOP(T)=FIRSTOP(F)+{}={n,(,}\text{FIRSTOP}(T) = \text{FIRSTOP}(F) + \{*\} = \{n, (, *\}

And,

FIRSTOP(E)=FIRSTOP(T)+{+}={n,(,,+}\text{FIRSTOP}(E) = \text{FIRSTOP}(T) + \{+\} = \{n, (, *, +\} FIRSTOP(S)=FIRSTOP(E)={n,(,,+}\text{FIRSTOP}(S) = \text{FIRSTOP}(E) = \{n, (, *, +\}

Now, draw another graph based on last-generate relationship, which, here, happens to be exactly identical to the FIRSTOP\text{FIRSTOP} graph,

And,

LASTOP(F)={n,)}LASTOP(T)={,n,)}LASTOP(E)={+,,n,)}LASTOP(S)={+,,n,)}\text{LASTOP}(F) = \{n, )\} \\ \text{LASTOP}(T) = \{*, n, )\} \\ \text{LASTOP}(E) = \{+, *, n, )\} \\ \text{LASTOP}(S) = \{+, *, n, )\}

And we are done.

Determining Precedence

Because our deduction concerns the end-of-text symbol S\sout{S}, we add an extra rule,

SSSSS' \rightarrow \sout{S}S\sout{S}

The use SS' as the starting symbol, so that the precedence of S\sout{S} will come out naturally.

Now, for rule,

AX0X1Xn1A \rightarrow X_0 X_1 \ldots X_{n - 1}

Where XiNVX_i \in \mathcal{N} \cup \mathcal{V}

  • If XiXi+1VVX_iX_{i+1} \in \mathcal{V}\mathcal{V}, then XiXi+1X_i \equiv X_{i+1}.
  • If XiXi+1Xi+2VNVX_iX_{i+1}X_{i+2} \in \mathcal{V}\mathcal{N}\mathcal{V}, then XiXi+2X_i \equiv X_{i+2}.
  • If XiXi+1VNX_iX_{i+1} \in \mathcal{V}\mathcal{N}, then bFIRSTOP(Xi+1),Xib\forall b \in \text{FIRSTOP}(X_{i+1}), X_i \not < b.
  • If XiXi+1NVX_iX_{i+1} \in \mathcal{N}\mathcal{V}, then bLASTOP(Xi),bXi+1\forall b \in \text{LASTOP}(X_{i}), b \not > X_{i+1}.

For convenience, we note,

bSb \not > S

Where SS is a set as a shorthand for,

aS,ba\forall a \in S, b \not > a

And this shorthand is also used for \not < and \equiv.

We had,

FIRSTOP(F)={n,(}FIRSTOP(T)={,n,(}FIRSTOP(E)={+,,n,(}FIRSTOP(S)={+,,n,(}LASTOP(F)={n,)}LASTOP(T)={,n,)}LASTOP(E)={+,,n,)}LASTOP(S)={+,,n,)}\text{FIRSTOP}(F) = \{n, (\} \\ \text{FIRSTOP}(T) = \{*, n, (\} \\ \text{FIRSTOP}(E) = \{+, *, n, (\} \\ \text{FIRSTOP}(S) = \{+, *, n, (\} \\ \text{LASTOP}(F) = \{n, )\} \\ \text{LASTOP}(T) = \{*, n, )\} \\ \text{LASTOP}(E) = \{+, *, n, )\} \\ \text{LASTOP}(S) = \{+, *, n, )\} \\

And rules,

SSSSSEEE+TTTTFFF(E)nS' \rightarrow \sout{S}S\sout{S} \\ S \rightarrow E \\ E \rightarrow E + T | T \\ T \rightarrow T * F | F \\ F \rightarrow (E) | n

Unit productions like SES \rightarrow E, ETE \rightarrow T, and TFT \rightarrow F doesn't yield any precedence information.

SSSSS' \rightarrow \sout{S}S\sout{S} tells us that, SFIRSTOP(S)\sout{S} \not < \text{FIRSTOP}(S), LASTOP(S)S \text{LASTOP}(S) \not > \sout{S}, and SS\sout{S} \equiv \sout{S}.

EE+TE \rightarrow E + T tells us that, LASTOP(E)+\text{LASTOP}(E) \not > +, +FIRSTOP(T)+ \not < \text{FIRSTOP}(T).

TTFT \rightarrow T * F tells us that, LASTOP(T)\text{LASTOP}(T) \not > *, FIRSTOP(F)* \not < \text{FIRSTOP}(F).

F(E)F \rightarrow (E) tells us that, ()( \equiv ), (FIRSTOP(E)( \not < \text{FIRSTOP}(E) and LASTOP(E))\text{LASTOP}(E) \not > ).

Make them into a table,

++*(())nnS\sout{S}
++\not >\not <\not <\not >\not <\not >
*\not >\not >\not <\not >\not <\not >
((\not <\not <\not <\equiv\not <\not >
))\not >\not >-\not >--
nn\not >\not >-\not >-\not >
S\sout{S}\not <\not <-\not <\not <\equiv

- denotes there doesn't exist a precedence relation.

Parser

The parser of OPG is a monotonically increasing stack machine. If the newly pushed symbol violates the precedence relation, we perform a deduction.

We had,

SSSSSEEE+TTTTFFF(E)nS' \rightarrow \sout{S}S\sout{S} \\ S \rightarrow E \\ E \rightarrow E + T | T \\ T \rightarrow T * F | F \\ F \rightarrow (E) | n
++*(())nnS\sout{S}
++\not >\not <\not <\not >\not <\not >
*\not >\not >\not <\not >\not <\not >
((\not <\not <\not <\equiv\not <\not >
))\not >\not >-\not >--
nn\not >\not >-\not >-\not >
S\sout{S}\not <\not <-\not <\not <\equiv

An OPG parser works in the following way, conside the next symbol ss,

  • If the current stack looks like xi(or)xi+1(or)(or)xk(or)sx_i (\not < \text{or} \equiv) x_{i+1} (\not < \text{or} \equiv) \cdots (\not < \text{or} \equiv) x_k (\not < \text{or} \equiv) s, then we push ss into the stack. Please note that xix_i are the terminals in the stack. We ignore the non-terminals.
  • If the current stack looks like xixi+1(or)(or)xksx_i \not < x_{i+1} (\not < \text{or} \equiv) \cdots (\not < \text{or} \equiv) x_k \not > s, then we perform a deduction by finding the leftmost xix_i such that xixi+1xkx_ix_{i+1}\ldots x_k match the source of a rule, and then deduce it into a single non-terminal. This should be done recursively until there exists no such xix_i. Then we can push the ss into the stack.

Let's see how the machine would parse n+nnn + n * n.

Firstly, it adds special symbols, Sn+nnS\sout{S}n+n*n\sout{S}. For convenience, we note the input sequence as s0s1sisi+1sns_0s_1\ldots s_i \downarrow s_{i+1} \ldots s_n. The part before the \downarrow is the part that the parser has taken in, and the part after is the remaining part. The next symbol to handle will be si+1s_{i+1}.

Input SequenceStack SnapShotActionReductionReason
Sn+nnS\downarrow \sout{S}n+n*n\sout{S}ShiftEmpty Stack
n+nnS\ldots \downarrow n+n*n\sout{S}S\sout{S}ShiftSn\sout{S}\not < n
+nnS\ldots \downarrow +n*n\sout{S}Sn\sout{S}nReducen+nnF+nnn+n*n \Leftarrow F+n*nSn+\sout{S} \not < n\not > +
+nnS\ldots \downarrow +n*n\sout{S}SF\sout{S}FReduceF+nnT+nnF+n*n\Leftarrow T+n*n-
+nnS\ldots \downarrow +n*n\sout{S}ST\sout{S}TReduceT+nnE+nnT+n*n\Leftarrow E+n*n-
+nnS\ldots \downarrow +n*n\sout{S}SE\sout{S}EShiftS+\sout{S} \not < +
nnS\ldots \downarrow n*n\sout{S}SE+\sout{S}E+ShiftS+n\sout{S}\not < + \not < n
nS\ldots \downarrow *n\sout{S}SE+n\sout{S}E+nReduceE+nnE+FnE+n*n\Leftarrow E+F*nS+n\sout{S}\not < + \not < n \not > *
nS\ldots \downarrow *n\sout{S}SE+F\sout{S}E+FReduceE+FnE+TnE+F*n\Leftarrow E+T*n-
nS\ldots \downarrow *n\sout{S}SE+T\sout{S}E+TShiftS+\sout{S}\not < + \not < *
nS\ldots \downarrow n\sout{S}SE+T\sout{S}E+T*ShiftS+n\sout{S}\not < + \not < * \not < n
S\ldots \downarrow \sout{S}SE+Tn\sout{S}E+T*nReduceE+FnE+TFE+F*n\Leftarrow E+T*FS+nS\sout{S}\not < + \not < * \not < n \not > \sout{S}
S\ldots \downarrow \sout{S}SE+TF\sout{S}E+T*FReduceE+TFE+TE+T*F \Leftarrow E+TS+S\sout{S}\not < + \not < * \not > \sout{S}
S\ldots \downarrow \sout{S}SE+T\sout{S}E+TReduceE+TEE+T \Leftarrow ES+S\sout{S}\not < + \not > \sout{S}
S\ldots \downarrow \sout{S}SE\sout{S}EReduceESE \Leftarrow S-
S\ldots \downarrow \sout{S}SS\sout{S}SShiftSS\sout{S} \equiv \sout{S}
λ\lambdaSSS\sout{S}S\sout{S}

So we have the reduction sequence.

However, in some rows, we gave the reason -. This is because, in those rows, there exists conflicts. That is, at such states, whether,

  • You can either shift or continue reduction. This is called the shift-reduce conflict.
  • There are multiple source that you can reduce into. This is called the reduce-reduce conflict.

In the table above, we resolved that by choosing the option that the input can be parsed- we can do it in simple cases, but machines can't do so.

This issue is caused by the nature of PDA- PDA is a e-NFA with a stack. In our discussion above, to reduce means to walk back in the PDA. However, because e-NFA is non-deterministic, thus allowing multiple transitions- and multiple transition means conflicts, which, in theory, is not a big deal, yet in practice, will cause the rise of time complexity.

We will later see that by replacing the e-NFA with a DFA, that is, a DFA with a stack, we can solve this issue elegantly- albeit it imposes more restrictions on the grammar.

In practice, we need to do backtrace to find the only possible reduction sequence encountered with such conflicts. However, more commonly, we design the grammar so that there exists easier ways to decide the action in conflicts.

Look Ahead LR

The basic idea of LR(k)LR(k) is to look ahead kk characters so that we can decide on the action. Just like what we did with LL(1)LL(1), where, by looking a head of one character, we can decide how to derivate the sentence (If the grammar is LL(1)LL(1)).

The parser or LR is identical to OPG, except that it has it's own rules to resolve conflict, unlike OPG, which requires back tracing.

Let's consider the following grammar,

SEEE+EEnS \rightarrow E \\ E \rightarrow E + E \\ E \rightarrow n \\

And let's perform leftmost reduction (rightmost derivation) for n+nn + n.

n+nE+nE+EESn + n \Leftarrow E + n \Leftarrow E + E \Leftarrow E \Leftarrow S

Our ideal parser should mimic this behavior,

Stack SnapshotInputAction
S\sout{S}Sn+nS\sout{S} \downarrow n + n \sout{S}Shift
Sn\sout{S}nSn+nS\sout{S}n\downarrow + n \sout{S}Reduce
SE\sout{S}ESn+nS\sout{S}n\downarrow + n \sout{S}Shift
SE+\sout{S}E+Sn+nS\sout{S}n+\downarrow n \sout{S}Shift
SE+n\sout{S}E+nSn+nS\sout{S}n+n\downarrow \sout{S}Shift
SE+E\sout{S}E+ESn+nS\sout{S}n+n\downarrow \sout{S}Reduce
SE\sout{S}ESn+nS\sout{S}n+n\downarrow \sout{S}shift
SES\sout{S}E\sout{S}\ldots \downarrow-

The parser should decide the action based on the stack and the next kk characters.

Live Prefix

Suppose we have a CFG and a rightmost derivation sequence αirmβi\alpha_i \Rightarrow_{rm} \beta_i.

We call a string ss a handle if the reduction of a sequence is as follows,

xsyxAyxsy \Leftarrow xAy

For any intermediate result in a rightmost derivation sequence, the βi\beta_i. It's prefix pp is called a live sequence if, pp does not contain any character to the right side of the handle of βi\beta_i.

For example,

SAA0A101S \rightarrow A \\ A \rightarrow 0A1 | 01 \\

For the reduction sequence,

00110A1AS0011 \Leftarrow 0A1 \Leftarrow A \Leftarrow S

In the step 00110A10011 \Leftarrow 0A1,

  • 0101 is the handle because A01A \rightarrow 01 was used.
  • λ\lambda, 00, 0000, 001001 are all live prefixes

Let's consider the language,

LP={pp is a live prefix of any sentence u such that Su}LP = \{p | p \text{ is a live prefix of any sentence } u \text{ such that } S \Rightarrow^* u \}

We can prove that LPLP is a regular language

TODO: ADD THE PROOF

And RL can be recognized by a DFA. And thus, we can design the LR parser to be,

  • A DFA that recognizes the live prefix.
  • A set of rules that tells which rule should be applied, given the next kk character and the state of the DFA.

LR Parser

The real LR parser is designed in a easier way to implement in programming, that is,

  • A State stack that is used to record the state of the DFA
  • A symbol stack that contains the current string to be reduced
  • An action table ACTION(S,a)\text{ACTION}(S, a) that tells the parser, if the top of the state stack is SS, and the input symbol is aa, which action should the parser take. Specifically, we note accacc as the accept action.
  • A goto table GOTO(S,X)\text{GOTO}(S, X) that tells the parser, if the top of the state stack is SS, and the top of the symbol stack is XX, which state the parser should move into.

The different parser uses different means to construct the action table and the goto table. Common ways are LR(0)LR(0), SLR(1)SLR(1), LR(1)LR(1).

LR(0) Parser

Item and Its Closure

We first define two concepts, item and item closure.

An item is a rule that has special note on the right side. We use \Downarrow. That is, for example, from the rule,

AaBcA \rightarrow aBc

We can get the following items,

AaBcAaBcAaBcAaBcA \rightarrow \Downarrow aBc \\ A \rightarrow a \Downarrow Bc \\ A \rightarrow aB \Downarrow c \\ A \rightarrow aBc \Downarrow

Then we define its closure CLOSURE(I)\text{CLOSURE}(I) as all the possible reduction from the current state, that is,

r=AαX where rCn1append(Cn,r)If X=Bβ where BN,Bγ,append(Cn,Bγ)CLOSURE(I)=C+\forall r = A \rightarrow \alpha \Downarrow X \text{ where } r \in C_{n - 1} \\ \text{append}(C_{n}, r) \\ \text{If } X = B\beta' \text{ where } B \in \mathcal{N}, \forall B \rightarrow \gamma, \text{append}(C_{n}, B \rightarrow \Downarrow \gamma) \\ \text{CLOSURE}(I) = C_{+\infty}

For example, consider the grammar,

SSSSSCCCcCdS' \rightarrow \sout{S}S\sout{S} \\ S \rightarrow CC \\ C \rightarrow cC | d

Consider the closure of SSSSS' \rightarrow \sout{S}\Downarrow S\sout{S}

C0={SSSS}C1={SSSCC}C2={SSSSSCCCcCCd}C_0 = \{ S' \rightarrow \sout{S}\Downarrow S\sout{S} \} \\ C_1 = \{ S' \rightarrow \Downarrow S \\ S \rightarrow \Downarrow CC \} \\ C_2 = \{ S' \rightarrow \sout{S}\Downarrow S\sout{S} \\ S \rightarrow \Downarrow CC \\ C \rightarrow \Downarrow cC \\ C \rightarrow \Downarrow d \} \\

Repeating the process doesn't generate more items, so, CLOSURE(SSSS)=C2\text{CLOSURE}(S \rightarrow \sout{S}\Downarrow S\sout{S}) = C_2

Generate the Table

For a CFG grammar. Firstly, we add the extra grammar SSSSS' \rightarrow \sout{S}S\sout{S}, and use SS' as the starting symbol.

The idea here is similar to converting NFA to DFA. Basically, we need to find all the possible occurring items.

Firstly, we have I0=CLOSURE({SSSS})I_0 = \text{CLOSURE}( \{ S' \rightarrow \sout{S}\Downarrow S \sout{S} \}). This is the first state.

THen, suppose we have items,

In={AαXβ}I_n = \{ A \rightarrow \alpha \Downarrow X \beta \}

Where XX represents a non-terminal or a terminal.

Then, we would like to look for, for example, GOTO(In,Z)\text{GOTO}(I_n, Z) or ACTION(In,Z)\text{ACTION}(I_n, Z). If ZZ is a terminal, it is an action. Or else, a goto.

We first create a set In+1,ZI'_{n+1, Z}, and then,

AαXβInX=Zappend(In+1,Z,AαXβ)\forall A \rightarrow \alpha \Downarrow X \beta \in I_n \land X = Z \\ \text{append}(I'_{n+1, Z}, A \rightarrow \alpha X \Downarrow \beta)

We define the new state In+1,Z=CLOSURE(In+1,Z)I_{n+1, Z} = \text{CLOSURE}(I'_{n+1, Z}), and GOTO(In,Z)=In+1,Z\text{GOTO}(I_n, Z) = I_{n+1, Z} or ACTION(In,Z)=In+1,Z\text{ACTION}(I_n, Z) = I_{n+1, Z}.

If In+1,ZI_{n+1, Z} exists already, you should use the old state. This should be repeated until there is no new state.

For example, we have CFG,

SSSSSCCCcCdS' \rightarrow \sout{S}S\sout{S} \\ S \rightarrow CC \\ C \rightarrow cC | d \\

And the initial state,

I0=CLOSURE({SSSS})={SSSSSCCCcCCd}I_0 = \text{CLOSURE}(\{ S' \rightarrow \sout{S}\Downarrow S\sout{S} \}) \\ = \{ S' \rightarrow \sout{S}\Downarrow S\sout{S} \\ S \rightarrow \Downarrow CC \\ C \rightarrow \Downarrow cC \\ C \rightarrow \Downarrow d \}

So,

I1,S=CLOSURE({SSSS})={SSSS}I1,C=CLOSURE({SCC})={SCC,CcC,Cd}I1,c=CLOSURE({CcC})={CcC,CcC,Cd}I1,d=CLOSURE({Cd})={Cd}I_{1, S} = \text{CLOSURE}(\{ S' \rightarrow \sout{S}S \Downarrow \sout{S}\}) = \{ S' \rightarrow \sout{S}S \Downarrow \sout{S}\} \\ I_{1, C} = \text{CLOSURE}(\{ S \rightarrow C \Downarrow C \}) = \{ S \rightarrow C \Downarrow C, C \rightarrow \Downarrow cC, C \rightarrow \Downarrow d \} \\ I_{1, c} = \text{CLOSURE}(\{ C \rightarrow c \Downarrow C \}) = \{ C \rightarrow c \Downarrow C, C \rightarrow \Downarrow cC, C \rightarrow \Downarrow d \} \\ I_{1, d} = \text{CLOSURE}(\{ C \rightarrow d \Downarrow \}) = \{ C \rightarrow d \Downarrow \} I2,S,S=CLOSURE({SSSS})={SSSS}I2,C,d=CLOSURE({Cd})=I1,dI2,C,C=CLOSURE({SCC})={SCC}I2,C,c=CLOSURE({CcC})=I1,cI2,c,c=CLOSURE({CcC})=I1,cI2,c,C=CLOSURE({CcC})={CcC}I2,c,d=CLOSURE({Cd})=I1,dI_{2, S, \sout{S}} = \text{CLOSURE}(\{ S' \rightarrow \sout{S}S \sout{S} \Downarrow\}) = \{ S' \rightarrow \sout{S}S \sout{S} \Downarrow\} \\ I_{2, C, d} = \text{CLOSURE}(\{ C \rightarrow d \Downarrow \}) = I_{1, d} \\ I_{2, C, C} = \text{CLOSURE}(\{ S \rightarrow CC \Downarrow \}) = \{ S \rightarrow CC \Downarrow \} \\ I_{2, C, c} = \text{CLOSURE}(\{ C \rightarrow c \Downarrow C\}) = I_{1, c} \\ I_{2, c, c} = \text{CLOSURE}(\{ C \rightarrow c \Downarrow C \}) = I_{1, c} \\ I_{2, c, C} = \text{CLOSURE}(\{ C \rightarrow cC \Downarrow \}) = \{ C \rightarrow cC \Downarrow \} \\ I_{2, c, d} = \text{CLOSURE}(\{ C \rightarrow d \Downarrow \}) = I_{1, d} \\

Now, we have finished all the states.

If GOTO(In,Z)=In+1,Z\text{GOTO}(I_n, Z) = I_{n+1, Z}, then we just goto the new II. This is done by pushing the new state to the state stack.

If ACTION(In,Z)=In+1,Z\text{ACTION}(I_n, Z) = I_{n+1, Z}, if there exists AαxβA \rightarrow \alpha \Downarrow x\beta, then the action is push stack and goto the new state.

If InI_n contains AαA \rightarrow \alpha \Downarrow, then the action is reduce using that rule.

Specially, if there is SSSSS' \rightarrow \sout{S}S \Downarrow \sout{S}, then it's an accept.

We had,

I0=CLOSURE({SSSS})={SSSSSCCCcCCd}I_0 = \text{CLOSURE}(\{ S' \rightarrow \sout{S}\Downarrow S\sout{S} \}) \\ = \{ S' \rightarrow \sout{S}\Downarrow S\sout{S} \\ S \rightarrow \Downarrow CC \\ C \rightarrow \Downarrow cC \\ C \rightarrow \Downarrow d \}

So,

I1,S={SSSS}I1,C={SCC,CcC,Cd}I1,c={CcC,CcC,Cd}I1,d={Cd}I_{1, S} = \{ S' \rightarrow \sout{S}S \Downarrow \sout{S}\} \\ I_{1, C} = \{ S \rightarrow C \Downarrow C, C \rightarrow \Downarrow cC, C \rightarrow \Downarrow d \} \\ I_{1, c} = \{ C \rightarrow c \Downarrow C, C \rightarrow \Downarrow cC, C \rightarrow \Downarrow d \} \\ I_{1, d} = \{ C \rightarrow d \Downarrow \} I2,S,S={SSSS}I2,C,d=I1,dI2,C,C={SCC}I2,C,c=I1,cI2,c,c=I1,cI2,c,C={CcC}I2,c,d=I1,dI_{2, S, \sout{S}} = \{ S' \rightarrow \sout{S}S \sout{S} \Downarrow\} \\ I_{2, C, d} = I_{1, d} \\ I_{2, C, C} = \{ S \rightarrow CC \Downarrow \} \\ I_{2, C, c} = I_{1, c} \\ I_{2, c, c} = I_{1, c} \\ I_{2, c, C} = \{ C \rightarrow cC \Downarrow \} \\ I_{2, c, d} = I_{1, d} \\

We label them with number. Please note that I2,S,SI_{2,S,\sout{S}} won't be present in the table because before this state, the parser has accepted.

Old NameNumber
I0I_00
I1,SI_{1,S}1
I1,CI_{1,C}2
I1,cI_{1,c}3
I1,dI_{1,d}4
I2,C,CI_{2,C,C}5
I2,c,CI_{2,c,C}6

And we can conclude the ACTION and GOTO table. We note the action sisi as shift and move to state ii. If we write ii, it means to move to state ii. If we write the rule, it means to reduce using that rule.

S\sout{S}ccddSSCC
0-s3s412
1acc----
2-s3s4-5
3-s3s4-6
4CdC \rightarrow dCdC \rightarrow dCdC \rightarrow d--
5SCCS \rightarrow CCSCCS \rightarrow CCSCCS \rightarrow CC--
6CcCC \rightarrow cCCcCC \rightarrow cCCcCC \rightarrow cC--

If your table looks the same as this one, that every action has a definite action or goto, then it is an LR(1)LR(1) grammar. If there exists multiple reduction, there exists reduction-reduction conflict. If there exists both reduction and shift, there exists shift-reduction conflict.

Parsing example

S\sout{S}ccddSSCC
0-s3s412
1acc----
2-s3s4-5
3-s3s4-6
4CdC \rightarrow dCdC \rightarrow dCdC \rightarrow d--
5SCCS \rightarrow CCSCCS \rightarrow CCSCCS \rightarrow CC--
6CcCC \rightarrow cCCcCC \rightarrow cCCcCC \rightarrow cC--

Let's use this table to parse cddcdd.

Suppose we have a pointer that points to the next symbol in the sentence ready to parse.

When there exists remaining input, we make judgement based on the next character. If the pointer is already at S\sout{S} in the end, we use the top of symbol stack.

  • By shifting, we mean to push the next input symbol and push the new state. We also move the pointer.
  • By reducing, we mean to, pop the corresponding part out of the stack, and do a reduction. The reduced non-terminal will be inserted after the next pointer. In addition, it will also pop equal number of states to the number of symbols in the target of the rules. That is, if we have AαA \rightarrow \alpha, we pop α|\alpha| states out, pop α|\alpha| symbols out, and insert AA after the pointer.
  • By goto, we do the same as shifting, it's just that we are pushing a non-terminal.

We are always determining the action based on the next symbol and the current state.

Symbol StackState StackInputAction
S\sout{S}00cddS\downarrow cdd \sout{S}s3
Sc\sout{S}c0303cddSc\downarrow dd \sout{S}s4
Scd\sout{S}cd034034cddScd\downarrow d \sout{S}CdC \rightarrow d
Sc\sout{S}c0303cdCdcd\downarrow Cd6
ScC\sout{S}cC036036cdCdScdC\downarrow d \sout{S}CcCC \rightarrow cC
S\sout{S}00cdCCdcdC \downarrow Cd2
SC\sout{S}C0202cdCCdScdCC \downarrow d \sout{S}s4
SCd\sout{S}Cd024024cdCCdScdCCd\downarrow \sout{S}CdC \rightarrow d
SC\sout{S}C0202cdCCdCScdCCd\downarrow C \sout{S}5
SCC\sout{S}CC025025cdCCdCScdCCdC\downarrow \sout{S}SCCS \rightarrow CC
S\sout{S}00cdCCdCSScdCCdC\downarrow S\sout{S}1
SS\sout{S}S0101cdCCdCSScdCCdCS\downarrow \sout{S}acc

SLR(1)

SLR(1)SLR(1) and LR(1)LR(1) are solutions to the case where there exists conflict in the LRLR table. We look at SLR(1)SLR(1) (Simplified LR(1)LR(1)) first.

Consider the rules,

SSSSSyAxAaabS' \rightarrow \sout{S}S\sout{S} \\ S \rightarrow yAx \\ A \rightarrow a | ab

We calculate its items.

I0=CLOSURE({SSSS})={SSSS,SyAx}GOTO(I0,S)=CLOSURE({SSSS})={SSSS}=I1ACTION(I0,y)=CLOSURE({SyAx})={SyAx,Aaab}=I2GOTO(I2,A)=CLOSURE({SyAx})={SyAx}=I3ACTION(I2,a)=CLOSURE({Aaab})={Aaab}=I4ACTION(I3,x)=CLOSURE({SyAx})={SyAx}=I5ACTION(I4,b)=CLOSURE({Aab})={Aab}=I6I_0 = \text{CLOSURE}(\{ S' \rightarrow \sout{S}\Downarrow S \sout{S} \}) = \{ S' \rightarrow \sout{S}\Downarrow S \sout{S}, S \rightarrow \Downarrow yAx \} \\ \text{GOTO}(I_0, S) = \text{CLOSURE}(\{ S' \rightarrow \sout{S} S \Downarrow \sout{S} \}) = \{ S' \rightarrow \sout{S} S \Downarrow \sout{S} \} = I_1 \\ \text{ACTION}(I_0, y) = \text{CLOSURE}(\{ S \rightarrow y \Downarrow Ax \}) = \{ S \rightarrow y \Downarrow Ax, A \rightarrow \Downarrow a | \Downarrow ab \} = I_2 \\ \text{GOTO}(I_2, A) = \text{CLOSURE}(\{ S \rightarrow yA\Downarrow x \}) = \{ S \rightarrow yA\Downarrow x \} = I_3 \\ \text{ACTION}(I_2, a) = \text{CLOSURE}(\{ A \rightarrow a \Downarrow | a \Downarrow b \}) = \{ A \rightarrow a \Downarrow | a \Downarrow b \} = I_4 \\ \text{ACTION}(I_3, x) = \text{CLOSURE}(\{ S \rightarrow yAx \Downarrow \}) = \{ S \rightarrow yAx \Downarrow \} = I_5 \\ \text{ACTION}(I_4, b) = \text{CLOSURE}(\{ A \rightarrow ab \Downarrow \}) = \{ A \rightarrow ab \Downarrow \} = I_6 \\

We have the table,

S\sout{S}SSAAaabbxxyy
0-1----s2
1acc------
2--3s4---
3-----s5-
4AaA \rightarrow aAaA \rightarrow aAaA \rightarrow aAaA \rightarrow aAaA \rightarrow a, s6AaA \rightarrow aAaA \rightarrow a
5SyAxS \rightarrow yAxSyAxS \rightarrow yAxSyAxS \rightarrow yAxSyAxS \rightarrow yAxSyAxS \rightarrow yAxSyAxS \rightarrow yAxSyAxS \rightarrow yAx
6AabA \rightarrow abAabA \rightarrow abAabA \rightarrow abAabA \rightarrow abAabA \rightarrow abAabA \rightarrow abAabA \rightarrow ab

You can see that at 4,b4, b, there exists two possible actions, wether to shift and goto 6, or to reduce. This is a shift-reduction conflict. To resolve this conflict, we calculate the FOLLOW\text{FOLLOW} of AA (Because the conflict happens to the reduction rule with the source symbol of AA).

Obviously, the only rule that produces AA is SyAxS \rightarrow yAx, thus FOLLOW(A)={x}\text{FOLLOW}(A) = \{ x \}.

Encountered the case where the machine is at state 44, and the pointer to the next symbol bb, we will peek ahead the new symbol nn.

If nFOLLOW(A)n \in \text{FOLLOW}(A), we choose reduction because, will, nn is a valid successor of the reduced AA.

If n∉FOLLOW(A)n \not \in \text{FOLLOW}(A), we choose shifting.

Because we need to peek ahead one character, this is a SLR(1)SLR(1) grammar.

Suppose we have yabxyabx to parse.

Symbol StackState StackInputAction
S\sout{S}00yabxS\downarrow yabx \sout{S}s2
Sy\sout{S}y0202yabxSy\downarrow abx \sout{S}s4
Sya\sout{S}ya024024yabxSya\downarrow bx \sout{S}b∉FOLLOW(A)b \not \in \text{FOLLOW}(A) s6
Syab\sout{S}yab02460246yabxSyab\downarrow x \sout{S}AabA \rightarrow ab
Sy\sout{S}y0202yabAxSyab\downarrow Ax \sout{S}3
SyA\sout{S}yA023023yabAxSyabA\downarrow x \sout{S}s5
SyAx\sout{S}yAx02350235yabAxSyabAx\downarrow \sout{S}SyAxS \rightarrow yAx
S\sout{S}00yabAxSSyabAx\downarrow S\sout{S}1
SS\sout{S}S0101yabAxSSyabAxS\downarrow \sout{S}acc

This is a case where we chose to shift. For yaxyax, we choose to reduce.

Symbol StackState StackInputAction
S\sout{S}00yaxS\downarrow yax \sout{S}s2
Sy\sout{S}y0202yaxSy\downarrow ax \sout{S}s4
Sya\sout{S}ya024024yaxSya\downarrow x \sout{S}xFOLLOW(A)x \in \text{FOLLOW}(A), AaA \rightarrow a
Sy\sout{S}y0202yaAxSya\downarrow Ax \sout{S}3
SyA\sout{S}yA023023yaAxSyaA\downarrow x\sout{S}s5
SyAx\sout{S}yAx02350235yaAxSyaAx\downarrow \sout{S}SyAxS \rightarrow yAx
S\sout{S}00yaAxSSyaAx\downarrow S\sout{S}1
SS\sout{S}S0101yaAxSSyaAxS\downarrow \sout{S}acc

As for reduction-reduction conflict, let's consider a row that looks like,

x
iAαA \rightarrow \alpha, BαB \rightarrow \alpha

To choose which item to reduce do depends on the next symbol xx

If xFOLLOW(A)x \in \text{FOLLOW}(A), reduce to AA, or else reduce to BB. So is it for multiple conflicts.

However, SLR(1)SLR(1) does not guarantee to eliminate all conflicts. For example, when multiple textFOLLOWtext{FOLLOW} overlaps, we can't choose which one to reduce.

LR(1)

LR(k)LR(k) will not only peek the symbol ahead when conflict happens. It constantly look ahead.

We define an item in LR(k)LR(k) as,

Axy,wA \rightarrow x\Downarrow y, w

Where w=k|w|=k, and there exists a derivation such that S+αxywβS' \Rightarrow^+ \alpha xyw \beta . That is, ww can be a successor string of the handle AA derivate.

In the case where k=1k = 1, that is to say,

Axy,fA \rightarrow x\Downarrow y, f

Where fFOLLOW(A)f \in \text{FOLLOW}(A).

Then, utilizing the LR(1)LR(1) item, we can build a new set in the same way as before- it's just that we need to distinguish the following characters. This will results in an increase in the states.

The way to get the closure is a bit different.

r=AαX,a where rCn1append(Cn,r)If X=Bβ where BN,Bγ,append(Cn,(Bγ,FIRST(βa)))CLOSURE(I)=C+\forall r = A \rightarrow \alpha \Downarrow X, a \text{ where } r \in C_{n - 1} \\ \text{append}(C_{n}, r) \\ \text{If } X = B\beta' \text{ where } B \in \mathcal{N}, \forall B \rightarrow \gamma, \text{append}(C_{n}, (B \rightarrow \Downarrow \gamma, \text{FIRST}(\beta' a))) \\ \text{CLOSURE}(I) = C_{+\infty}

And we starts with I0=CLOSURE({(SSSS,S)})I_0 = \text{CLOSURE}(\{(S' \rightarrow \sout{S}\Downarrow S \sout{S}, \sout{S})\})

Let's use the grammar,

SSSSSCCCcCdS' \rightarrow \sout{S}S\sout{S} \\ S \rightarrow CC \\ C \rightarrow cC | d

This is our previous grammar. Here it is just for demonstration.

We first calculate the FIRSTFIRST and FOLLOWFOLLOW.

FIRST(C)={c,d}FIRST(S)=FIRST(C)={c,d}FOLLOW(S)={S}FOLLOW(C)=FOLLOW(S)+FIRST(C)={S,c,d}\text{FIRST}(C) = \{c, d\} \\ \text{FIRST}(S) = \text{FIRST}(C) = \{c, d\} \\ \text{FOLLOW}(S) = \{\sout{S}\} \\ \text{FOLLOW}(C) = \text{FOLLOW}(S) + \text{FIRST}(C) = \{\sout{S}, c, d\} I0=CLOSURE({(SSSS,S)})={(SSSS,S),(SCC,S),(CcCd,{c,d})}I_0 = \text{CLOSURE}(\{(S' \rightarrow \sout{S}\Downarrow S \sout{S}, \sout{S})\}) \\ = \{ (S' \rightarrow \sout{S}\Downarrow S \sout{S}, \sout{S}),\\ (S \rightarrow \Downarrow CC, \sout{S}),\\ (C \rightarrow \Downarrow cC | \Downarrow d, \{ c,d \})\}

We use (CcCd,{c,d})(C \rightarrow \Downarrow cC | \Downarrow d, \{ c,d \}) as a shorthand. Don't treat it as one item. It is a shorthand of four.

GOTO(I0,S)=CLOSURE({(SSSS,S)})={(SSSS,S)}=I1GOTO(I0,C)=CLOSURE({(SCC,S)})={(SCC,S),(CcCd,S)}=I2ACTION(I0,c)=CLOSURE({(CcC,{c,d})})={(CcC,{c,d}),(CcCd,{c,d})}=I3ACTION(I0,d)=CLOSURE({(Cd,{c,d})})={(Cd,{c,d})}=I4GOTO(I2,C)=CLOSURE({(SCC,S)})={(SCC,S)}=I5ACTION(I2,c)=CLOSURE({(CcC,S)})={(CcC,S),(CcCd,S)}=I6I3ACTION(I2,d)=CLOSURE({(Cd,S)})={(Cd,S)}=I7I4GOTO(I3,C)=CLOSURE({(CcC,{c,d})})={(CcC,{c,d})}=I8ACTION(I3,c)=CLOSURE({(CcC,{c,d})})={(CcC,{c,d}),(CcCd,{c,d})}=I3ACTION(I3,d)=CLOSURE({(Cd,{c,d})})={(Cd,{c,d})}=I4GOTO(I6,C)=CLOSURE({(CcC,S)})={(CcC,S)}=I9I8GOTO(I6,c)=CLOSURE({(CcC,S)})={(CcC,S),(CcCd,S)}=I6GOTO(I6,d)=CLOSURE({(Cd,S)})={(Cd,S)}=I7\text{GOTO}(I_0, S) = \text{CLOSURE}(\{(S' \rightarrow \sout{S} S \Downarrow \sout{S}, \sout{S})\}) \\ = \{(S' \rightarrow \sout{S} S \Downarrow \sout{S}, \sout{S})\} = I_1 \\ \text{GOTO}(I_0, C) = \text{CLOSURE}(\{ (S \rightarrow C \Downarrow C, \sout{S}) \}) \\ = \{ (S \rightarrow C \Downarrow C, \sout{S}), (C \rightarrow \Downarrow cC | \Downarrow d, \sout{S}) \} = I_2 \\ \text{ACTION}(I_0, c) = \text{CLOSURE}(\{ (C \rightarrow c \Downarrow C , \{ c,d \}) \}) \\ = \{ (C \rightarrow c \Downarrow C , \{ c,d \}), (C \rightarrow \Downarrow cC | \Downarrow d, \{ c,d \}) \} = I_3 \\ \text{ACTION}(I_0, d) = \text{CLOSURE}(\{ (C \rightarrow d \Downarrow , \{ c,d \}) \}) \\ = \{ (C \rightarrow d \Downarrow , \{ c,d \}) \} = I_4 \\ \text{GOTO}(I_2, C) = \text{CLOSURE}(\{ (S \rightarrow CC\Downarrow, \sout{S}) \}) \\ = \{ (S \rightarrow CC\Downarrow, \sout{S}) \} = I_5 \\ \text{ACTION}(I_2, c) = \text{CLOSURE}(\{ (C \rightarrow c \Downarrow C, \sout{S}) \}) \\ = \{ (C \rightarrow c \Downarrow C, \sout{S}), (C \rightarrow \Downarrow cC | \Downarrow d, \sout{S}) \} = I_6 \neq I_3\\ \text{ACTION}(I_2, d) = \text{CLOSURE}(\{(C \rightarrow d\Downarrow, \sout{S})\}) \\ = \{(C \rightarrow d\Downarrow, \sout{S})\} = I_7 \neq I_4 \\ \text{GOTO}(I_3, C) = \text{CLOSURE}(\{(C \rightarrow c C \Downarrow , \{ c,d \})\})\\ = \{(C \rightarrow c C \Downarrow , \{ c,d \})\} = I_8 \\ \text{ACTION}(I_3, c) = \text{CLOSURE}(\{ (C \rightarrow c \Downarrow C, \{ c,d \}) \}) \\ = \{ (C \rightarrow c \Downarrow C, \{ c,d \}), (C \rightarrow \Downarrow c C | \Downarrow d, \{ c,d \}) \} = I_3 \\ \text{ACTION}(I_3, d) = \text{CLOSURE}(\{ (C \rightarrow d \Downarrow , \{ c,d \}) \}) \\ = \{ (C \rightarrow d \Downarrow , \{ c,d \}) \} = I_4 \\ \text{GOTO}(I_6, C) = \text{CLOSURE}(\{ (C \rightarrow cC \Downarrow , \sout{S}) \}) \\ = \{ (C \rightarrow cC \Downarrow , \sout{S}) \} = I_9 \neq I_8 \\ \text{GOTO}(I_6, c) = \text{CLOSURE}(\{ (C \rightarrow c\Downarrow C, \sout{S}) \}) \\ = \{ (C \rightarrow c\Downarrow C, \sout{S}), (C \rightarrow \Downarrow cC | \Downarrow d, \sout{S}) \} = I_6 \\ \text{GOTO}(I_6, d) = \text{CLOSURE}(\{ (C \rightarrow d \Downarrow , \sout{S}) \}) \\ = \{ (C \rightarrow d \Downarrow , \sout{S}) \} = I_7

Now we have the table,

SCcdS\sout{S}
012s3s4-
1----acc
2-5s6s7-
3-8s3s4-
4(Cd,{c,d})(C \rightarrow d \Downarrow , \{ c,d \})(Cd,{c,d})(C \rightarrow d \Downarrow , \{ c,d \})(Cd,{c,d})(C \rightarrow d \Downarrow , \{ c,d \})(Cd,{c,d})(C \rightarrow d \Downarrow , \{ c,d \})(Cd,{c,d})(C \rightarrow d \Downarrow , \{ c,d \})
5(SCC,S)(S \rightarrow CC\Downarrow, \sout{S})(SCC,S)(S \rightarrow CC\Downarrow, \sout{S})(SCC,S)(S \rightarrow CC\Downarrow, \sout{S})(SCC,S)(S \rightarrow CC\Downarrow, \sout{S})(SCC,S)(S \rightarrow CC\Downarrow, \sout{S})
6-9s6s7-
7(Cd,S)(C \rightarrow d\Downarrow, \sout{S})(Cd,S)(C \rightarrow d\Downarrow, \sout{S})(Cd,S)(C \rightarrow d\Downarrow, \sout{S})(Cd,S)(C \rightarrow d\Downarrow, \sout{S})(Cd,S)(C \rightarrow d\Downarrow, \sout{S})
8(CcC,{c,d})(C \rightarrow c C \Downarrow , \{ c,d \})(CcC,{c,d})(C \rightarrow c C \Downarrow , \{ c,d \})(CcC,{c,d})(C \rightarrow c C \Downarrow , \{ c,d \})(CcC,{c,d})(C \rightarrow c C \Downarrow , \{ c,d \})(CcC,{c,d})(C \rightarrow c C \Downarrow , \{ c,d \})
9(CcC,S)(C \rightarrow cC \Downarrow , \sout{S})(CcC,S)(C \rightarrow cC \Downarrow , \sout{S})(CcC,S)(C \rightarrow cC \Downarrow , \sout{S})(CcC,S)(C \rightarrow cC \Downarrow , \sout{S})(CcC,S)(C \rightarrow cC \Downarrow , \sout{S})

This is the table we need.