Нужно ли исправлять проблемы смещения / уменьшения в Yacc вручную? - PullRequest
0 голосов
/ 16 апреля 2019

Мне сложнее всего решить две проблемы сдвига / уменьшения в моей грамматике.Я не могу найти решение нигде.Я вижу, что 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);
}```

1 Ответ

2 голосов
/ 16 апреля 2019

Ваша yywrap() реализация вызывает exit(). Это означает, что как только сканер увидит конец файла, приложение будет остановлено. Поэтому парсер не сможет завершить свою работу.

Как правило, вы должны использовать %option noyywrap в вашем (f) файле lex, чтобы избежать необходимости предоставления yywrap. Или используйте реализацию по умолчанию в -lfl. Но если вы настаиваете на его реализации, он должен возвратить 1, чтобы указать, что больше нечего читать.

Кроме того, extern int yytext[]; не является необходимым, поскольку вы нигде не ссылаетесь на yytext в вашем парсере. И вам не следует ссылаться на yytext в вашем парсере; такое использование почти всегда является ошибкой. Но если бы вы использовали yytext, объявление было бы неправильным: это указатель (не массив) на char (не int). Ваш компилятор C, вероятно, не будет отмечать эту ошибку.

...