【发布时间】:2023-03-23 17:15:01
【问题描述】:
我尝试了一下使用 Haskell 的解析器生成器,这里使用的是 Happy。我以前使用解析器组合器,例如 Parsec,而我现在无法实现的一件事是动态添加(在执行期间)新的外部定义的运算符。例如,Haskell 有一些基本的运算符,但我们可以添加更多,赋予它们优先级和固定性。所以我想知道如何按照 Haskell 设计(查看下面要解析的示例代码)用 Happy 重现它,如果它不是很可行,或者是否应该通过解析器组合器来完成。
-- Adding the new operator
infixl 5 ++
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : xs ++ ys
-- Using the new operator taking into consideration fixity and precedence during parsing
example = "Hello, " ++ "world!"
【问题讨论】:
-
提示:你可以检查 GHC 的语法:github.com/ghc/ghc/blob/master/compiler/parser/Parser.y
-
IIRC,GHC 解析所有忽略固定点的中缀运算符,然后根据固定点转换 AST。本质上,优先级和关联性在解析后是固定的。我不知道这是否真的更容易——也许是这样。
-
@chi – 所以它会是一个“解析后”元素?
-
嗯,它发生在类型检查期间,在“正确”的时间。一般的想法是:GHC 已经推断出
10 :: Num a => a所以,如果我们以这种方式注释10,我们不会告诉 GHC 任何它不知道的东西——这是一个空操作。相反,f的类型被推断(因为 MR)到其他东西,所以注释很重要。完整的解释有点棘手,需要深入挖掘类型系统、GHC Core、MR 和其他一些血腥细节。
标签: parsing haskell parser-generator happy