IT603(A) • Compiler Design • Unit II

Syntax Analysis and LR Parsing

Complete RGPV exam-oriented notes on parser working, top-down and bottom-up methods, predictive parsing, operator precedence, SLR, CLR, LALR and parsing table construction.

Start Unit 2 Notes

1. Working of Parser 14 Marks

Parser: A parser is the syntax-analysis component of a compiler that receives tokens from the lexical analyzer, checks them against the grammar and constructs a parse tree or syntax tree.

Position of Parser

Source Program | Lexical Analyzer | Tokens v +-------------+ | PARSER | <---- Grammar +-------------+ | Parse Tree / Syntax Tree | Semantic Analysis Parser also uses Symbol Table and Error Handler.

Main Functions

  • Accept tokens from lexical analyzer.
  • Check grammatical correctness.
  • Construct parse tree or syntax tree.
  • Report syntax errors.
  • Recover from errors where possible.
  • Support semantic-action execution.

Parser Components

  • Input buffer: contains token sequence.
  • Parsing stack: stores grammar symbols or states.
  • Parsing table: determines parsing action.
  • Driver program: controls stack, input and actions.

Types of Parsers

TypeConstruction DirectionExamples
Top-downRoot to leavesRecursive descent, predictive parser
Bottom-upLeaves to rootOperator precedence, LR parser
Conclusion: The parser verifies the syntactic structure of token sequences and provides a structured representation for later compiler phases.

2. Top-Down Parsing 14 Marks

Top-down parsing begins with the start symbol and repeatedly expands non-terminals to construct a parse tree from root to leaves.

Basic Idea

The parser attempts to find a leftmost derivation of the input string. It chooses productions and predicts which production can generate the current input.

Start Symbol | Select Production | Expand Non-terminal | Match Input Tokens | Accept or Report Error

Types

  • Backtracking parser
  • Recursive-descent parser
  • Predictive parser
  • LL(1) parser

Problems

Left Recursion

A grammar such as E → E + T | T causes infinite recursion in top-down parsing.

Removal:
Original: A → Aα | β After removal: A → βA' A' → αA' | ε

Left Factoring

Left factoring is needed when alternatives have a common prefix.

Original: A → αβ1 | αβ2 Left factored: A → αA' A' → β1 | β2

Advantages

  • Easy to understand and implement.
  • Parse tree is constructed naturally.
  • Suitable for hand-written parsers.

Limitations

  • Cannot directly handle left-recursive grammar.
  • May require left factoring.
  • Less powerful than LR methods.

3. Recursive-Descent Parsing 14 Marks

Recursive-descent parsing uses a set of recursive procedures, normally one procedure for each non-terminal.

Example Grammar

E → T E' E' → + T E' | ε T → id

Procedure Outline

procedure E() { T(); EPrime(); } procedure EPrime() { if lookahead == '+' { match('+'); T(); EPrime(); } } procedure T() { match(id); }

Working

  1. Call the procedure for the start symbol.
  2. Each procedure checks the current lookahead token.
  3. Terminals are matched directly.
  4. Non-terminals invoke other procedures.
  5. Success occurs when complete input is matched.

Backtracking

If the parser tries one production and later fails, it may return to the earlier input position and try another alternative. Predictive parsing avoids this costly backtracking.

Advantages

  • Simple program structure
  • Easy semantic-action integration
  • Readable and maintainable

Limitations

  • Backtracking may be inefficient.
  • Grammar transformation may be required.
  • Not suitable for left-recursive grammar.

4. Predictive Parsing 14 Marks

A predictive parser is a non-backtracking top-down parser that selects a production using the current non-terminal and one or more lookahead tokens.

LL(1) Meaning

  • First L: scans input from Left to right.
  • Second L: produces a Leftmost derivation.
  • 1: uses one lookahead token.

Architecture

Parsing Table M | Input Buffer ---> Driver Program <--- Stack | Output / Error

Algorithm

  1. Push $ and start symbol onto stack.
  2. Compare stack top X with input symbol a.
  3. If X is a terminal and X = a, pop and advance input.
  4. If X is a non-terminal, use M[X,a].
  5. Replace X by the right side of selected production.
  6. If both stack and input contain $, accept.
  7. If table entry is empty, report error.

