我无法识别的 Yacc shift/reduce

Yacc shift/reduce that I cannot identify

所以我有这个 .y 文件,我试图用它的参数解析和评估一个函数,但是有一个我无法识别的 shift/reduce 冲突:

.y

%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "types.h"
#define YYDEBUG 0
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id(int i);
nodeType *con(int value);
void freeNode(nodeType *p);
void yyerror(char *s);

nodeType *RadEc;
int sym[26]; /* symbol table */

%}

%union {
  int iValue;      /* integer value */
  char sIndex;     /* symbol table index */
  nodeType *nPtr;  /* node pointer */
};

%token <iValue> INTEGER 
%token <sIndex> VARIABLE
%token WHILE IF PRINT SUBRAD ENDSUB THEN DO ENDIF RAD
%nonassoc IFX
%nonassoc ELSE

%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS

%type <nPtr> statement expr stmt_list
%type <iValue> expresie
%start      program

%%

program   : declaratii cod         { exit(0); }
          ;

declaratii: SUBRAD stmt_list ENDSUB   { RadEc=; }
          | /* NULL */
          ;

statement : '\n'                    { $$ = opr(';', 2, NULL, NULL); }
          | expr '\n'                   { $$ = ; }
          | PRINT expr '\n'             { $$ = opr(PRINT, 1, ); }
          | VARIABLE '=' expr '\n'          { $$ = opr('=', 2, id(), ); }
          | DO stmt_list WHILE expr         { $$ = opr(WHILE, 2, , ); }
          | IF expr THEN stmt_list ENDIF %prec IFX  { $$ = opr(IF, 2, , ); }
          | IF expr THEN stmt_list ELSE stmt_list ENDIF { $$ = opr(IF, 3, , , ); }
          ;

stmt_list : statement
          | stmt_list statement   { $$ = opr(';', 2, , ); }
          ;

expr      : INTEGER               { $$ = con(); }
          | VARIABLE              { $$ = id(); }
          | '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, ); }
          | expr '+' expr         { $$ = opr('+', 2, , ); }
          | expr '-' expr         { $$ = opr('-', 2, , ); }
          | expr '*' expr         { $$ = opr('*', 2, , ); }
          | expr '/' expr         { $$ = opr('/', 2, , ); }
          | expr '<' expr         { $$ = opr('<', 2, , ); }
          | expr '>' expr         { $$ = opr('>', 2, , ); }
          | expr GE expr          { $$ = opr(GE, 2, , ); }
          | expr LE expr          { $$ = opr(LE, 2, , ); }
          | expr NE expr          { $$ = opr(NE, 2, , ); }
          | expr EQ expr          { $$ = opr(EQ, 2, , ); }
          | '(' expr ')'          { $$ = ; }
          ;


cod   : '.'          {exit(0);}
      | instruc '\n' cod
      ;


instruc   : '\n'
      | PRINT expresie              {printf("%d\n",);}
      | VARIABLE '=' expresie           {sym[]=;}
      | RAD'('expresie','expresie','expresie')'     {sym[0]=; sym[1]=; sym[2]=; ex(RadEc);}
      ;


expresie  : INTEGER         { $$ = ; }
          | VARIABLE            { $$ = sym[]; }
          | '-' expresie %prec UMINUS   { $$ = -; }
          | expresie '+' expresie   { $$ = +; }
          | expresie '-' expresie   { $$ = -; }
          | expresie '*' expresie   { $$ = *; }
          | expresie '/' expresie   { $$ = /; }
          | expresie '<' expresie   { $$ = <; }
          | expresie '>' expresie   { $$ = >; }
          | expresie GE expresie    { $$ = >=; }
          | expresie LE expresie    { $$ = <=; }
          | expresie NE expresie    { $$ = !=; }
          | expresie EQ expresie    { $$ = ==; }
          | '(' expresie ')'        { $$ = ; }
          ;

%%

nodeType *con(int value) 
{ 
  nodeType *p; 

  /* allocate node */ 
  if ((p = malloc(sizeof(conNodeType))) == NULL) 
    yyerror("out of memory"); 
  /* copy information */ 
  p->type = typeCon; 
  p->con.value = value; 
  return p; 
} 

