Bison shift/reduce confilcs

47 views Asked by At

I have the following start of a Pascal grammar The grammar works correctly. What I don't understand is I have a very similar grammar in my 6502 assembler that does not have any reduce/shift conflicts.

    %no-lines

    %{
    // ***********************************************************************
    // Author           : Paul Baxter
    // ***********************************************************************

    #pragma warning(disable:4065)
    #pragma warning(disable:4996)

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h>
    #include <limits.h>
    #include <errno.h>
    #include <ctype.h>
    #include <stdbool.h>

    #include "node.h"
    #include "pascal.h"
    #include "expander.h"
    #include "pascal.tab.h"

    %}

    %union
    {
        char cValue;                /* char value */
        int iValue;                 /* integer value */
        bool bValue;                /* bool value */
        double dValue;              /* double value */
        struct PString *pValue;     /* pascal string value */
        struct parse_node *nPtr;    /* node pointer */
    };

    %token <iValue> INTEGER         /* integer */
    %token <dValue> REAL            /* real */
    %token <pValue> ST              /* string */
    %token <bValue> BO              /* bool */
    %token <pValue> SYM             /* symbol */
    %token <iValue> VARTYPE         /* variable type */
    %token <cValue> CH              /* char */

    %token PROGRAM INPUT OUTPUT BEG END ENDP SC PARAMLIST NOT PROC STATEMENT VAR CONST CO DECL AS

    %nonassoc ELSE '~'
    %left SHIFT_LEFT SHIFT_RIGHT UMINUS UPLUS
    %left OR AND GE LE EQ NE '>' '<'
    %left BIT_OR BIT_AND '^'
    %left '+' '-'
    %left '*' '/'

    %type <nPtr> header stmt begstmt endstmt endprogram subexpr expr assign opr
    %type <nPtr> parameter_list procedure_call var_decl varstmt sym_list conststmt basetype
    %type <nPtr> const_decl

    %%

    program
        : program stmt                      { Ex($2);                                       }
        |                                   {                                               }
        ;

    stmt
        : header                            { $$ = Statement(1, $1);                        }
        | procedure_call                    { $$ = Statement(1, $1);                        }
        | conststmt                         { $$ = Statement(1, $1);                        }
        | const_decl                        { $$ = Statement(1, $1);                        }
        | var_decl                          { $$ = Statement(1, $1);                        }
        | varstmt                           { $$ = Statement(1, $1);                        }
        | begstmt                           { $$ = Statement(1, $1);                        }
        | endstmt                           { $$ = Statement(1, $1);                        }
        | assign                            { $$ = Statement(1, $1);                        }
        | endprogram                        { $$ = Statement(1, $1);                        }
        ;

    begstmt
        : BEG                               { $$ = Beg();                                   }
        ;

    endstmt
        : END                               { $$ = End();                                   }
        ;

    header
        : PROGRAM SYM '(' INPUT ')' SC                  { $$ = ProgHeader($2, true, false);     }
        | PROGRAM SYM '(' OUTPUT ')' SC                 { $$ = ProgHeader($2, false, true);     }
        | PROGRAM SYM '(' INPUT ',' OUTPUT ')' SC       { $$ = ProgHeader($2, true, true);      }
        | PROGRAM SYM '(' ')' SC                        { $$ = ProgHeader($2, false, false);    }
        | PROGRAM SYM  SC                               { $$ = ProgHeader($2, false, false);    }
        ;

    endprogram
        : ENDP                              { $$ = EndProg();                               }
        ;

    varstmt
        : VAR                               { $$ = Var();                                   }
        ;

    conststmt
        : CONST                             { $$ = Const();                                 }
        ;

    expr
        : basetype                          { $$ = $1;                                      }
        | opr                               { $$ = $1;                                      }
        ;

    basetype
        : INTEGER                           { $$ = IntCon($1);                              }
        | REAL                              { $$ = RealCon($1);                             }
        | CH                                { $$ = CharCon($1);                             }
        | ST                                { $$ = StrListNode(1, $1);                      }
        | SYM                               { $$ = SymVal($1);                              }
        ;

    opr
        : '-' subexpr %prec UMINUS          { $$ = Oper(UMINUS, 1, $2);                     }
        | '+' subexpr %prec UPLUS           { $$ = Oper(UPLUS, 1, $2);                      }
        | NOT subexpr                       { $$ = Oper(NOT, 1, $2);                        }
        | subexpr OR subexpr                { $$ = Oper(OR, 2, $1, $3);                     }
        | subexpr AND subexpr               { $$ = Oper(AND, 2, $1, $3);                    }
        | subexpr SHIFT_LEFT subexpr        { $$ = Oper(SHIFT_LEFT, 2, $1, $3);             }
        | subexpr SHIFT_RIGHT subexpr       { $$ = Oper(SHIFT_RIGHT, 2, $1, $3);            }
        | subexpr GE subexpr                { $$ = Oper(GE, 2, $1, $3);                     }
        | subexpr LE subexpr                { $$ = Oper(LE, 2, $1, $3);                     }
        | subexpr NE subexpr                { $$ = Oper(NE, 2, $1, $3);                     }
        | subexpr BIT_AND subexpr           { $$ = Oper(BIT_AND, 2, $1, $3);                }
        | subexpr BIT_OR subexpr            { $$ = Oper(BIT_OR, 2, $1, $3);                 }
        | subexpr '^' subexpr               { $$ = Oper('^', 2, $1, $3);                    }
        | subexpr '+' subexpr               { $$ = Oper('+', 2, $1, $3);                    }
        | subexpr '-' subexpr               { $$ = Oper('-', 2, $1, $3);                    }
        | subexpr '*' subexpr               { $$ = Oper('*', 2, $1, $3);                    }
        | subexpr '/' subexpr               { $$ = Oper('/', 2, $1, $3);                    }
        ;

    subexpr
        : expr                              { $$ = $1;                                      }
        | '(' subexpr ')'                   { $$ = $2;                                      }
        ;

    assign
        : SYM AS expr SC                    { $$ = Oper(AS, 2, Id($1), $3);                 }
        ;

    procedure_call
        : SYM '('  parameter_list ')' SC    { $$ = ProcCall($1, ParamListHead);             }
        | SYM '(' ')' SC                    { $$ = ProcCall($1, NULL);                      }
        | SYM  SC                           { $$ = ProcCall($1, NULL);                      }
        ;

    parameter_list
        : expr                              { $$ = ParamList(Param($1));                    }
        | parameter_list ','  expr          { $$ = ParamList(Param($3));                    }
        ;

    const_decl
        : SYM '=' expr SC                   { $$ = ConDecl(Id($1), $3);                     }
        ;

    var_decl
        : sym_list CO VARTYPE SC            { $$ = VarDecl($1, IntCon($3));                 }
        ;

    sym_list
        : SYM                               { $$ = SymList(Id($1));                         }
        | sym_list ',' SYM                  { $$ = SymList(Id($3));                         }
        ;

    %%

