Lecture 06
Lecture 06
Syntax-Directed Translation
Recursive Descent Parsing
CS143
Lecture 6
2
Outline
3
Error Handling
4
Syntax Error Handling
5
Syntax Error Recovery
6
Error Recovery: Panic Mode
7
Error Recovery: Panic Mode (Cont.)
8
Error Recovery: Error Productions
• Example:
– Write 5 x instead of 5 * x
– Add the production E → … | E E
• Disadvantage
– Complicates the grammar
9
Error Recovery: Local and Global Correction
• Disadvantages:
– Hard to implement
– Slows down parsing of correct programs
– “Nearby” is not necessarily “the intended” program
– Not supported by most tools
10
Syntax Error Recovery: Past and Present
• Past
– Slow recompilation cycle (even once a day)
– Find as many errors in one cycle as possible
– Researchers could not let go of the topic
• Present
– Quick recompilation cycle
– Users tend to correct one error/cycle
– Complex error recovery is less compelling
– Panic-mode seems enough
11
Abstract Syntax Trees
12
Abstract Syntax Trees (Cont.)
13
Example of Parse Tree
E
• Traces the operation of
E + E the parser
int2 int3
14
Example of Abstract Syntax Tree
PLUS
PLUS
5 2 3
16
Semantic Actions: Example
17
Semantic Actions: Example (Cont.)
• String: 5 + (2 + 3)
• Tokens: int5 ‘+’ ‘(‘ int2 ‘+’ int3 ‘)’
Productions Equations
E → E1 + E2 E.val = E1.val + E2.val
E1 → int5 E1.val = int5.val = 5
E2 → (E3) E2.val = E3.val
E3 → E4 + E5 E3.val = E4.val + E5.val
E4 → int2 E4.val = int2.val = 2
E5 → int3 E5.val = int3.val = 3
18
Semantic Actions: Notes
• Declarative Style
– Order of resolution is not specified
– The parser figures it out
• Imperative Style
– The order of evaluation is fixed
– Important if the actions manipulate global state
19
Semantic Actions: Notes
• Example:
E3.val = E4.val + E5.val
– Must compute E4.val and E5.val before E3.val
– We say that E3.val depends on E4.val and E5.val
20
Dependency Graph
E4 +
E5
int2 2 int3 3
21
Evaluating Attributes
22
Dependency Graph
E 10
E1 5 + E2 5
int5 5 ( E3 5 )
E4 2 + 3
E5
int2 2 int3 3
23
Semantic Actions: Notes (Cont.)
• Synthesized attributes
– Calculated from attributes of descendents in the parse
tree
– E.val is a synthesized attribute
– Can always be calculated in a bottom-up order
24
Semantic Actions: Notes (Cont.)
25
Constructing an AST
mkleaf(n) = n
PLUS
mkplus( , ) =
T1 T2 T1 T2
26
Constructing an AST
27
Abstract Syntax Tree Example
• Consider the string int5 ‘+’ ‘(‘ int2 ‘+’ int3 ‘)’
• A bottom-up evaluation of the ast attribute:
E.ast = mkplus(mkleaf(5),
mkplus(mkleaf(2), mkleaf(3))
PLUS
PLUS
5 2 3
28
Summary
29
Intro to Top-Down Parsing: The Idea
30
Recursive Descent Parsing
31
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( int5 )
32
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( int5 )
33
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( int5 )
34
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( int5 )
35
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( int5 )
36
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( int5 )
37
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
T
Match! Advance input.
( E )
( int5 )
38
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( E )
( int5 )
39
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
( E )
( int5 ) T
40
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
T
Match! Advance input.
( E )
( int5 ) T
int 41
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
T
Match! Advance input.
( E )
( int5 ) T
int 42
Recursive Descent Parsing
E → T |T + E
T → int | int * T | ( E )
T
End of input, accept.
( E )
( int5 ) T
int 43
A Recursive Descent Parser: Preliminaries
44
A (Limited) Recursive Descent Parser (2)
45
A (Limited) Recursive Descent Parser (3)
• For production E → T
bool E1() { return T(); }
• For production E → T + E
bool E2() { return T() && term(PLUS) && E(); }
• For all productions of E (with backtracking)
bool E() {
TOKEN *save = next;
return (next = save, E1())
|| (next = save, E2()); }
46
A (Limited) Recursive Descent Parser (4)
bool T() {
TOKEN *save = next;
return (next = save, T1()
|| (next = save, T2())
|| (next = save, T3()); }
47
Recursive Descent Parsing. Notes.
48
Example
E→T|T+E ( int )
T → int | int * T | ( E )
49
When Recursive Descent Does Not Work
• Consider a production S → S a
bool S1() { return S() && term(a); }
bool S() { return S1(); }
50
Elimination of Left Recursion
51
More Elimination of Left-Recursion
• In general
S → S α1 | … | S αn | β1 | … | βm
• All strings derived from S start with one of
β1,…,βm and continue with several instances of
α1,…,αn
• Rewrite as
S → β1 S’ | … | βm S’
S’ → α1 S’ | … | αn S’ | ε
52
General Left Recursion
• The grammar
S→Aα|δ
A→Sβ
is also left-recursive because
S →+ S β α
53
Summary of Recursive Descent