0

我正在学习 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 '+' '-'在 yacc 文件中添加这些行%left '*' '/'应该可以解决这个问题,但他们没有。谁能告诉我为什么?

4

2 回答 2

2

但是,您对产品的规范是错误的。它应该是expression '+' expression代替expression '+' NUMBER(并且在每个运算符的情况下类似),即双方都是表达式,您不想禁止添加两个表达式,是吗。

于 2013-05-28T21:45:15.060 回答
1

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

将语法expr: expr op NUMBER定义为将所有运算符的优先级定义为相同,并严格从左到右评估它们。您想expr: expr op expr为每个运算符定义语法,以便语法有歧义,并且优先规则可以解决歧义。

于 2013-05-28T22:49:32.660 回答