bison 中应该如何定义二元运算符?

发布于 2024-09-26 18:03:56 字数 1374 浏览 1 评论 0原文

我正在用 bison 用 C 语言编写一个解析器,虽然它在我迄今为止尝试过的所有情况下似乎都能正常工作,但我在我的二元运算符上收到了一堆移位/归约警告(以及在我的一元 NOT 运算符上的一个警告)出色地)。

binary_op :
      PLUS { }
      | MINUS { }
      | TIMES { }
      | SLASH { }
      | POWER { }
      | AND { }
      | OR { }
      | LE { }
      | LT { }
      | GE { }
      | GT { }
      | EQ { }
      | NE { }
      | MOD { }
    ;

unary_op :
    NOT { }
    ;

expr :
    ...
    | unary_op expr { }
    | expr binary_op expr { }

当我通过 bison --verbose 运行我的 .y 文件时,我看到:

state 51
   11 set_existence: expr . IN set
   12              | expr . NOT IN set
   34 expr: expr . binary_op expr
   34     | expr binary_op expr .

   ...
   NOT    shift, and go to state 26
   AND    shift, and go to state 27
   OR     shift, and go to state 28
   ....
   NOT     [reduce using rule 34 (expr)]
   AND     [reduce using rule 34 (expr)]
   OR      [reduce using rule 34 (expr)]

我没有看到任何实际解析二元运算符的问题,但看来我应该解决移位/归约问题。我无法弄清楚冲突在哪里—— set_existence 的产生似乎完全不相关。我最好的猜测(黑暗中的一枪)是,它可能与 EQ 用作二元运算符(相等比较)以及赋值(例如,“foo = bar = baz;”会设置)有关根据 bar 和 baz 是否相等,将 foo 设置为 true/false)。如果我将相等比较更改为 == ("foo = bar==baz;"),我的解析器将按预期运行,但仍然具有相同的移位/归约冲突。

编辑:我确实指定了关联性:

%left OR
%left AND
%left NOT
%left LT LE GT GE NE EQ
%left PLUS MINUS
%left TIMES MOD SLASH
%left POWER

I'm writing a parser in C with bison, and while it appears to work correctly in all circumstances I've tried so far, I get a bunch of shift/reduce warnings on my binary operators (and one on my unary NOT operator as well).

binary_op :
      PLUS { }
      | MINUS { }
      | TIMES { }
      | SLASH { }
      | POWER { }
      | AND { }
      | OR { }
      | LE { }
      | LT { }
      | GE { }
      | GT { }
      | EQ { }
      | NE { }
      | MOD { }
    ;

unary_op :
    NOT { }
    ;

expr :
    ...
    | unary_op expr { }
    | expr binary_op expr { }

When I run my .y file through bison --verbose, I see:

state 51
   11 set_existence: expr . IN set
   12              | expr . NOT IN set
   34 expr: expr . binary_op expr
   34     | expr binary_op expr .

   ...
   NOT    shift, and go to state 26
   AND    shift, and go to state 27
   OR     shift, and go to state 28
   ....
   NOT     [reduce using rule 34 (expr)]
   AND     [reduce using rule 34 (expr)]
   OR      [reduce using rule 34 (expr)]

I don't see any issues actually parsing binary operators, but it seems I should probably resolve the shift/reduce issues anyway. I can't figure out where the conflict is -- the set_existence productions seem completely unrelated. My best guess (a shot in the dark) is that it could have something to do with the fact that EQ is used as a binary operator (equality comparison) as well as assignment (eg, "foo = bar = baz;" would set foo to true/false based on whether bar and baz are equal). If I change my equality comparison to be == ("foo = bar==baz;"), my parser acts as expected but still has the same shift/reduce conflicts.

EDIT: I do have associativity specified:

%left OR
%left AND
%left NOT
%left LT LE GT GE NE EQ
%left PLUS MINUS
%left TIMES MOD SLASH
%left POWER

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

居里长安 2024-10-03 18:03:56

有几种方法可以避免这种情况。第一种是使用 %left%right%nonassoc 命令指定优先级(请参阅 手册)。

我个人更喜欢的另一个选项是将优先级直接编码到语法中。例如,下面是简单算术表达式的 BNF:

expr ::= term | expr + term
term ::= factor | term * factor
factor ::= number | ( expr )

这消除了语法级别的二义性解析。

There are a couple of ways to avoid this. The first is to use the %left, %right and %nonassoc commands to specify the precedence level (see the manual).

The other option, which I personally prefer, is to encode the precedence directly into the grammar. For example, here is a BNF for simple arithmetic expressions:

expr ::= term | expr + term
term ::= factor | term * factor
factor ::= number | ( expr )

This eliminates the ambiguous parse at the grammar level.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文