我是否必须手动修复Yacc中的移位/减少问题?

问题描述 投票:0回答:1

我正在努力消除语法中的两个移位/减少问题。我无法在任何地方找到解决方案。我看到Yacc显然更喜欢这种转变,但如果是这样,为什么我的编译不会?我知道其中一个问题是悬挂的if-else,但另一个,我不知道。我更希望Yacc能为我处理它。错误消息说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);
}```

bison yacc lex
1个回答
2
投票

你的yywrap()实现调用exit()。这意味着只要扫描程序看到文件结束,应用程序就会终止。因此解析器将无法完成其工作。

通常,您应该在(f)lex文件中使用%option noyywrap,以避免提供yywrap。或者使用-lfl中的默认实现。但是如果你坚持实现它,它应该返回1表示没有更多要阅读。

此外,extern int yytext[];是不必要的,因为你没有在解析器的任何地方引用yytext。你不应该在你的解析器中引用yytext;这种用法几乎总是一个错误。但如果你确实使用了yytext,声明就会出错:它是char(不是int)的指针(不是数组)。您的C编译器可能不会标记该错误。

© www.soinside.com 2019 - 2024. All rights reserved.