0% found this document useful (0 votes)
11 views

Lecture 8

Uploaded by

mohdarman01072
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Lecture 8

Uploaded by

mohdarman01072
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Bottom-Up Parsing

„ Bottom-up parsing is more general than


top-down parsing
„ Just as efficient
„ Builds on ideas in top-down parsing

„ Bottom-up is the preferred method in


practice

„ Reading: Section 4.5

An Introductory Example
„ Bottom-up parsers don’t need left-
factored grammars

„ Hence we can revert to the “natural”


grammar for our example:
E→T+E|T
T → int * T | int | (E)

„ Consider the string: int * int + int

1
The Idea
Bottom-up parsing reduces a string to the
start symbol by inverting productions:

int * int + int T → int


int * T + int T → int * T
T + int T → int
T+T E→T
T+E E→T+E
E

Observation
„ Read productions from bottom-up parse
in reverse (i.e., from bottom to top)
„ This is a rightmost derivation!
int * int + int T → int
int * T + int T → int * T
T + int T → int
T+T E→T
T+E E→T+E
E

2
A Bottom-up Parse
E
int * int + int
int * T + int
T E
T + int
T+T
T T
T+E
E
int * int + int
A bottom-up parser traces a rightmost
derivation in reverse!

Bottom-up Parse in Detail


int * (int + int) + int

3
Trivial Bottom-Up Parsing
Algorithm
Let I = input string
repeat
pick a non-empty substring β of I
where X→ β is a production
if no such β, backtrack
replace one β by X in I
until I = “S” (the start symbol) or
all possibilities are exhausted

Questions
„ Does this algorithm terminate?

„ How fast is the algorithm?

„ Does the algorithm handle all cases?

„ How do we choose the substring to


reduce at each step?

4
Where Do Reductions Happen
Important Fact #1 has an interesting
consequence:
„ Let αβω be a step of a bottom-up parse
„ Assume the next reduction is by X→ β
„ Then ω is a string of terminals

Why? Because αXω → αβω is a step in a


right-most derivation

Notation
„ Idea: Split string into two substrings
„ Right substring is as yet unexamined by parsing
(a string of terminals)
„ Left substring has terminals and non-terminals

„ The dividing point is marked by a |


„ The | is not part of the string

„ Initially, all input is unexamined |x1x2 . . . xn

5
Shift-Reduce Parsing
Bottom-up parsing uses two kinds of
actions:

Shift

Reduce

Shift
„ Shift: Move | one place to the right
„ Shifts a terminal to the left string

ABC|xyz ⇒ ABCx|yz

6
Reduce
„ Apply an inverse production at the right
end of the left string
„ If A → xy is a production, then

Cbxy|ijk ⇒ CbA|ijk

Example with Reductions Only


|int * int + int shift
int | * int + int shift
int * | int + int shift
int * int | + int reduce T → int
int * T | + int reduce T → int * T
T | + int shift
T + | int shift
T + int | reduce T → int
T+T| reduce E→T
T+E| reduce E→T+E
E|

7
The Example with Shift-
Reduce Parsing
|int * int + int shift
int | * int + int shift
int * | int + int shift
int * int | + int reduce T → int
int * T | + int reduce T → int * T
T | + int shift
T + | int shift
T + int | reduce T → int
T+T| reduce E→T
T+E| reduce E→T+E
E|

Shift-Reduce Parse in Detail


int * (int + int) + int

8
The Stack
„ Left string can be implemented by a stack
„ Top of the stack is the |

„ Shift pushes a terminal on the stack

„ Reduce pops 0 or more symbols off of the


stack (production rhs) and pushes a non-
terminal on the stack (production lhs)

Key Issue (will be resolved by


algorithms)
„ How do we decide when to shift or
reduce?
„ Consider step int | * int + int
„ We could reduce by T → int giving T | * int
+ int
„ A fatal mistake: No way to reduce to the
start symbol E

9
Conflicts
„ Generic shift-reduce strategy:
„ If there is a handle on top of the stack, reduce
„ Otherwise, shift

„ But what if there is a choice?


„ If it is legal to shift or reduce, there is a
shift-reduce conflict
„ If it is legal to reduce by two different
productions, there is a reduce-reduce conflict

Source of Conflicts
„ Ambiguous grammars always cause
conflicts

„ But beware, so do many non-


ambiguous grammars

10
Conflict Example
Consider our favorite ambiguous
grammar:

E → E+E

| E*E

| (E)

| int

One Shift-Reduce Parse


| int * int + int shift
... ...
E * E | + int reduce E → E * E
E | + int shift
E + | int shift
E + int | reduce E → int
E+E| reduce E → E + E
E|

11
Another Shift-Reduce Parse
| int * int + int shift
... ...
E * E | + int shift
E * E + | int shift
E * E + int | reduce E → int
E*E+E| reduce E → E + E
E*E| reduce E → E * E
E|

Example Notes
„ In the second step E * E | + int we can either
shift or reduce by E → E * E

„ Choice determines associativity of + and *

„ As noted previously, grammar can be


rewritten to enforce precedence
„ Precedence declarations are an alternative

12
Precedence Declarations
Revisited
„ Precedence declarations cause shift-reduce
parsers to resolve conflicts in certain ways

„ Declaring “* has greater precedence than +”


causes parser to reduce at E * E | + int

„ More precisely, precedence declaration is


used to resolve conflict between reducing a *
and shifting a +

Precedence Declarations
Revisited (Cont.)
„ The term “precedence declaration” is
misleading

„ These declarations do not define


precedence; they define conflict
resolutions
„ Not quite the same thing!

13

You might also like