YACC中的Shift减少错误

时间:2014-10-03 21:59:31

标签: yacc

我正在和lex和yacc合作。以下是lex和yacc计算器的程序。同时激发yacc文件。请帮我解决这个问题。我遇到了以下错误:

这是错误:

conflicts: 20 shift/reduce

// YACC计划

 %{
#include<stdio.h>
#include<math.h>

extern void printsymbol();

struct symboltable
{
char name[20];
double value;
}ST[20];

%}

%union
{
double p;
}

%token <p> NUM
%token <p> IDENTIFIER
%token SIN COS TAN ROOT
%left '+' '-'
%left '*' '/'
%type <p> E

%%

Edash:E';'{printf("\n=%f",$1);printsymbol();}
      |Edash E';'{printf("\n=%f",$2);printsymbol();}

E:    E'+'E      {$$=$1+$3;}
      |E'-'E     {$$=$1-$3;}
      |E'*'E     {$$=$1*$3;}
      |E'/'E     {$$=$1/$3;}
      |NUM    {$$=$1;}
      |IDENTIFIER {$$=ST[(int)]$1.value;}
      |'('E')'     {$$=$2;}
      |IDENTIFIER'='E {$$=ST[(int)]$1.value=$3;}
      |SIN E          {$$=sin($2*3.141/180);}
      |COS E          {$$=sin($2*3.141/180);}
      |TAN E          {$$=sin($2*3.141/180);}
      |ROOT E          {$$=sqrt($2);}

%%

int main()
{
yyparse();
}

yyerror()
{
printf("Error Found..!");
}

2 个答案:

答案 0 :(得分:1)

您必须使用yacc选项运行-v以生成名为y.output的文件。在那里你可以找到有关冲突的线索。该文件显示了生成的解析器的详细状态,以及哪些状态在转移特定令牌或通过某些规则减少之间存在冲突。

你的语法可能存在的问题是:

E : IDENTIFIER '=' E

假设你有

X = 3 + 5

=+的优先顺序是什么?如果解析器刚看到X = 3并且下一个前瞻标记是+,它该怎么办?它应该减少 X = 3EE : IDENTIFIER '=' E,还是转移 +并继续扫描更长的右侧E

查看y.output,看看它是否证实了这一假设。

答案 1 :(得分:1)

您的冲突来自规则:

  |IDENTIFIER '=' E
  |SIN E
  |COS E
  |TAN E
  |ROOT E

因为这些规则都没有为它们设置优先级(未在这些规则中的任何标记上设置),所以当您获得类似SIN X + Y的输入时,解析器不知道是否要 将其解析为(SIN X) + YSIN (X + Y)

您可以通过设置所有这些规则的优先顺序来修复它,这最容易通过添加一行来完成

%nonassoc '=' SIN COS TAN ROOT

设置所有这些令牌的优先级值,这些值将由规则继承。它取决于你是否应该比二元运算符更高或更低的优先级。对于普通约定,您可能希望=作为较低的优先级而函数作为较高的优先级(这意味着您实际上需要两个新行而不是将它们全部放在一行中)