无法识别的Yacc移位/减少

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

所以我有这个.y文件,我试图在该文件上解析和评估带有其参数的函数,但是有一个无法识别的移位/减少冲突:

。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=$2; }
          | /* NULL */
          ;

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

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

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


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


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


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

%%

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; 
}

我尝试了不同的方式来查看我是否正在失去某些东西,但是我对此很陌生,仍然无法很好地弄清冲突。

非常感谢任何帮助。

parsing yacc lex
1个回答
0
投票

您的语法允许语句成为表达式,并且允许两个语句按顺序出现而没有任何分隔符。

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

a
-1

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

a - 1

歧义总是显示为解析冲突。

顺便说一下,定界的if语句(带有endif标记)不能表现出悬而未决的else模糊性。 endif括号使解析明确。因此,从不同语法复制的所有优先权工具在这里完全是多余的。

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