0
votes

I am having the hardest time trying to remove two shift/reduce problems in my grammar. I cant find a solution anywhere. I see that Yacc apparently will prefer the shift, but if so then why won't mine compile? I know one of the issues is the dangling if-else, but the other, I have no idea. I would prefer that Yacc just handle it for me. The error message says 2 shift reduce conflicts

void yyerror (char *s);
#include <stdio.h>
#include <stdlib.h>
int yylex();
extern int yytext[];
extern FILE *yyin;
%}
%start program
%token LTE GTE BEQUALS NOTEQUALS BEGCOMMENT ENDCOMMENT COMMENT GREATER LESS COMMA PLUS SUB MULT DIV EQUAL LP RP LB RB LC RC SEMICOLON INT FLOAT VOID IF WHILE RETURN  ID NUM 
%nonassoc IFX

%nonassoc ELSE
%%
program : declaration_list { printf("\nACCEPT\n"); };

declaration_list : declaration_list declaration     
                 | declaration          
                 ;

declaration  : var_declaration 
         | fun_declaration
             ;

var_declaration : type_specifier ID SEMICOLON   
                | type_specifier ID LB NUM RB SEMICOLON 
                ;

type_specifier : INT      
               | VOID   
           ;

fun_declaration : type_specifier ID LP params RP compound_stmt  ;

params : param_list | VOID ;

param_list : param_list COMMA param 
           | param                  
             ;

param : type_specifier ID           
      | type_specifier ID LB RB   
      ;


compound_stmt : LC local_declarations statement_list RC  
              ;

local_declarations : local_declarations var_declaration 
                   | /* empty */ ;

statement_list : statement_list statement
               | /* empty */ ;

statement : expression_stmt
          | compound_stmt
          | selection_stmt
          | iteration_stmt
          | return_stmt ;

expression_stmt : expression SEMICOLON
                | SEMICOLON 
        ;

selection_stmt : ifsubroutine  statement        
               | ifsubroutine  statement ELSE     
               ;

ifsubroutine : IF  LP expression RP  
        ;

iteration_stmt : whilesubroutine LP expression RP statement          
                ;
whilesubroutine : WHILE   ;

return_stmt : RETURN SEMICOLON              

            | RETURN expression SEMICOLON  
            ;

expression : var EQUAL expression     
           | simple_expression      
           ;

var : ID                    
    | ID LB expression RB 
    ;

simple_expression : additive_expression relop additive_expression  
                  | additive_expression                            
                  ;

relop : LTE | LESS | GREATER | GTE | EQUAL| NOTEQUALS ;

additive_expression : additive_expression addop term    
                    | term                              
                    ;

addop : PLUS 
      | SUB 
      ;

term : term mulop factor    
     | factor               
     ;

mulop : MULT 
      | DIV 
      ;

factor : LP expression RP 
       | var                
       | call               
       | NUM                
       ;

call : ID LP args RP  
     ;

args : arg_list | /* empty */ ;

arg_list : arg_list COMMA expression 
         | expression              
         ;

%%
int main(int argc, char *argv[])
{
   yyin = fopen(argv[1], "r");
   if (!yyin)
   {
      printf("no file\n");
      exit(0);
   }
   yyparse();
}
void yyerror(char *s)
{
   printf("\nREJECT\n");
//   printf("error from yyerror\n");
   exit(0);
}
int yywrap()
{
  // printf("in yywarp\n");
   exit(0);
}```

1
If your code doesn't compile, it has nothing to do with parse conflicts. But unless you show the code and the compile errors, nobody can give you a better hint than "read the error message".rici
and the compiler errors (which conveniently usually contain line numbers telling you where to look.)rici
Then what do you mean by "won't compile"? That's just a warning and will not stop you from compiling.rici
You need to provide more accurate and more complete problem descriptions. Otherwise, you're relying on telepathy or clairvoyance, neither of which are particularly reliable debugging tools.rici
I think it is terminating. You get a shell prompt, right? But only you know for sure because you are in front of your machine and I'm on a different continent where I can't see over your shoulder. I did my best in my answer. Good luck.rici

1 Answers

1
votes

Your yywrap() implementation calls exit(). That means that as soon as end-of-file is seen by the scanner, the application will terminate. So the parser will not be able to finish its work.

In general, you should use %option noyywrap in your (f)lex file, to avoid the need for providing yywrap. Or use the default implementation in -lfl. But if you insist on implementing it, it should return 1 to indicate that there is nothing more to read.

Also, extern int yytext[]; is unnecessary, because you don't refer to yytext anywhere in your parser. And you should not refer to yytext in your parser; such usage is almost always an error. But if you did use yytext, the declaration would be wrong: it's a pointer (not an array) to char (not int). Your C compiler probably won't flag that error.