我的一些语法规则出了问题。
语法如下:
defLINES : carrRet
| defLine carrRet
| defLines defLine carrRet
;
defLine : error carrRet {yyerrok();}
| "DEF" kwType attrbt ID
| "DEF" kwType ID fieldSuff
;
kwType : "INT"
| "REAL"
;
fieldSuff: "[" expr "]"
| "[" expr "," expr "]"
;
attrbt : /* nothing */
| "PHU" intValue
;
使用输入检查:
DEF INT testvar1
DEF REAL testvar2
对于此输入,应使用头部“defLine”的第二个生产规则。
为什么不呢?将始终使用第三条规则并抛出错误
Unexpected 'carRet', '[' expected.
非常感谢你的帮助, 亚历
答案 0 :(得分:1)
该语法肯定会产生至少一次转移/减少冲突,同时警告生产attrbt: /* nothing */
因冲突而无效。 (如果情况并非如此,那是因为GPPG没有提供与野牛一样多的警告。但我确信它至少会标记转移/减少冲突。)
冲突出现在规则中:
defLine : "DEF" kwType attrbt ID
defLine : "DEF" kwType ID fieldSuff
因为attrbt
可以为空,但在第二条规则中不能位于ID
之前。假设解析器遇到DEF INT
,下一个符号为ID
。此时,解析器不知道要使用defLine
的两个产品中的哪一个,但差异很重要。在第一种情况下,解析器必须在移位attrbt
之前减少空ID
。在第二种情况下,创建attrbt
将是一个错误。
类似Yacc的解析器生成器总是解决移位/减少冲突而转移(除非有优先级声明),因此在这种情况下ID
将始终被移位。这意味着不可能减少生产attrbt: /* nothing */
。 (至少,野牛会警告你这个事实。
此外,由于在这种情况下会发生ID
的转换,因此只有defLine
的第二次生成可用,因此解析器需要fieldStuff
来跟随ID
并且fieldStuff
必须以[
开头。因此,您遇到的解析错误。
要解决此问题,您需要删除shift / reduce冲突。一种简单的方法是在attrbt
制作中允许defLine
(您可以在语义操作中检测错误)。另一种可能性是删除attrbt
的空制作并明确允许它丢失:
attrbt : "PHU" intValue
defLine : "DEF" kwType ID
| "DEF" kwType attrbt ID
| "DEF" kwType ID fieldSuff