如何解决在 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 举报,一经查实,本站将立刻删除。