Conditions for LL(1)

  • No left recursion
  • Grammar should be left factored
  • FIRST sets of alternatives must be disjoint
  • If ε is possible, FIRST and FOLLOW conditions must hold

5. FIRST and FOLLOW Sets 14 Marks

FIRST(α) is the set of terminals that can begin strings derived from α. FOLLOW(A) is the set of terminals that can appear immediately after non-terminal A.

Rules for FIRST

  1. If X is terminal, FIRST(X) = {X}.
  2. If X → ε, include ε.
  3. For X → Y1Y2..., include FIRST(Y1) except ε; continue if Yi can derive ε.

Rules for FOLLOW

  1. Place $ in FOLLOW(S), where S is start symbol.
  2. For A → αBβ, add FIRST(β) except ε to FOLLOW(B).
  3. If β derives ε or B is at end, add FOLLOW(A) to FOLLOW(B).

Example

Grammar: E → T E' E' → + T E' | ε T → id FIRST(E) = { id } FIRST(E') = { +, ε } FIRST(T) = { id } FOLLOW(E) = { $ } FOLLOW(E') = { $ } FOLLOW(T) = { +, $ }

Uses

  • LL(1) parsing table construction
  • Grammar analysis
  • Error recovery
  • Production selection

6. Construction of Predictive Parsing Table 14 Marks

Construction Rules

  1. For each production A → α, place it in M[A,a] for every a in FIRST(α).
  2. If ε belongs to FIRST(α), place A → α in M[A,b] for every b in FOLLOW(A).
  3. All remaining entries are errors.

Example Grammar

E → T E' E' → + T E' | ε T → id
Non-terminalid+$
EE → T E'ErrorError
E'ErrorE' → + T E'E' → ε
TT → idErrorError

Parsing id + id

Stack Input Action $ E id+id$ E → T E' $ E' T id+id$ T → id $ E' id id+id$ Match id $ E' +id$ E' → + T E' $ E' T + +id$ Match + $ E' T id$ T → id $ E' id id$ Match id $ E' $ E' → ε $ $ Accept

7. Bottom-Up Parsing 14 Marks

Bottom-up parsing constructs a parse tree from leaves to root by reducing substrings of input to grammar non-terminals.

Basic Idea

It performs the reverse of a rightmost derivation. Such a reverse derivation is called a rightmost derivation in reverse.

Input String | Find Handle | Reduce Handle | Repeat Reduction | Start Symbol

Handle

A handle is a substring that matches the right side of a production and whose reduction represents one step in the reverse rightmost derivation.

Types

  • Shift-reduce parsing
  • Operator precedence parsing
  • LR parsing

Advantages

  • Handles a larger class of grammars.
  • Can handle left recursion.
  • Detects errors as soon as possible in viable-prefix sense.

Limitations

  • More complex construction.
  • Parsing tables may be large.
  • Manual design is difficult.

8. Shift-Reduce Parsing 14 Marks

Shift-reduce parsing uses a stack and input buffer and performs shift, reduce, accept and error actions.

Actions

  • Shift: move next input symbol onto stack.
  • Reduce: replace a handle by the left-side non-terminal.
  • Accept: successful parsing.
  • Error: invalid input.

Example

Grammar: E → E + id | id Input: id + id Stack Input Action $ id+id$ Shift id $id +id$ Reduce id to E $E +id$ Shift + $E+ id$ Shift id $E+id $ Reduce E+id to E $E $ Accept

Conflicts

  • Shift-reduce conflict: parser cannot decide whether to shift or reduce.
  • Reduce-reduce conflict: parser cannot decide which production to reduce.

9. Operator Precedence Parsing 14 Marks

Operator precedence parsing is a bottom-up method that uses precedence relations between terminals to identify handles.

Operator Grammar Conditions

  • No ε-production.
  • No two adjacent non-terminals on the right side.

Precedence Relations

  • a ā‹– b: a yields precedence to b
  • a ≐ b: a has equal precedence with b
  • a ā‹— b: a takes precedence over b

Basic Working

  1. Compare topmost terminal on stack with current input symbol.
  2. If stack terminal yields or equals precedence, shift.
  3. If stack terminal takes precedence, reduce.
  4. Accept when stack contains $S and input contains $.

Example Precedence

+*id$
+ā‹—ā‹–ā‹–ā‹—
*ā‹—ā‹—ā‹–ā‹—
idā‹—ā‹—Errorā‹—
$ā‹–ā‹–ā‹–Accept

Advantages

  • Simple for expression grammars.
  • Efficient table-driven method.
  • Directly handles precedence and associativity.

Limitations

  • Works only for operator grammars.
  • Cannot parse all context-free grammars.
  • Error detection is weaker than LR parsers.

10. LR Parser 14 Marks

An LR parser scans input from left to right and constructs a rightmost derivation in reverse.

LR Parser Structure

Input Buffer ----+ | v LR Driver ^ | State Stack --->| | ACTION and GOTO Table

ACTION Table

  • Shift sj
  • Reduce A → β
  • Accept
  • Error

GOTO Table

GOTO[state, non-terminal] specifies the next state after a reduction.

LR Item

An LR item is a production with a dot showing how much of the production has been recognized.

A → X • Y X has been recognized. Y is expected next.

Advantages

  • Very powerful deterministic parsing method.
  • Handles left-recursive grammar.
  • Detects syntax errors early.
  • No grammar transformation is generally required.

Types

  • SLR(1)
  • Canonical LR(1)
  • LALR(1)

11. SLR Parser and Table Construction 14 Marks

SLR uses LR(0) item sets and FOLLOW sets to construct reduce actions.

Construction Steps

  1. Augment grammar using S' → S.
  2. Construct LR(0) items using closure and goto.
  3. Create canonical collection of item sets.
  4. For A → α•aβ, enter shift action to goto state.
  5. For A → α•, enter reduction for terminals in FOLLOW(A).
  6. For S' → S•, enter accept on $.
  7. Fill GOTO entries for non-terminals.

Closure Operation

If I contains A → α • B β, add B → • γ for every production B → γ. Repeat until no new item can be added.

Goto Operation

GOTO(I, X) = closure of all items obtained by moving dot past grammar symbol X in items of I.

Advantages

  • Smaller tables than CLR.
  • Easy to construct compared with CLR.
  • More powerful than LL(1) for many grammars.

Limitation

Some LR grammars are not SLR because FOLLOW sets may create conflicts.

12. Canonical LR Parser and Table Construction 14 Marks

Canonical LR uses LR(1) items containing both a dotted production and a lookahead terminal.

LR(1) Item

[A → α • β, a] a is the lookahead terminal used when β becomes empty.

Construction Steps

  1. Augment the grammar.
  2. Construct closure of LR(1) item sets.
  3. Compute goto transitions.
  4. Create canonical LR(1) collection.
  5. Add shifts for terminal transitions.
  6. Add reductions only on the item's specific lookahead.
  7. Add accept for [S' → S•, $].

Why CLR Is More Powerful

SLR uses all terminals in FOLLOW(A), while CLR uses exact lookahead information attached to each item. Therefore unnecessary reductions and conflicts are avoided.

Advantages

  • Most powerful standard LR method.
  • Very precise lookahead handling.
  • Accepts the largest grammar class among SLR, LALR and CLR.

Limitations

  • Very large number of states.
  • Large parsing table.
  • Construction is complex.

13. LALR Parser and Table Construction 14 Marks

LALR is constructed by merging Canonical LR states that have the same LR(0) core while combining their lookaheads.

Construction Steps

  1. Construct Canonical LR(1) item sets.
  2. Identify states having identical LR(0) cores.
  3. Merge these states.
  4. Combine lookahead symbols of corresponding items.
  5. Construct ACTION and GOTO tables from merged states.
State I: [A → α •, a] State J: [A → α •, b] Same core after merging: [A → α •, a/b]

Advantages

  • Table size close to SLR.
  • Power close to CLR.
  • Widely used by parser generators such as YACC.

Limitation

Merging states can introduce reduce-reduce conflicts that were absent in the CLR parser.

14. Comparison of SLR, CLR and LALR 14 Marks

FeatureSLRCLRLALR
Items usedLR(0)LR(1)Merged LR(1)
Reduce lookaheadFOLLOW setExact item lookaheadMerged lookahead
PowerLowestHighestBetween SLR and CLR
Table sizeSmallVery largeSmall
ConstructionSimpleComplexModerate
Typical useTeaching, simple grammarsPowerful theoretical parserPractical compiler tools
Remember: SLR is simple, CLR is most powerful, and LALR gives a practical balance between table size and parsing power.

15. Using Ambiguous Grammars 14 Marks

A grammar is ambiguous if one sentence has more than one parse tree or more than one leftmost/rightmost derivation.

Expression Grammar

E → E + E | E * E | id

The input id + id * id has two parse trees because the grammar does not define precedence.

Resolution Methods

  • Rewrite grammar to encode precedence.
  • Rewrite grammar to encode associativity.
  • Use precedence declarations in parser generators.
  • Resolve dangling-else conflict using a rule such as matching else with nearest unmatched if.

Why Ambiguous Grammar May Still Be Used

An ambiguous grammar can be shorter and more natural. Parser generators may permit it when conflicts are resolved using explicit precedence and associativity declarations.

Advantages

  • Compact grammar
  • Readable expression rules
  • Convenient with parser-generator directives

Risk

Unresolved ambiguity creates shift-reduce or reduce-reduce conflicts and may generate unintended parse trees.

16. Automatic Parser Generator 14 Marks

An automatic parser generator produces parser source code and parsing tables from a grammar specification and semantic actions.

General Architecture

Grammar + Semantic Actions | Parser Generator | Parser Source + Tables | Language Compiler

YACC Workflow

  1. Declare tokens and precedence.
  2. Write grammar productions.
  3. Attach semantic actions.
  4. Run YACC to generate parser source.
  5. Compile generated parser with lexical analyzer.

Benefits

  • Reduces development time.
  • Automatically creates complex tables.
  • Reports grammar conflicts.
  • Supports semantic actions and error handling.
  • Easy grammar modification.

Limitations

  • Generated code may be difficult to debug.
  • Grammar conflicts require expert understanding.
  • Tool-specific declarations reduce portability.

Unit 2 Quick Revision

  • The parser checks syntax and constructs a parse tree.
  • Top-down parsing produces a leftmost derivation.
  • Bottom-up parsing produces a rightmost derivation in reverse.
  • Predictive parsers use FIRST and FOLLOW sets.
  • Shift-reduce parsing uses shift, reduce, accept and error actions.
  • Operator precedence parsing is suitable for expression grammars.
  • SLR uses LR(0) items and FOLLOW sets.
  • CLR uses LR(1) items with exact lookahead.
  • LALR merges CLR states having the same core.
  • Parser generators automate table and parser construction.

Important RGPV Exam Questions

Long Answer Questions

  1. Explain the working and role of a parser.
  2. Explain top-down parsing and problems of left recursion and left factoring.
  3. Explain recursive-descent parsing with an example.
  4. Explain predictive parsing and the LL(1) algorithm.
  5. Compute FIRST and FOLLOW sets for a grammar.
  6. Construct a predictive parsing table and parse an input string.
  7. Explain bottom-up and shift-reduce parsing.
  8. Explain operator precedence parsing.
  9. Explain LR parser architecture and actions.
  10. Construct SLR parsing table for a grammar.
  11. Explain Canonical LR parser construction.
  12. Explain LALR table construction.
  13. Compare SLR, CLR and LALR parsers.
  14. Explain ambiguous grammars and conflict resolution.
  15. Explain automatic parser generators.

Short Answer Questions

  1. Define parser.
  2. What is left recursion?
  3. What is left factoring?
  4. Define FIRST and FOLLOW.
  5. What is a handle?
  6. Define viable prefix.
  7. What is an LR item?
  8. What is a shift-reduce conflict?
  9. Expand SLR, CLR and LALR.
  10. What is an ambiguous grammar?
Exam Strategy: For parser questions, always include grammar, item sets or table, parsing algorithm, one worked example and a final comparison or conclusion.

Download Study Resources

Unit 2 PDF

Printable detailed notes will be uploaded soon.

Coming Soon

Parsing Questions

Practice grammars and tables will be available soon.

Coming Soon

PYQ Analysis

Repeated Unit 2 questions will be added soon.

Coming Soon

Frequently Asked Questions

Syntax analysis checks whether the token stream follows the grammar of the programming language.
Bottom-up parsers such as LR parsers can handle left-recursive grammars.
Canonical LR is the most powerful among SLR, CLR and LALR.
LALR provides compact tables with parsing power close to CLR, making it practical for compiler tools.
It is a grammar that can be parsed from left to right using a leftmost derivation and one lookahead token without conflict.