【问题标题】:How to remove commas and parenthesis from function calls如何从函数调用中删除逗号和括号
【发布时间】:2016-10-06 17:35:32
【问题描述】:

在使用快乐解析器编写的函数式语言编译器中,它与 yacc/bison 非常相似,我使用以下规则实现了列表和列表一些核心函数 mapconcatfilter

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)),也许这对你的语言也是可以接受的。稍后我会尝试写一个答案。

标签: grammar bison yacc happy


【解决方案1】:

问题在于,由于函数应用程序中没有标记,因此基于标记的优先级冲突解决不能很好地工作——当它试图决定一个可能是函数应用程序的转变并减少其他一些应用程序时表达式,前瞻标记是参数表达式开头的任何内容;没有可以使用的“空白”标记。

要解决该问题并使其正常工作,您需要将每个可能是表达式的标记(FIRST(Exp) 中的每个标记)的优先级设置为函数应用程序的优先级。如果这些标记中的任何一个需要其他优先级(例如,任何可能是中缀或前缀的标记),这将变得更加棘手并且可能不起作用。

一个可能更好的替代方法是根本不使用优先规则——相反,为每个优先级别使用不同的规则来消除语法的歧义:

Exp: Term | Exp '+' Term
Term: Factor | Term '*' Factor
Factor: Primary | Factor Primary
Primary: num | id | '(' Exp ')'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 2020-08-05
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    相关资源
    最近更新 更多