2013-05-28 54 views
0

我在學習yacc,而我從書中得到的這段代碼似乎並沒有正確應用優先規則。優先規則在Yacc中不起作用

這裏的YACC文件:

%{ 

#include <stdio.h> 
extern int yylex(); 
void yyerror (char const *msg); 

%} 

%token NAME NUMBER 
%left '+' '-' 
%left '*' '/' 

%% 

statement: NAME '=' expression 
    |  expression    { printf("= %d\n", $1); } 
    ; 

expression: expression '+' NUMBER { $$ = $1 + $3; } 
    |  expression '-' NUMBER { $$ = $1 - $3; } 
    |  expression '*' NUMBER { $$ = $1 * $3; } 
    |  expression '/' NUMBER { if ($3) $$ = $1/$3; 
             else yyerror("divide by zero"); } 
    |  '-' expression   { $$ = -$2; } 
    |  '(' expression ')'  { $$ = $2; } 
    |  NUMBER     { $$ = $1; } 
    ; 

%% 

這裏的法:

%{ 
#include "y.tab.h" 
#include <stdio.h> 
extern int yylval; 
%} 

%% 

[0-9]+  { yylval = atoi(yytext); return NUMBER; } 
[ \t]  { ; } 
\n   { return 0; } 
.   { return yytext[0]; } 

%% 

我編譯:

lex foo.l 
yacc -d foo.y 
clang -o foo lex.yy.c y.tab.c -ly -ll 

運行它乘法首先給出正確的答案:

> ./foo 
3 * 2 + 1 
= 7 

但當乘法發生第二次,它給出錯誤的答案:

> ./foo 
4 + 5 * 2 
= 18 

添加線%left '+' '-'%left '*' '/'在YACC文件理應解決這個問題,但他們沒有。誰能告訴我爲什麼?

回答

2

但是,您對製作的指定是錯誤的。它應該是expression '+' expression而不是expression '+' NUMBER(在每個運營商的情況下也是如此),即。即雙方都是表情,你不想禁止添加兩個表情,你呢。

1

優先規則僅用於解決語法中的歧義。如果您的語法直接對優先級進行編碼,則優先級規則無法解決。

將語法定義爲expr: expr op NUMBER將所有運算符的優先級定義爲相同,並嚴格按照從左到右的順序進行評估。你想爲每個操作符定義語法爲expr: expr op expr,以便語法不明確,優先規則可以解決歧義。