shift/reduce conflict with if ... else statement

714 views Asked by At

I'm trying to make a parser about a java like language, but with else statement, a shift/reduce conflict appears. I tried bison bison_file.y --report=state and the result about the conflict is:

State 62 31 statement: if_statement . 65 if_else_statement: if_statement . ELSE statement ELSE shift, and go to state 84 ELSE [reduce using rule 31 (statement)] $default reduce using rule 31 (statement)

I cannot think a way to avoid the conflict. Any good ideas? Here, I submit the full code:

%{
#include <stdio.h>
#include <math.h>
void yyerror(char *);
extern int yylval;
extern FILE *yyin;
extern FILE *yyout;
extern yylineno;
extern int yyparse(void);
extern int yylex(void);
extern int yywrap() { return 1; }
extern char* yytext;
int errors;
%}

%debug
%start m_class


%token IF ELSE INT CHAR CLASS NEW GURISE VOID WHILE
%token PUBLIC PROTECTED PRIVATE STATIC FINAL ABSTRACT
%token PLUS MINUS MUL DIV MODULO
%token EQ NEQ GRT LT GREQ LEQ
%token OR AND NOT
%token AR_PAR DEK_PAR AR_AGK DEK_AGK AR_STRO DEK_STRO
%token SEMICOLON ANATHESI COMA
%token MY_INT SINT MY_CHAR ID

%right          ANATHESI
%left           OR AND
%nonassoc       EQ NEQ GRT LT GREQ LEQ
%left           PLUS MINUS MUL DIV MODULO
%right          NOT

%%

m_class: m_class class_declaration
        | class_declaration
        ;

class_declaration: CLASS ID class_body
        ;

class_body: AR_STRO variable_declaration constructor method_declaration DEK_STRO
        ;

variable_declaration:variable variable_declaration
    |variable
    |array_declaration
    |array_declaration variable_declaration
        ;

variable:  var_type ID SEMICOLON
    ;

var_type: INT
        |CHAR
        ;

array_declaration: ID ANATHESI NEW var_type AR_AGK MY_INT DEK_AGK SEMICOLON
    ;


constructor: modifier ID AR_STRO variable_declaration DEK_STRO
        ;

modifier: PUBLIC
        | PROTECTED
        | PRIVATE
        | STATIC
        | FINAL
        | ABSTRACT
        ;
method_declaration: modifier meth_type ID parameters meth_body
        ;

meth_type: VOID
        | var_type
        ;

parameters: AR_PAR par_body DEK_PAR
        ;

par_body: var_type ID
        | par_body COMA var_type ID
        ;

meth_body: AR_STRO bodybuilder DEK_STRO
        ;

bodybuilder: statement GURISE expression SEMICOLON
        |statement bodybuilder
    |statement
        ;

statement: anathesh
        | if_statement
    | if_else_statement
        | while_statement
        ;

statementsss: statement
    |
    ;

anathesh:atath SEMICOLON
        | atath numeric_expression SEMICOLON
        ;

atath: ID ANATHESI orisma
    |ID AR_AGK MY_INT DEK_AGK ANATHESI orisma
    ;

orisma: ID
    |MY_INT
    |SINT
    |MY_CHAR
    ;

expression: testing_expression
        | numeric_expression
        | logical_expression
        | ID
        | MY_INT
        | SINT
        | MY_CHAR
        ;

numeric_expression:  expression PLUS  expression
        | expression MINUS expression
        | expression MUL expression
        | expression DIV expression
        | expression MODULO expression
        ;

testing_expression: expression EQ expression
        | expression NEQ expression
        | expression GRT expression
        | expression LT expression
        | expression GREQ expression
        | expression LEQ expression
        ;
logical_expression: expression OR expression
        | expression AND expression
        | expression NOT expression
        ;

if_statement: IF abc
    |
        ;

if_else_statement: if_statement ELSE statement
        ;

abc: sin8iki statement
    ;

sin8iki: AR_PAR testing_expression DEK_PAR
        | AR_PAR logical_expression DEK_PAR
        ;

while_statement: WHILE sin8iki statement
        ;


%%



void yyerror(char *s) {
        errors++;
printf("\n------- ERROR AT LINE #%d.\n\n", yylineno);
fprintf(stderr, "%d: error: '%s' at '%s', yylval=%u\n", yylineno, s, yytext, yylval);

}
int main (int argc, char **argv) {
        ++argv;
        --argc;
    errors=0;
        if (argc > 0)
                yyin = fopen (argv[0], "r");
        else
                yyin = stdin;
        yyout = fopen ("output","w");
        yyparse ();
    if(errors==0)
        printf("komple");
        return 0;
}
1

There are 1 answers

0
user2714471 On

Here the parser pushes the tokens into the stack and when IF abc are pushed and the next token is ELSE there will be a conflict, the parser should reduce the IF abc according to if_statement rule or it should shift the next token ELSE into the stack. you have to determine the priorities of your rules, in this case you have to give the ELSE token more priority than if_statement by using %nonassoc and %prec. try this:

if_statement: IF abc %prec else_priority

and in the priorities area:

%nonassoc else_priority
%nonassoc ELSE

you have to write the priorities in this order (the more priority below the less one). hope this will solve your problem.