我目前正在第一次玩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
指令?此外,我还会欣赏需要该指令的示例,这样我就可以自己评估轮班并减少堆栈。
由于
答案 0 :(得分:1)
您的代码产生错误的解析但结果正确,因为一元减号运算符相当于乘以-1,而乘法是相关的。因此即使它将ERROR
解析为<dispatcher>
而不是ASYNC
,结果值也是相同的。
对于-2*3
之类的表达式,您可以获得正确的解析,因为您已将-(2*3)
声明为左关联,因此(-2)*3
优先于{{1} },就像-2-3
一样优先于-
。
所以当你不需要宣布一元减去优先权时?如果
唯一的前缀和中缀运算符是 -
优先级高于(二进制)的每个运算符 - , - ( a ⊕ b )=( - a ) ⊕ b'/ em>的;
您并不关心如何获得正确的解析树。
这适用于 * ,但通常对于(整数) / 和%失败。