【问题标题】:Yacc/Bison, minimize amount by grouping math opsYacc/Bison,通过对数学运算进行分组来最小化数量
【发布时间】:2009-09-11 13:30:10
【问题描述】:

我在这里查看计算源http://epaperpress.com/lexandyacc/

我在 calc.y 中看到这些行

| expr '+' expr         { $$ = opr('+', 2, $1, $3); }
| expr '-' expr         { $$ = opr('-', 2, $1, $3); }
| expr '*' expr         { $$ = opr('*', 2, $1, $3); }
| expr '/' expr         { $$ = opr('/', 2, $1, $3); }
| expr '<' expr         { $$ = opr('<', 2, $1, $3); }
| expr '>' expr         { $$ = opr('>', 2, $1, $3); }

有没有办法将它们分组?所以我可以写下面的东西吗?

| expr mathOp expr         { $$ = opr(mathOp, 2, $1, $3); }
| expr cmpOp  expr         { $$ = opr(cmpOp, 2, $1, $3); }

注意:我正在使用野牛。

【问题讨论】:

  • 为什么不一路走下去,把 mathOp/cmpOp 也结合起来呢?
  • @pax: cmp ops 返回布尔值,数学返回与它相同的类型(想想 C#。0!=false)。我认为它更容易分开。
  • 为什么想到 C#?您使用的是 Bison,因此使用的是 C/C++。组合起来要容易得多,尤其是当您无论如何都要调用相同的函数时。

标签: yacc bison


【解决方案1】:

像这样对它们进行分组的问题是您失去了规则的优先级——您只有一个规则具有不同的优先级,具体取决于它是哪个数学运算,哪个 bison/yacc 无法处理。也就是说,您可以将相同优先级的操作组合在一起

expr: expr mulOp expr { $$ = opr($2, 2, $1, $3); } %prec '*'
    | expr addOp expr { $$ = opr($2, 2, $1, $3); } %prec '+'
    | expr relOp expr { $$ = opr($2, 2, $1, $3); } %prec '<'
             :

mulOp: '*' { $$ = '*'; }
     | '/' { $$ = '/'; }
;

【讨论】:

  • +1 表示优先级!但是为什么不在词法分析阶段对 * 和 / 进行分组呢?
  • 你可以在词法分析阶段进行分组,但是如果你在其他上下文中使用这些字符标记可能会带来问题(例如,一元'*'用于指针取消引用)
【解决方案2】:

您可以通过两种方式做到这一点:

  • 在 lex 阶段定义对运算符的识别,并为终端符号(在您的语法 mathOp 中)提供运算符“+”、“-”的值...
  • 使用 mathOp 作为非终结符可以返回一些相关的值:

    mathOp : '+' { $$ = '+'; } | '-' { $$ = '-'; } ...

那么用法会是这样的(注意$2):

| expr mathOp expr         { $$ = opr($2, 2, $1, $3); }

也许你想定义更复杂的 mathOp 然后使用 %type

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多