nodeType *id(int i) 
{ 
  nodeType *p; 
  /* allocate node */ 
  if ((p = malloc(sizeof(idNodeType))) == NULL) 
    yyerror("out of memory"); 
  /* copy information */ 
  p->type = typeId; 
  p->id.i = i; 
  return p; 
} 

nodeType *opr(int oper, int nops, ...) 
{ 
  va_list ap; 
  nodeType *p; 
  size_t size; 
  int i; 

  /* allocate node */ 
  size = sizeof(oprNodeType) + (nops - 1) * sizeof(nodeType*); 
  if ((p = malloc(size)) == NULL) 
    yyerror("out of memory"); 
  /* copy information */
  p->type = typeOpr; 
  p->opr.oper = oper; 
  p->opr.nops = nops; 
  va_start(ap, nops); 
  for (i = 0; i < nops; i++) 
    p->opr.op[i] = va_arg(ap, nodeType*); 
  va_end(ap); 

  return p; 
}

void freeNode(nodeType *p) 
{ 
  int i; 

  if (!p) 
    return; 
  if (p->type == typeOpr) { 
    for (i = 0; i < p->opr.nops; i++) 
      freeNode(p->opr.op[i]); 
  } 
  free (p); 
} 

int ex(nodeType *p) 
{ 
  if (!p) 
    return 0; 

  switch(p->type) 
    { 
    case typeCon: return p->con.value; 
    case typeId: return sym[p->id.i]; 
    case typeOpr: switch(p->opr.oper) 
                    { 
            case WHILE: while(ex(p->opr.op[0])) 
                           ex(p->opr.op[1]); 
                        return 0; 
            case IF: if (ex(p->opr.op[0])) 
                        ex(p->opr.op[1]); 
                     else if (p->opr.nops > 2) 
                         ex(p->opr.op[2]); 
                     return 0; 
            case PRINT: printf("%d\n", ex(p->opr.op[0])); 
                        return 0; 
            case ';': ex(p->opr.op[0]); 
                      return ex(p->opr.op[1]); 
            case '=': return sym[p->opr.op[0]->id.i] = ex(p->opr.op[1]); 
            case UMINUS: return -ex(p->opr.op[0]); 
            case '+': return ex(p->opr.op[0]) + ex(p->opr.op[1]); 
            case '-': return ex(p->opr.op[0]) - ex(p->opr.op[1]); 
            case '*': return ex(p->opr.op[0]) * ex(p->opr.op[1]); 
            case '/': return ex(p->opr.op[0]) / ex(p->opr.op[1]); 
            case '<': return ex(p->opr.op[0]) < ex(p->opr.op[1]); 
            case '>': return ex(p->opr.op[0]) > ex(p->opr.op[1]); 
            case GE: return ex(p->opr.op[0]) >= ex(p->opr.op[1]); 
            case LE: return ex(p->opr.op[0]) <= ex(p->opr.op[1]); 
            case NE: return ex(p->opr.op[0]) != ex(p->opr.op[1]); 
            case EQ: return ex(p->opr.op[0]) == ex(p->opr.op[1]); 
            } 
    } 
}

void yyerror(char *s) 
{ 
  fprintf(stdout, "%s\n", s); 
} 

int main(void) 
{
#if YYDEBUG
  yydebug = 1;
#endif
  yyparse();
  return 0; 
}

我尝试了不同的方法来查看我是否丢失了一些东西,但我在这方面还很陌生,仍然无法很好地解决冲突。

非常感谢任何帮助。

你的语法允许语句是表达式,它允许两个语句按顺序出现,没有任何分隔符。

现在,下面两个都是表达式:

a
-1

假设它们在语句列表中看起来像那样。这与这个单一的表达方式有何不同?

a - 1

歧义总是表现为解析冲突。

顺便说一下,分隔的 if 语句(带有 endif 标记)不能表现出悬空的 else 歧义。 endif 括号使解析明确。因此,所有从不同语法复制的优先设备在这里都是完全多余的。