【发布时间】:2016-10-06 17:35:32
【问题描述】:
在使用快乐解析器编写的函数式语言编译器中,它与 yacc/bison 非常相似,我使用以下规则实现了列表和列表一些核心函数 map、concat 和 filter:
Exp:
...
| concat '(' Exp ',' Exp ')' { Concat $3 $5 }
| map '(' Exp ',' Exp ')' { Map $3 $5 }
| filter '(' Exp ',' Exp ')' { Filter $3 $5 }
这很好用,但在大多数函数式语言中没有括号或逗号,所以我宁愿写 map(myfun, [1,2,3]) 而不是map myfun [1,2,3]。语法上明显的修改如下:
Exp:
...
| concat Exp Exp { Concat $2 $3 }
| map Exp Exp { Map $2 $3 }
| filter Exp Exp { Filter $2 $3 }
但是这个修改包含很多reduce-reduce 冲突。如何在没有逗号和括号的情况下实现函数调用的解析?
我能提取的最小的冲突语法是这样的:
Exp :
-- Math
Exp '+' Exp { Op $1 Add $3 }
| Exp '-' Exp { Op $1 Sub $3 }
-- Literals
| num { Num $1 }
| '-' num %prec NEGATIVE { Num (-$2) }
-- Lists
| map Exp Exp { Map $2 $3 }
它会产生 4 个减少/减少冲突。删除任何规则也会导致冲突。如果您有兴趣,这里是full grammar。
【问题讨论】:
-
我把github上的语法转成bison,bison报没有冲突。
-
@ric 这是因为链接的完整语法具有我首先陈述的规则,而不是我真正想要的(我的帖子副本上的第二个示例)
-
:这就是为什么我们总是要求minimal reproducible example。
-
@rici 我已经用产生减少/减少冲突的最小语法更新了我的问题。我不确定您如何设法将其转换为野牛?如果您需要完整的文件,here it is
-
简化示例与
map f - 3 ...的模糊性有关,其中不清楚f是否是map的第一个参数(在这种情况下-3是否定的) number) 或中缀运算符的一部分。我怀疑这是否可以使用优先声明来解决,但我可能是错的。它当然可以(在某种意义上)语法上解决,就像 Haskell 本身一样;在 Haskell 中,如果你想写负数,你必须使用括号(map f (-3)),也许这对你的语言也是可以接受的。稍后我会尝试写一个答案。