This produces 14 shift/reduce conflicts that I don't understand.

State 51 conflicts: 14 shift/reduce

State 51

   32 opr: NOT subexpr .
   33    | subexpr . OR subexpr
   34    | subexpr . AND subexpr
   35    | subexpr . SHIFT_LEFT subexpr
   36    | subexpr . SHIFT_RIGHT subexpr
   37    | subexpr . GE subexpr
   38    | subexpr . LE subexpr
   39    | subexpr . NE subexpr
   40    | subexpr . BIT_AND subexpr
   41    | subexpr . BIT_OR subexpr
   42    | subexpr . '^' subexpr
   43    | subexpr . '+' subexpr
   44    | subexpr . '-' subexpr
   45    | subexpr . '*' subexpr
   46    | subexpr . '/' subexpr

    SHIFT_RIGHT  shift, and go to state 56
    SHIFT_LEFT   shift, and go to state 57
    NE           shift, and go to state 58
    LE           shift, and go to state 59
    GE           shift, and go to state 60
    AND          shift, and go to state 61
    OR           shift, and go to state 62
    '^'          shift, and go to state 63
    BIT_AND      shift, and go to state 64
    BIT_OR       shift, and go to state 65
    '+'          shift, and go to state 66
    '-'          shift, and go to state 67
    '*'          shift, and go to state 68
    '/'          shift, and go to state 69

    SHIFT_RIGHT  [reduce using rule 32 (opr)]
    SHIFT_LEFT   [reduce using rule 32 (opr)]
    NE           [reduce using rule 32 (opr)]
    LE           [reduce using rule 32 (opr)]
    GE           [reduce using rule 32 (opr)]
    AND          [reduce using rule 32 (opr)]
    OR           [reduce using rule 32 (opr)]
    '^'          [reduce using rule 32 (opr)]
    BIT_AND      [reduce using rule 32 (opr)]
    BIT_OR       [reduce using rule 32 (opr)]
    '+'          [reduce using rule 32 (opr)]
    '-'          [reduce using rule 32 (opr)]
    '*'          [reduce using rule 32 (opr)]
    '/'          [reduce using rule 32 (opr)]
    $default     reduce using rule 32 (opr)

it is the opr subexpr . subexpr The grammar works but I would rather not have any conflicts. I want to understand why it is a conflict and how to fix it.

Thanks in advance

0

There are 0 answers