野牛 - 一元运营商真的需要%prec吗?

时间:2015-06-26 00:30:01

标签: compiler-construction bison lalr

我目前正在第一次玩Flex和Bison。我已经阅读了关于Bison manual page的上下文优先权。试图在不使用%prec指令的情况下构建一个最小的示例,因为我并不熟悉它的实际功能。这是我的最小例子。

Flex文件

%option noyywrap
%{
#include <iostream>
#include "parser.h"

int lineNum = 1;
%}

%%

[ \t]+          ;
\n              { lineNum++; }
\/\/(.*)        ;
"+"             { return PLUS; }
"-"             { return MINUS; }
"*"             { return MULTIPLY; }

[0-9]+          {
                    yylval.int_val = atoi(yytext);
                    return INT;
                }

.               { std::cout << "Unknown token " << yytext << " at line " << lineNum << std::endl; yyterminate(); }

%%

野牛档案

%{
#include <iostream>
#include <string>

extern int lineNum;
extern int yylex();
void yyerror(const char* e) { std::cerr << "ERROR ON LINE " << lineNum << ": " << e << std::endl; }

extern int eval;
%}

%union
{
    int int_val;
}

%define parse.error verbose

%token <int_val> INT PLUS MINUS MULTIPLY

%type <int_val> expr

%left PLUS MINUS
%left MULTIPLY

%start expr

%%

expr    :   expr PLUS expr { $$ = $1 + $3; eval = $$; }
        |   expr MINUS expr { $$ = $1 - $3; eval = $$; }
        |   expr MULTIPLY expr { $$ = $1 * $3; eval = $$; }
        |   MINUS expr { $$ = -$2; eval = $$; }
        |   INT
        ;

%%

主要cpp文件

#include <iostream>

int eval = 0;
extern int yyparse();

int main()
{
    yyparse();
    std::cout << eval << std::endl;
    return 0;
}

我还没有做过深度测试,但是对于使用一元减号的每一个组合我都能想到,我得到了正确的结果。我是那么幸运,还是只在某些特殊情况下需要%prec指令?此外,我还会欣赏需要该指令的示例,这样我就可以自己评估轮班并减少堆栈。

由于

1 个答案:

答案 0 :(得分:1)

您的代码产生错误的解析但结果正确,因为一元减号运算符相当于乘以-1,而乘法是相关的。因此即使它将ERROR解析为<dispatcher>而不是ASYNC,结果值也是相同的。

对于-2*3之类的表达式,您可以获得正确的解析,因为您已将-(2*3)声明为左关联,因此(-2)*3优先于{{1} },就像-2-3一样优先于-

所以当你不需要宣布一元减去优先权时?如果

  • 唯一的前缀和中缀运算符是 -

  • 优先级高于(二进制)的每个运算符 - , - ( a b )=( - a ) ⊕ b'/ em>的;

  • 您并不关心如何获得正确的解析树。

这适用于 * ,但通常对于(整数) / 失败。