Lecture 7
Lecture 7
Parsing
1. S → SS | a | b
2. E→E+E|a
3. S → ε | Sa | Sb
4. E’ → -E’ | n | (E)
E → E’ | E’ + E
Question
Which of the following grammars are ambiguous?
1. S → SS | a | b
2. E→E+E|a
3. S → Sa | Sb
4. E’ → -E’ | n | (E)
E → E’ | E’ + E
Removing Ambiguity
S → if E then S
| if E then S’ else S
S’ → if E then S’ else S’
E1 if S2 E1 if
E2 S1 E2 S1 S2
Removing Ambiguity
CFG : Str : id * id + id
E → id | E + E | E * E
CFG’ :
E’ → E’ + E | E
E → id | E * (E’) | (E’) * E
Removing Ambiguity
● No standard approaches
● Cannot convert the grammar automatically
● Can sometimes be useful
● Can use precedence and associativity to remove ambiguity
precedence left ADD, SUBTRACT; // less precedence
precedence left TIMES, DIVIDE; // more precedence
Multiple Parse Trees
E + E E + E
id id
E + E E + E
id id id id
Multiple Parse Trees
E * E E + E
id id
E + E E * E
id id id id
Abstract Syntax Trees
● Data structure that represents the parse tree for the compiler
○ Ignores some detail in the parse tree
Abstract Syntax Trees
CFG:
E → E * E | E + E | (E) | int
Str:
5 * (2 + 3)
Tokens:
<NUMBER, 5>;<MUL, *>;<OPAREN, (>;
<NUMBER, 2>;<PLUS, +>;<NUMBER, 3>;<CPAREN, )>;
Abstract Syntax Trees
E * E
int, 5 E
( )
E + E
int, 2 int, 3
Abstract Syntax Trees
Times
E
int, 5 Plus
E * E
int, 5 E
( ) int, 2 int, 3
E + E
int, 2 int, 3
Recursive Descent Parsing
● Top-down parsing approach
○ Start at the top when constructing parse tree
○ Grows from left to right
○ Start with the start-symbol and try the rules in order
● Consider the CFG:
E→T|E+T
T → int | (E)
● String: (5)
Recursive Descent Parsing
E
CFG:
E→T|E+T
T → int | (E) T
String: (5) E
( )
T
Recursive Descent Parsing
E
CFG:
E→T|E+T
T → int | (E) T
String: (5) E
( )
int
Recursive Descent Parsing
● Easy to implement
● Cannot backtrack once a production is successful
○ Works when only one production succeeds for a non-terminal
● Does not work for left-recursive grammars
S → Sa | b
Recursive Descent Parsing
● Easy to implement
● Cannot backtrack once a production is successful
○ Works when only one production succeeds for a non-terminal
● Does not work for left-recursive grammars
S → Sa | b
● Eliminate left-recursive
Eliminate Left Recursion
Suppose we have a left-recursive grammar:
S → Sa | b
Left-to-right Lookahead
scanning of input k tokens
Leftmost
derivation
LL(1) Parser
● Looks ahead 1 token
● Only one choice of production at every step
○ Unique production or no production given the next token
● No backtracking
E→T+E|T
T → int | int * T | (E)
LL(1) Parser - Left factoring
E→T+E|T
T → int | int * T | (E)
T → int B | (E)
B→*T|ε
LL(1) Parser - Example
S → if E then S
| if E then S else S
S → if E then S S’
S’ → ε | else S