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

しかし、乗算が 2 番目に発生すると、間違った答えが得られます。

> ./foo
4 + 5 * 2
= 18

%left '+' '-'行をyacc ファイルに追加すると%left '*' '/'、これが修正されるはずでしたが、修正されませんでした。誰でも理由を教えてもらえますか?

4

2 に答える 2

2

ただし、プロダクションの仕様は間違っています。expression '+' expression代わりに(各演算子の場合expression '+' NUMBERも同様に)、つまり、両側が式である必要があります。2 つの式の追加を禁止したくありませんか。

于 2013-05-28T21:45:15.060 に答える