我正在处理yacc文件以解析给定文件并将其转换为等效的c ++文件。我已根据提供的语法图创建了以下语法:
program: PROGRAMnumber id 'is' comp_stmt
;
comp_stmt: BEGINnumber statement symbol ENDnumber
;
statement: statement SEMInumber statement
| id EQnumber expression
| PRINTnumber expression
| declaration
;
declaration: VARnumber id
;
expression: term
;
term: term as_op term
| MINUSnumber term
| factor
;
factor: factor md_op factor
| ICONSTnumber
| id
| RPARENnumber expression LPARENnumber
;
as_op: PLUSnumber
| MINUSnumber
;
md_op: TIMESnumber
| DIVnumber
;
symbol: SEMInumber
| COMMAnumber
;
id: IDnumber
| id symbol id
;
我剩下的唯一问题是我在尝试使用yacc进行编译时收到此错误。
conflicts: 14 shift/reduce
calc.y:103.17-111.41: warning: rule useless in parser due to conflicts: declaration: VARnumber id
我已经解决了我遇到的唯一其他冲突,但我不确定这场冲突的解决方案是什么。它应匹配的行格式为
var a, b, c, d;
或
var a;
答案 0 :(得分:4)
用于派生列表的所有产品都不明确,因此会产生减少/减少冲突。例如:
id: id symbol id
当有三个标识符时,显然会有歧义:前两个要先减少,还是最后两个?通常的列表习惯是左递归:
id_list: id | id_list `,` id
对于大多数语言而言,对于使用分号终止而不是分隔的语句来说这是不正确的,但该模型适用于逗号 - 标识符的分隔列表,或者加法运算符的左关联序列。
对于陈述,您可能需要更类似的内容:
statement_list: | statement_list statement ';'
说到symbol
,你真的相信,
和;
具有相同的句法功能吗?这似乎不太可能,因为您编写var a, b, c, d;
而不是var a; b, c; d,
。
野牛产生的“无用规则”警告正是因为你的语法允许id
用分号分隔。当解析器看到"var" ID
;
作为预测时,它首先将ID
缩减为id
,然后需要决定是否将var id
缩减为declaration
或者转移;
以便稍后将其缩减为symbol
,然后继续缩减id symbol id
。在没有优先规则的情况下,野牛总是解决转移/减少冲突而转向,这就是它在这种情况下的作用。但结果是永远不可能将"var" id
减少到declaration
,因为减少冲突的解决方案使得生产无用,这或多或少是警告所说的。