Compiler construction 删除减少/减少冲突

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

我已经为一种语言创建了一个编译器,该语言具有如下语法,如ML Yacc所定义(起始符号为“program”,在底部定义):

这个语法很好,但现在我想介绍参数多态性,因此在语法中添加了以下结果:

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