Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Left recursion in LR(1) parsers

Can a LR(1) parser parse a grammar of this type?

S -> SA  | A
A -> aSb | ab

I'm trying to write a Java program that implements this type of parser, but I only get the right results on a grammars without left recursion.

like image 316
SegFault Avatar asked Jan 30 '14 16:01

SegFault


2 Answers

LR(1) parsers can handle some types of left recursion, though not all left-recursive grammars are LR(1).

Let's see if your particular grammar is LR(1). Augmenting the grammar gives

S' → S

S → SA | A

A → aSb | ab

Our configurating sets are therefore

 (1)
 S' -> .S    [$]     (Go to 2)
 S  -> .SA   [$a]    (Go to 2)
 S  -> .A    [$a]    (Go to 3)
 A  -> .aSb  [$a]    (Shift on a and go to 4)
 A  -> .ab   [$a]    (Shift on a and go to 4)

 (2)
 S' -> S.    [$]     (Accept on $)
 S  -> S.A   [$a]    (Go to 3)
 A  -> .aSb  [$a]    (Shift on a and go to 4)
 A  -> .ab   [$a]    (Shift on a and go to 4)

 (3)
 S  -> A.    [$a]    (reduce on $ or a)

 (4)
 A  -> a.Sb  [$a]    (Go to 6)
 A  -> a.b   [$a]    (Shift on b and go to 10)
 S  -> .SA   [ab]    (Go to 11)
 S  -> .A    [ab]    (Go to 12)
 A  -> .aSb  [ab]    (Shift on a and go to 8)
 A  -> .ab   [ab]    (Shift on a and go to 8)

 (5)
 A  -> ab.   [$a]    (Reduce on a or $)

 (6)
 A  -> aS.b  [$a]    (Shift on b and go to 7)
 S  -> S.A   [ab]    (Go to 13)
 A  -> .aSb  [ab]    (Shift on a and go to 8)
 A  -> .ab   [ab]    (Shift on a and go to 8)

 (7)
 A  -> aSb.  [$a]    (Reduce on a or $)

 (8)
 A  -> a.Sb  [ab]    (Go to 14)
 A  -> a.b   [ab]    (Shift on b and go to 16)
 S  -> .SA   [ab]    (Go to 11)
 S  -> .A    [ab]    (Go to 12)
 A  -> .aSb  [ab]    (Shift on a and go to 8)
 A  -> .ab   [ab]    (Shift on a and go to 8)

 (9)
 S  -> SA.   [$a]    (Reduce on a or $)

 (10)
 A  -> ab.   [$a]    (Reduce on a or b)

 (11)
 S  -> S.A   [ab]    (Go to 13)
 A  -> .aSb  [ab]    (Shift on a and go to 8)
 A  -> .ab   [ab]    (Shift on a and go to 8)

 (12)
 S  -> A.    [ab]    (Reduce on a or b)

 (13)
 S  -> SA.   [ab]    (Reduce on a or b)

 (14)
 A  -> aS.b  [ab]    (Shift on b and go to 15)
 S  -> S.A   [ab]    (Go to 13)
 A  -> .aSb  [ab]    (Shift on a and go to 8)
 A  -> .ab   [ab]    (Shift on a and go to 8)   

 (15)
 A  -> aSb.  [ab]    (Reduce on a or b)

 (16)
 A  -> ab.   [ab]    (Reduce on a or b)

There are no shift/reduce or reduce/reduce conflicts in this grammar, and so it should be LR(1) (unless I made a mistake somewhere!)

Hope this helps!

like image 50
templatetypedef Avatar answered Sep 22 '22 06:09

templatetypedef


Turns out it's also an SLR grammar, so LR is overkill. Instead of requiring 16 states with LR, only 10 states are needed with SLR.

(1)
 S' -> .S    S => (Go to 2)
 S  -> .SA   A => (Go to 3)
 S  -> .A    a => (Shift and go to 4)
 A  -> .aSb     
 A  -> .ab   

 (2)
 S' -> S.    $ => (Accept on $)
 S  -> S.A   A => (Go to 5)
 A  -> .aSb  a => (Shift and go to 6)
 A  -> .ab   

 (3)
 S  -> A.    [$b] => (reduce on $ or b)

 (4)
 A  -> a.Sb  S => (Go to 7)
 A  -> a.b   A => (Go to 9)
 S  -> .SA   a => (Shift and go to 6)
 S  -> .A    b => (Shift and go to 8)
 A  -> .aSb  
 A  -> .ab   

 (5)
 S  -> SA.   [$b] => (reduce on $ or b)

 (6)
 A  -> a.Sb  S => (Go to 7)
 A  -> a.b   A => (Go to 3)
 S  -> .SA   a => (Shift and go to 4)
 S  -> .A    b => (Shift and go to 8)
 A  -> .aSb  
 A  -> .ab   

 (7)
 A  -> aS.b  A => (Go to 5)
 S  -> S.A   a => (Shift and go to 6)
 A  -> .aSb  b => (Shift and go to 10)
 A  -> .ab   

 (8)
 A  -> ab.   [$b] => (reduce on $ or b)

 (9)
 S  -> A.    [$b] => (reduce on $ or b)

 (10)
 A  -> aSb.  [$b] => (reduce on $ or b)
like image 27
tgoneil Avatar answered Sep 22 '22 06:09

tgoneil