Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Compiler construction 野牛-一元运算符何时真正需要%prec?_Compiler Construction_Bison_Lalr - Fatal编程技术网

Compiler construction 野牛-一元运算符何时真正需要%prec?

Compiler construction 野牛-一元运算符何时真正需要%prec?,compiler-construction,bison,lalr,Compiler Construction,Bison,Lalr,我现在第一次玩Flex和Bison。我读过关于上下文优先权的文章。尝试在不使用%prec指令的情况下构建一个最小的示例,因为我不太熟悉它的实际功能。这是我的最小示例 Flex文件 %option noyywrap %{ #include <iostream> #include "parser.h" int lineNum = 1; %} %% [ \t]+ ; \n { lineNum++; } \/\/(.*) ; "

我现在第一次玩Flex和Bison。我读过关于上下文优先权的文章。尝试在不使用
%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
        ;

%%
#include <iostream>

int eval = 0;
extern int yyparse();

int main()
{
    yyparse();
    std::cout << eval << std::endl;
    return 0;
}
%选项noyywrap
%{
#包括
#包括“parser.h”
int lineNum=1;
%}
%%
[\t]+;
\n{lineNum++;}
\/\/(.*)        ;
“+”{return PLUS;}
“-”{返回减号;}
“*”{返回乘法;}
[0-9]+          {
yylval.int_val=atoi(yytext);
返回INT;
}

. {std::cout您的代码生成了错误的解析,但却是正确的结果,因为一元减号运算符等于乘以-1,并且乘法是关联的。因此,即使它将
-2*3
解析为
-(2*3)
而不是
(-2)*3
,结果也是相同的

对于像
-2-3
这样的表达式,您得到了正确的解析,因为您已经声明
-
是左关联的,所以
(-2)-3
-(2-3)
更受欢迎,就像
(1-2)-3
1-(2-3)
更受欢迎一样

那么什么时候不需要声明一元负号的优先级呢?如果

  • 唯一同时作为前缀和中缀的运算符是−

  • 每个操作员⊕ 优先级高于(二进制)−, −(一)⊕(b)=(−(a)⊕b

  • 你不在乎得到一个正确的解析树


这适用于*,但通常不适用于(整数)/和%。

谢谢你的解释。不知何故,我没有想到一个错误的派生树。我还找到了一种方法,如何将bison转换为调试模式,在我看到堆栈上发生的一切之后,我看到了差异。我将试着用它来看看
%prec
是如何工作的。它没有给出
-2+3
的正确答案。它确实存在并且我看不出有任何理由不应该这样做。正如rici所说,它没有生成正确的解析树,但是它给出了正确的答案。基于-和+具有相同的优先级并且是左关联的事实,这个甚至生成了右解析树。