微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Bison 中解析函数调用例如 `exp '(' exp ')'`:导致移位/减少错误优先级问题

如何解决在 Bison 中解析函数调用例如 `exp '(' exp ')'`:导致移位/减少错误优先级问题

我正在尝试解析一个函数调用(目前只有一个参数,但当我让它工作时,我会允许多个)。

假设 exp 定义为

%left '+'
%precedence CALL
exp:
    exp '+' exp { ... }
|   exp '(' exp ')' %prec CALL { ... }
|   LIteraL { ... }
;

这造成了歧义。如果我使用 -Wcounterexamples,那么它说 exp '+' exp · '(' exp ')' 可以通过两种方式解析,在 '(' 处移动或减少。

calc.y: warning: shift/reduce conflict on token '(' [-Wcounterexamples]
  Example: exp '+' exp • '(' exp ')'
  Shift derivation
    exp
    ↳ exp '+' exp
              ↳ exp • '(' exp ')'
  Example: exp '+' exp • '(' exp ')'
  Reduce derivation
    exp
    ↳ exp             '(' exp ')'
      ↳ exp '+' exp •

它似乎不知道调用的优先级应该高于还是低于 +。我该怎么做才能确保它知道 x+y(z) 应该等同于 x+(y(z)) 而不是 (x+y)(z)

Bison: strange shift-reduce conflict 似乎相关。

解决方法

您告诉 bison 产生式 gender = int(input("enter your gender as a number from the following \n Male: 1 \n Female: 2 \n ")) height = int(input("Please enter your height in inches: ")) age = int(input("Please enter your age: ")) weight = int(input("Enter your weight in lbs: ")) exercise = int(input( "How much exercise do you do during the week (enter number) \n little to no: 1 \n light: 2 \n moderate: 3 \n heavy: 4 \n ")) if gender == 1: BMR = 66 + (6.3 * weight) + (12.9 * height) - (6.8 * age) elif gender == 2: BMR = 655 + (4.3 * weight) + (4.7 * height) - (4.7 * age) if gender == 1: if exercise == 1: cal = BMR * 1.2 elif exercise == 2: cal = BMR * 1.375 elif exercise == 3: cal = BMR * 1.55 elif exercise == 4: cal = BMR * 1.8 else: if exercise == 1: cal = BMR * 1.2 elif exercise == 2: cal = BMR * 1.375 elif exercise == 3: cal = BMR * 1.55 elif exercise == 4: cal = BMR * 1.8 if gender == 1: TotalCal = BMR * 1.2 # print(mTotalCal) else: TotalCal = BMR * 1.2 # print(fTotalCal) loseWeight = str(input("do you want to loose weight? if yes,enter Y: \n if no enter N: \n ")) if loseWeight == "Y": yesWeight = int(input("How much weight do you want to loose (lbs) ? ")) else: print("thank you for using Nakul Industries health program!") weeks = yesWeight days = weeks * 7 months = days / 30 if gender == 1: newCal = TotalCal - 500 else: newCal = TotalCal - 500 if newCal < 1200: print("WARNING! your total intake will be less then 1200 calories,please consult a doctor before following this.") print( "In order to lose " + yesWeight + ",it will take " + weeks + " weeks " + "\n" + "or " + days + " days" + "\n or " + "approximately " + months + " months.") else: print( "In order to lose " + yesWeight + ",it will take " + weeks + " weeks " + "\n" + "or " + days + " days" + "\n or " + "approximately " + months + " months.") 和先行符号 { "mocha.files.glob": "test/**/*.spec.js","mocha.requires": [],"mocha.env": { "NODE_ENV": "test" },"mocha.sideBarOptions": { "lens": true,"decoration": true,"autoUpdateTime": 1000,"showDebugTestStatus": true } 的相对优先级。但是您还没有告诉 bison 产生式 exp: exp '(' exp ')' 和先行符号 + 的相对优先级。这就是为什么你在前瞻符号 exp: exp '+' exp

上有冲突的原因

请记住,优先级比较总是在产生式(可能会减少)和前瞻符号(可能会移位)之间进行。我知道 yacc/bison 使它看起来像是两个符号之间的比较,但这是一种错觉。每个产生式都由一个符号表示——默认情况下是最右边的终端——但就目前而言。恕我直言,这种约定对于简单的情况很直观,但否则会令人困惑。

最简单的解决方案是用符号 ( 确定调用产生式的优先级,而不是发明一个伪令牌。也就是说,将 '(' 声明更改为 (,并将优先规则中的 %prec 替换为 %prec '('

(实际上,您并不真正需要 CALL 声明,因为与 ( 前瞻标记不可能发生冲突。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。