LR
LR
An LR(0) parser is a type of bottom-up parser used for syntax analysis in compilers. It is a special
case of LR(k) parsers, where k=0, meaning it only looks at the current input symbol (without any
additional lookahead). The "LR" in LR(0) stands for Left-to-right scanning of the input and Rightmost
derivation in reverse (a bottom-up approach). The number "0" indicates that no lookahead is used
beyond the current symbol.
2. Rightmost derivation in reverse (R): The parsing process constructs the rightmost derivation
in reverse order, i.e., starting from the end of the string and moving backward toward the
start.
3. 0 Lookahead: The parser uses no lookahead tokens; it makes parsing decisions based solely
on the current symbol and the stack.
An LR(0) parser uses a stack to hold symbols (both terminals and non-terminals) and a state machine
to represent the parsing process. The parser performs the following operations:
Reduce: Replace a sequence of symbols at the top of the stack (a production) with a single
non-terminal symbol (the left-hand side of the production).
Accept: When the stack contains the start symbol and the input is fully consumed, the parse
is successful.
An LR(0) parser is driven by a parsing table, which is constructed during the grammar analysis. The
table has two parts:
1. Action Table: Specifies what action the parser should take based on the current state and the
next input symbol.
o Shift: Move the current input symbol to the stack and transition to a new state.
2. Goto Table: Specifies the state transitions when a non-terminal is found at the top of the
stack after a reduction.
Copy code
S→A
A → aA | b
The productions:
1. S → A
2. A → aA
3. A → b
We first convert the productions into LR(0) items, which are just the productions with a "dot" (.)
indicating the position of the parser in the production.
1. Start with the initial item (the start symbol with the dot at the beginning):
makefile
Copy code
I0: S → .A
2. From I0, we can derive the closure (all possible items based on the grammar rules):
makefile
Copy code
I0:
S → .A
A → .aA
A → .b
3. Next, we can compute the Goto of I0 for terminal symbols a, b, and non-terminal A:
o Goto(I0, b) → I2: A → b.
The action table is filled based on the current state and the terminal symbol:
Shift: If a terminal is found and can lead to a valid state transition, the action is to shift.
Reduce: If a production rule is complete (i.e., the dot is at the end), a reduce action is taken.
State a b $ (End)
0 Shift to I1 Shift to I2
1 Shift to I1 Reduce by A → aA
2 Reduce by A → b
3 Accept
The Goto table is used when a non-terminal is at the top of the stack:
State A
0 I3
If a shift is chosen, push the next input symbol onto the stack and transition to the
appropriate state.
If a reduce is chosen, apply the corresponding production to the stack, pop the appropriate
number of symbols, and push the left-hand side of the production.
The parsing continues until the stack contains only the start symbol and the input is
consumed, signaling a successful parse.
Deterministic: The parser has a clear decision to make for each state and symbol without
ambiguity.
Efficient: The parsing process can be done in linear time, which is crucial for real-time
applications like compilers.
Limited Grammar Coverage: LR(0) parsers can only handle a limited subset of context-free
grammars. They can't handle some ambiguous or complex grammars that require more
lookahead (like LR(1) or LALR parsers).
Cannot handle left recursion: LR(0) parsers, like many other LL-type parsers, cannot parse
grammars with left recursion.
Conclusion
An LR(0) parser is a bottom-up parser that uses a deterministic finite state machine and a parsing
table to process input based solely on the current symbol. It is efficient for simple grammars but has
limited applicability for more complex languages that require more lookahead or handle ambiguity. It
is widely used for building fast, reliable parsers for many programming languages in compiler
construction.