我正在和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..!");
}
答案 0 :(得分:1)
您必须使用yacc
选项运行-v
以生成名为y.output
的文件。在那里你可以找到有关冲突的线索。该文件显示了生成的解析器的详细状态,以及哪些状态在转移特定令牌或通过某些规则减少之间存在冲突。
你的语法可能存在的问题是:
E : IDENTIFIER '=' E
假设你有
X = 3 + 5
=
与+
的优先顺序是什么?如果解析器刚看到X = 3
并且下一个前瞻标记是+
,它该怎么办?它应该减少 X = 3
到E
到E : IDENTIFIER '=' E
,还是转移 +
并继续扫描更长的右侧E
?
查看y.output
,看看它是否证实了这一假设。
答案 1 :(得分:1)
您的冲突来自规则:
|IDENTIFIER '=' E
|SIN E
|COS E
|TAN E
|ROOT E
因为这些规则都没有为它们设置优先级(未在这些规则中的任何标记上设置),所以当您获得类似SIN X + Y
的输入时,解析器不知道是否要
将其解析为(SIN X) + Y
或SIN (X + Y)
您可以通过设置所有这些规则的优先顺序来修复它,这最容易通过添加一行来完成
%nonassoc '=' SIN COS TAN ROOT
设置所有这些令牌的优先级值,这些值将由规则继承。它取决于你是否应该比二元运算符更高或更低的优先级。对于普通约定,您可能希望=
作为较低的优先级而函数作为较高的优先级(这意味着您实际上需要两个新行而不是将它们全部放在一行中)