5

I believe I am having trouble understanding how shift reduce conflicts work. I understand that bison can look ahead by one, so I don't understand why I am having the issue.

In my language a List is defined as a set of numbers or lists between [ ]. For example [] [1] [1 2] [1 [2] 3] are all valid lists.

Here are the definitions that are causing problems

 value: num 
    | stringValue
    | list          
    ;

list: LEFTBRACE RIGHTBRACE  
    | LEFTBRACE list RIGHTBRACE 
    | num list          
    | RIGHTBRACE            
    ;

The conflict happens from the number, it doesn't know weather to shift by the list rule, or reduce by the value rule. I am confused because can't it check to see if a list is following the number?

Any incite on how I should proceed would be greatly appreciated.

Pieces
  • 2,256
  • 5
  • 25
  • 39

2 Answers2

6

I think I'd define things differently, in a way that avoids the problem to start with, something like:

value: num
     | stringvalue
     | list
     ;

items:
     | items value
     ;

list: LEFTBRACE items RIGHTBRACE;

Edit: Separating lists of numbers from lists of strings can't be done cleanly unless you eliminate empty lists. The problem that arises is that you want to allow an empty list to be included in a list of numbers or a list of strings, but looking at the empty list itself doesn't let the parser decide which. For example:

[ [][][][][][][][] 1 ]

To figure out what kind of list this is, the parser would have to look ahead all the way to the 1 -- but an LALR(N) parser can only lookahead N symbols to make that decision. Yacc (and Byacc, Bison, etc.) only do LALR(1), so they can only look ahead one symbol. That leaves a few possibilities:

  1. eliminate the possibility of empty lists entirely
  2. Have the lexer treat an arbitrary number of consecutive empty lists as a single token
  3. use a parser generator that isn't limited to LALR(1) grammars

Inside of a yacc grammar, however, I don't think there's much you can do -- your grammar simply doesn't fit yacc's limitations.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Sometimes nice to put a comment in for the empty match so that it is easier to see. `items: /* Empty */` – Martin York Mar 21 '11 at 19:00
  • @Martin: Sometimes true -- at the same time, anybody who can read yacc-like grammars otherwise will almost certainly recognize it very easily. – Jerry Coffin Mar 21 '11 at 19:18
  • Wouldn't this allow for strings to be in the list with numbers? Is there a way to make sure that there is only one type in a list? – Pieces Mar 21 '11 at 19:51
  • @Pieces: yes -- I thought that was the intent. See edited question. – Jerry Coffin Mar 21 '11 at 19:53
  • @Pieces to have a list with only numbers, you'd need a separate non-terminal for a list of only number and a list of only strings and so on. Wouldn't be hard to do though. – Samsdram Mar 21 '11 at 19:54
  • 1
    @Samsdram: Without the possibility of empty lists you'd be right, but allowing empty lists it's not only hard, but (I believe) impossible. – Jerry Coffin Mar 21 '11 at 20:29
  • @Jerry Coffin: You an experienced person like the OP. ;-p – Martin York Mar 21 '11 at 22:04
  • @Jerry-Coffin I don't see why it wouldn't be possible with yacc. One could create a separate non-terminal "empty-lists" in yacc easier than one could in the lexer. Empty lists could be an optional prefix before of the types of lists. This is just a problem of left factoring, no? – Samsdram Mar 22 '11 at 04:19
1

With a bottom up parser it is generally a good idea to avoid right recursion which is what you have in the starred line of the grammar below.

list: LEFTBRACE RIGHTBRACE  
    | LEFTBRACE list RIGHTBRACE 
  **| num list**          
    | RIGHTBRACE  

Instead have you thought about something like this?

value:value num
   | value string
   | value list
   | num
   | string
   | list

list: LEFTBRACE RIGHTBRACE
   | LEFTBRACE value RIGHTBRACE 

This way you have no right recursion and the nesting logic of the grammar is more simply expressed.

Samsdram
  • 1,615
  • 15
  • 18