2013-07-11 19 views
5

Sono nuovo di Bison e sto avendo problemi con lo spostamento/ridurre i conflitti ... Sto cercando di caricare da file array data[]:Shift/ridurre i conflitti in bisonti

struct _data 
{ 
    char name[50]; 
    char surname[50]; 
    int year; 
} data[1000]; 

Qui fa parte del mio codice bisonti:

%token ID NUM NL EOF 

%% 

File : List EOF 
     ; 
List : Record 
     | List Record 
     ; 
Record : Name Surname Year NL { count++; } 
     | NL     { count++; } 
     | /*empty*/ 
     ; 
Name : ID     { strcpy(data[count].name, yytext); } 
     ; 
Surname: ID     { strcpy(data[count].surname, yytext); } 
     ; 
Year : NUM     { data[count].year= atoi(yytext); } 
     ; 

%%    

ottengo questo errore:

conflicts: 5 shift/reduce 

Qualsiasi idea di dove ho sbagliato?

risposta

11

È possibile utilizzare l'opzione -v per ottenere bison per produrre un file .output contenente molte più informazioni che possono aiutare a diagnosticare lo spostamento/riduzione dei conflitti. In particolare, ti mostrerà ogni stato del parser, incluso l'elenco di elementi, e indicherà anche quali stati hanno conflitti.

Ma in questo caso, il problema è piuttosto semplice. Stripped all'essenziale si dispone:

List: Record 
    | List Record 
    ; 

Record: Something 
     | /* Nothing */ 
     ; 

ignorando ciò che la definizione di Something è, il problema è che un List può essere costituito da un numero qualsiasi di Records, uno dopo l'altro, e un Record può essere vuoto. Ciò significa che nulla può essere analizzato come qualsiasi numero di vuoto Records, che è totalmente ambiguo. Qualsiasi due Somethings consecutivi nell'ingresso può essere separato da 0, 1, 2, 42 o 273 vuoto Records. Poiché il parser non può sapere se iniziare l'analisi di un nuovo Something (spostamento) o di emettere uno Record vuoto (riduzione), si lamenta che vi è un conflitto di spostamento/riduzione.

In questo caso la soluzione è piuttosto semplice. Possiamo vedere che uno Something non vuoto deve terminare con uno NL; presumibilmente l'intento era che lo File fosse costituito da un qualsiasi numero di Records, ciascuno sulla propria linea. Quindi possiamo riscrivere:

File: List EOF 
    ; 

List: Record 
    | List NL Record 
    ; 

Record: Name Surname Year 
     | /* Empty */ 
     ; 

Ora un Record, vuota o non, deve essere seguito da un EOF o un NL. Non può essere seguito direttamente da un altro Record.