简体   繁体   English

如何更改 bison/yacc 中的优先级?

[英]How to change precedence in bison/yacc?

so I'm doing a thesis where I am making my own programming language.所以我正在写一篇论文,我正在制作自己的编程语言。 I am currently trying to make a simple calculator language that allows you to assign ints to variables and then do operations/print them out.我目前正在尝试制作一种简单的计算器语言,允许您将整数分配给变量,然后进行操作/打印出来。

However I ran across the situation that bison treats everything with the same precedence unless told otherwise (so 1 + 2 * 3 gives 9 instead of 7).但是我遇到了这种情况,除非另有说明,否则野牛以相同的优先级对待所有事物(因此 1 + 2 * 3 给出 9 而不是 7)。

I looked around and I was told doing something like我环顾四周,有人告诉我做类似的事情

%left ADD SUB
%left MUL DIV

would give me the expected output, but it doesn't.会给我预期的 output,但事实并非如此。 Can anyone help me figure out what is going wrong?谁能帮我弄清楚出了什么问题?

here's my flex file这是我的弹性文件

%{
#include <stdio.h>
#include <stdlib.h>
#include "Parser.tab.h"
%}


%%
print       {return PRINT;}
exit        {return EXIT;}

[a-zA-Z]    {yylval.name = yytext[0]; return ID;}
[0-9]+      {yylval.data = atoi(yytext); return NUMBER;}
[;\n]       {return NEWLINE;}
[ \t]       {;}
"-"         {return SUB;}
"+"         {return ADD;}
"*"         {return MUL;}
"/"         {return DIV;}
.           {return UNKNOWN;}
%%

int yywrap(void) { return -1; }

here's my bison file这是我的野牛文件

%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "Test.h"

void yyerror(const char* err);

int size = 52;
int vars[52];

extern int yylex();
%}

%define parse.error verbose

%union {
    char name;
    int data;
}

%token EXIT UNKNOWN NEWLINE
%token <data> PRINT

%token <name> ID
%token <data> NUMBER

%type <data> line exp term prog
%type <name> assignment

%start line

%left ADD SUB
%left MUL DIV

%%
term:   NUMBER {
            $$ = $1;
        }
        | ID {
            $$ = GetVar($1, vars);
        }
;

exp:    term
        | exp MUL term {
            $$ = $1 * $3;
        }
        | exp DIV term {
            $$ = $1 / $3;
        }
        | exp ADD term {
            $$ = $1 + $3;
        }
        | exp SUB term {
            $$ = $1 - $3;
        }
;

assignment: ID '=' exp NEWLINE  { 
    UpdateVar($1, $3, vars); 
}
;

prog:   assignment {;}
        | PRINT exp NEWLINE {
            printf("%d\n", $2);
        }
        | EXIT NEWLINE {
            return 0;
        }
        | NEWLINE { ; }
;

line: prog | line prog
%%



void yyerror(const char* err) {
    printf("Error happened: %s\n", err);
}

int main() {
    for(int i = 0; i < size; i++) {
        vars[i] = 0;
    }
    return yyparse();
}

Precedence rules are only used by yacc/bison to disambiguate.优先级规则仅被 yacc/bison 用于消除歧义。 If the grammar is not ambiguous, the precedence declarations are not used.如果文法没有歧义,则不使用优先声明。 And your grammar is unambiguous.你的语法是明确的。

It's not that bison treats all operators as having the same precedence unless told otherwise.除非另有说明,否则野牛并不是将所有运算符都视为具有相同的优先级。 It's that you told bison that all operators have the same precedence (in your grammar).这是你告诉 bison 所有运算符都具有相同的优先级(在你的语法中)。 If your grammar is ambiguous and you don't tell bison what the precedence rules are with precedence declarations, bison will report parsing conflicts.如果您的语法有歧义并且您没有告诉 bison 优先声明的优先规则是什么,bison 将报告解析冲突。 [Note 1] [注一]

If you take a look at the Bison manual, which is highly recommended, you will find:如果你看一下强烈推荐的 Bison 手册,你会发现:

  1. Fully explained example calculators 完整解释的示例计算器

  2. An explanation of the parsing algorithm 解析算法的解释

  3. which includesan explanation of the precedence rules其中包括对优先规则的解释

The Bison manual is pretty good. Bison 手册非常好。 But if the language you're writing is worth writing a thesis about, you might want to read a bit more about writing parsers.但是,如果您正在编写的语言值得写一篇论文,您可能需要阅读更多有关编写解析器的内容。 There are some pretty good textbooks.有一些很好的教科书。


Notes笔记

  1. After reporting the problem, it will fall back to a rule ("prefer shift") which treats all operators as being left-associative with the same precedence.报告问题后,它将回退到一个规则(“更喜欢移位”),该规则将所有运算符视为具有相同优先级的左结合运算符。 In that sense, you could say that bison has a default.从这个意义上说,你可以说野牛有一个默认值。 But if you get conflict reports you should fix them.但是如果你收到冲突报告,你应该修复它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM