2014-10-03 75 views
0

我正在使用lex和yacc。以下是lex和yacc計算器的程序。同時刪除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

「一個真實的awk中的」源代碼的一些歷史版本在語法上有多達96個轉換/減少衝突。看到這個歷史性的知識庫:https://github.com/danfuzz/one-true-awk所以,如果你不知道如何操作Yacc,那麼你就是來自貝爾實驗室的一些知名人士! – Kaz 2014-10-03 22:14:08

回答

1

你的衝突來自規則:

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

因爲沒有這些規則具有優先級爲它們(這些規則對任何標記的未設置)設置,當你輸入像SIN X + Y時,解析器不知道是否 解析它爲
(SIN X) + YSIN (X + Y)

您可以通過設置優先級,所有這些規則,這是最容易被添加一行

完成修復
%nonassoc '=' SIN COS TAN ROOT 

爲所有這些標記設置優先值,這些值將由規則繼承。它取決於你是否應該高於或低於二元運算符的優先級。對於普通的約定,你可能想=爲低優先級和功能更高的優先級(這意味着你實際上需要兩個新的生產線,而不是讓他們都在同一行)

1

您必須運行yacc-v選項生成一個名爲y.output。在那裏你可以找到有關衝突的線索。該文件顯示了生成的解析器的詳細狀態,以及哪些狀態在移動特定標記或通過某些規則縮小之間存在衝突。

一個可能的問題與你的語法是這樣的:

E : IDENTIFIER '=' E 

假設你有你有

X = 3 + 5 

是什麼=+的優先級?如果解析器剛剛看到X = 3並且下一個前視標記爲+,它應該怎麼做?如果它由規則E : IDENTIFIER '=' E減少X = 3E還是應該轉移+繼續掃描更長的右手邊E

看看y.output看看它是否證實了這個假設。