Compiler construction 删除减少/减少冲突
我已经为一种语言创建了一个编译器,该语言具有如下语法,如ML Yacc所定义(起始符号为“program”,在底部定义): 这个语法很好,但现在我想介绍参数多态性,因此在语法中添加了以下结果:Compiler construction 删除减少/减少冲突,compiler-construction,yacc,shift-reduce-conflict,reduce-reduce-conflict,ml-yacc,Compiler Construction,Yacc,Shift Reduce Conflict,Reduce Reduce Conflict,Ml Yacc,我已经为一种语言创建了一个编译器,该语言具有如下语法,如ML Yacc所定义(起始符号为“program”,在底部定义): 这个语法很好,但现在我想介绍参数多态性,因此在语法中添加了以下结果: tyargs: LT typeList' GT ty: ID tyargs callExp: exp tyargs LPAREN expList RPAREN idList: ID COMMA idList
tyargs: LT typeList' GT
ty: ID tyargs
callExp: exp tyargs LPAREN expList RPAREN
idList: ID COMMA idList
| ID
tyvars: LT idList GT
functionDecl: FUN ID tyvars LPAREN declList RPAREN ARROW ty compoundStat
现在我得到了以下两个reduce/reduce冲突,我不知道如何解决
error: state 75: reduce/reduce conflict between rule 46 and rule 5 on GT
error: state 75: reduce/reduce conflict between rule 46 and rule 5 on COMMA
谁能告诉我如何消除这两个冲突
编辑:这是mlyacc的完整.desc输出。并不是说这一个也显示了两个良性的移位/减少错误,好吧,没有人回答,但你已经使语法变得非常模糊。有两种可能的产品:
LT ID GT
ID LT ID GT
举几个例子:
<a>
b<a>
B
它们是tyargs
还是tyvars
还是callExp
的开头?你的语法说两者都可以。因此,如果不对所使用的语言或规则进行一些更改,使用诸如ml-yacc之类的工具进行解析是非常困难的
如果不进一步解释语言结构,使用ml-yacc编译它会有困难。有人可能会向您展示一种更好的语法规则构造方法,使其不受这些工具的限制。问题在于,对于新规则,语法需要任意向前看,以区分
varDecl
和expStmt
之间的区别。这是因为LT
既是表达式的二进制运算符,又表示参数化类型的tyargs
列表的开始
一种可能的修复方法是引入一个新关键字来表示参数化类型或函数(如当前用于引入函数类型的FUN
关键字),这将允许解析器提前知道是将LT
视为运算符还是类型参数列表。
因此,您可以添加新规则,如:
ty: TYPE ID tyargs
callExpr: CALL ID tyargs LPAREN expList RPAREN
另一种可能是通过符号表使用lexer反馈——让lexer识别需要类型参数的标识符(通过在符号表中查找名称),并为它们返回不同的标记
第三种可能是使用一个更强大的解析器生成器,它可以处理更多的前瞻性,例如bison选项,或者只有一个shift/reduce错误是良性的——另一个是错误的歧义,相同的歧义(在小于和args类型之间)由于这两个reduce/reduce冲突……该语言仍然是无文本的——根据定义,它是用无上下文的BNF表示的。据我所知,这甚至是不含糊的。它只需要1个以上的令牌才能解析,而不是LALR(1)。@chrisdd-谢谢您的更正。你说得对,我急忙回答。
ty: TYPE ID tyargs
callExpr: CALL ID tyargs LPAREN expList RPAREN