Download presentation
Presentation is loading. Please wait.
1
Bottom-Up Parsing “Shift-Reduce” Parsing
Reduce a string to the start symbol of the grammar. At every step a particular substring is matched (in left-to-right fashion) to the right side of some production and then it is substituted by the non-terminal in the left hand side of the production. abbcde aAbcde aAde aABe S 3 Consider: S aABe A Abc | b B d 1 2 4 2-3 1 4 Rightmost Derivation: S aABe aAde aAbcde abbcde 1 4 2 3 rm rm rm rm
2
Handles Handle of a string = substring that matches the RHS of some production AND whose reduction to the non-terminal on the LHS is a step along the reverse of some rightmost derivation. Formally: A phrase is a substring of a sentential form derived from exactly one Non-terminal A simple phrase is a phrase created in one step handle is a simple phrase of a right sentential form i.e. A is a handle of x, where x is a string of terminals, if: S => Ax => x A certain sentential form may have many different handles. Right sentential forms of a non-ambiguous grammar have one unique handle [but many substrings that look like handles potentially !]. * rm rm
3
Example Consider: S aABe A Abc | b B d
S aABe aAde aAbcde abbcde rm rm rm rm It follows that: (S ) aABe is a handle of aABe (B ) d is a handle of aAde (A ) Abc is a handle of aAbcde (A ) b is a handle of abbcde
4
Example, II Grammar: S aABe A Abc | b B d
Consider aAbcde (it is a right sentential form) Is [A b, aAbcde] a handle? if it is then there must be: S rm … rm aAAbcde rm aAbcde no way ever to get two consecutive A’s in this grammar. => Impossible
5
Example, III Grammar: S aABe A Abc | b B d
Consider aAbcde (it is a right sentential form) Is [B d, aAbcde] a handle? if it is then there must be: S rm … rm aAbcBe rm aAbcde we try to obtain aAbcBe not a right sentential form S rm aABe ?? aAbcBe
6
Shift Reduce Parsing with a Stack
The “big” problem : given the sentential form locate the handle General Idea for S-R parsing using a stack: “shift” input symbols into the stack until a handle is found on top of it. “reduce” the handle to the corresponding non-terminal. “accept” when the input is consumed and only the start symbol is on the stack. “error” call the error handler Viable prefix: prefix of a right sentential form that appears on the stack of a Shift-Reduce parser.
7
What happens with ambiguous grammars
Consider: E E + E | E * E | | ( E ) | id Derive id+id*id By two different Rightmost derivations
8
Example E E + E | E * E | ( E ) | id STACK INPUT Remark $ $ id $ E
id + id * id$ + id * id$ id * id$ * id$ Shift Reduce by E id Shift Shift Reduce by E id Both reduce by E E + E, and Shift can be performed: Shift/reduce conflict
9
Conflicts Conflicts [appear in ambiguous grammars]
either “shift/reduce” or “reduce/reduce” Another Example: stmt if expr then stmt | if expr then stmt else stmt | other (any other statement) Stack Input if … then else … Shift/ Reduce conflict
10
More Conflicts stmt id ( parameter-list ) stmt expr := expr
parameter-list parameter-list , parameter | parameter parameter id expr-list expr-list , expr | expr expr id | id ( expr-list ) Consider the string A(I,J) Corresponding token stream is id(id, id) After three shifts: Stack = id(id Input = , id) Reduce/Reduce Conflict … what to do? (it really depends on what is A, an array? or a procedure?
11
Removing Conflicts One way is to manipulate grammar.
cf. what we did in the top-down approach to transform a grammar so that it is LL(1). Nevertheless: We will see that shift/reduce and reduce/reduce conflicts can be best dealt with after they are discovered. This simplifies the design.
12
Operator-Precedence Parsing
problems encountered so far in shift/reduce parsing: IDENTIFY a handle. resolve conflicts (if they occur). operator grammars: a class of grammars where handle identification and conflict resolution is easy. Operator Grammars: no production right side is or has two adjacent non-terminals. note: this is typically ambiguous grammar. E E - E | E + E | E * E | E / E | E ^ E | - E | ( E ) | id
13
Basic Technique For the terminals of the grammar, define the relations <. .> and .=. a <. b means that a yields precedence to b a .=. b means that a has the same precedence as b. a .> b means hat a takes precedence over b E.g. * .> + or + <. * Many handles are possible. We will use <. .=. And .> to find the correct handle (i.e., the one that respects the precedence).
14
Using Operator-Precedence Relations
GOAL: delimit the handle of a right sentential form <. will mark the beginning, .> will mark the end and .=. will be in between. Since no two adjacent non-terminals appear in the RHS of any production, the general form sentential forms is as: 0 a1 1 a2 2 … an n, where each i is either a nonterminal or the empty string. At each step of the parse, the parser considers the top most terminal of the parse stack (i.e., either top or top-1), say a, and the current token, say b, and looks up their precedence relation, and decides what to do next:
15
Operator-Precedence Parsing
If a .=. b, then shift b into the parse stack If a <. b, then shift <. And then shift b into the parse stack If a .> b, then find the top most <. relation of the parse stack; the string between this relation (with the non-terminal underneath, if there exists) and the top of the parse stack is the handle (the handle should match (weakly) with the RHS of at least one grammar rule); replace the handle with a typical non-terminal
16
Example STACK INPUT Remark $ $ <. id $ E $ E <. +
$ E <. + <. id $ E <. + E $ E <. + E <. * $ E <. + E <. * <. id $ E <. + E <. * E id + id * id$ + id * id$ id * id$ * id$ id$ $ $ <. id id >. + $ <. + + <. id id .> * + <. * * <. id id .> $ * .> $ + .> $ accept * ( ) id $ .> <. <. .> <. .> .> .> <. .> <. .> <. <. <. .=. <. .> .> > > <. <. < <. .=. + * ( ) id $ Parse Table 1-2 E E + T | T 3-4 T T * F | F 5-6 T ( E ) | id
17
Producing the parse table
FirstTerm(A) = {a | A + a or A + Ba} LastTerm(A) = {a | A + a or A + aB} a .=. b iff U ab or U aBb a <. b iff U aB and b FirsTerm(B) a .> b iff U Bb and a LastTerm(B)
18
Example: FirstTerm (E) = {+, *, id, (} FirstTerm (T) = {*, id, (}
FirstTerm (F) = {id, (} LastTerm (E) = {+, *, id, )} LastTerm (T) = {*, id, )} LastTerm (F) = {id, )} 1-2 E E + T | T 3-4 T T * F | F 5-6 F ( E ) | id
19
Precedence Functions vs Relations
f(a) < g(b) whenever a <. b f(a) = g(b) whenever a .=. b f(a) > g(b) whenever a .> b * / ( ) id $ f g
20
Constructing precedence functions
g id f id f * g * g + f $ f + g $ + * id $ f g
21
Handling Errors During Reductions
Suppose abEc is poped and there is no production right hand side that matches abEc If there were a rhs aEc, we might issue message illegal b on line x If the rhs is abEdc, we might issue message missing d on line x If the found rhs is abc, the error message could be illegal E on line x, where E stands for an appropriate syntactic category represented by non-terminal E
22
Handling shift/reduce errors
e1: /* called when whole expression is missing */ insert id onto the input print “missing operand e2: /* called when expression begins with a right parenthesis */ delete ) from the input print “unbalanced right parenthesis” e3”: /* called when id or ) is followed by id or ( */ insert + onto the input print “missing operator e4: /* called when expression ends with a left parenthesis */ pop ( from the stack print “missing right parenthesis” id ( ) $ e3 e > .> <.. <. .=. e4 e3 e > .> <. <. e2 e1 id ( ) $
23
Extracting Precedence relations from parse tables
+ <. * E + T T * F id * <. id 1-2 E E + T | T 3-4 T T * F | F 5-6 T ( E ) | id
24
Extracting Precedence relations from parse tables
* F * .> * T * F 1-2 E E + T | T 3-4 T T * F | F 5-6 T ( E ) | id F id .> * id
25
Pros and Cons + simple implementation + small parse table
- weak (too restrictive for not allowing two adjacent non-terminals - not very accurate (some syntax errors are not detected due weak treatment of non-terminals) Simple precedence parsing is an improved form of operator precedence that doesn’t have these weaknesses 25
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.