首页 > 解决方案 > 我必须手动修复 Yacc 中的移位/减少问题吗?

问题描述

我最难尝试消除语法中的两个移位/减少问题。我无法在任何地方找到解决方案。我看到 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);
}```

标签: bisonyacclex

解决方案


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

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

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


推荐阅读