优先规则不适用于Yacc

时间:2013-05-28 21:36:07

标签: 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; }
    ;

%%

这是lex:

%{
#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

在yacc文件中添加行%left '+' '-'%left '*' '/'应该解决这个问题,但他们没有。谁能告诉我为什么?

2 个答案:

答案 0 :(得分:2)

但是你对作品的说明是错误的。它应该是expression '+' expression而不是expression '+' NUMBER(并且在每个运算符的情况下类似),i。即双方都是表达,你不想禁止添加两个表达,你呢。

答案 1 :(得分:1)

优先规则仅用于解决语法中的歧义。如果你的语法直接编码优先级,那么优先级规则就没有歧义。

将语法定义为expr: expr op NUMBER将所有运算符的优先级定义为相同,并严格按从左到右的方式对其进行求值。您希望为每个运算符将语法定义为expr: expr op expr,以便语法不明确,并且优先级规则可以解决歧义。