gpt4 book ai didi

parsing - 使用 Haskell 的 Parsec 进行编程语言转换器

转载 作者:行者123 更新时间:2023-12-04 13:20:26 28 4
gpt4 key购买 nike

假设我有两种语言(A 和 B)。我的目标是编写某种类型的程序,将 A 中的语法转换为 B 的等价物。目前我的解决方案是使用 Haskell 的 Parsec 来执行此任务。然而,作为一个刚接触 Haskell 和函数式编程的人,在 Parsec 中找到一个简单的例子是相当困难的。我在网上找到的示例要么是不完整的示例(对于新的 Haskell 程序员来说令人沮丧),要么与我的目标相差太多。

那么有人可以为我提供一个非常简单和明确的例子,说明使用 Parsec 来实现与我想要实现的目标相关的事情吗?甚至可能还有一些与我的目标相似的教程。

谢谢。

最佳答案

考虑以下 CSV 文档的简单语法(在 ABNF 中):

csv   = *crow
crow = *(ccell ',') ccell CR
ccell = "'" *(ALPHA / DIGIT) "'"

我们想编写一个转换器,将该语法转换为 TSV(制表符分隔值)文档:
tsv   = *trow
trow = *(tcell HTAB) tcell CR
tcell = DQUOTE *(ALPHA / DIGIT) DQUOTE

首先,让我们创建一个代数数据类型来描述我们的抽象语法树。包括类型同义词以方便理解:
data XSV  = [Row]
type Row = [Cell]
type Cell = String

为这种语法编写解析器非常简单。我们编写一个解析器,就好像我们要描述 ABNF:
csv :: Parser XSV
csv = XSV <$> many crow

crow :: Parser Row
crow = do cells <- ccell `sepBy` (char ',')
newline
return cells

ccell :: Parser Cell
ccell = do char '\''
content <- many (digit <|> letter)
char '\''
return content

此解析器使用 do -符号。在 do 之后,一系列语句如下。对于解析器,这些语句只是其他解析器。可以使用 <-绑定(bind)解析器的结果。这样,通过链接多个较小的解析器来构建一个大解析器。为了获得有趣的效果,还可以使用特殊的组合子组合解析器(例如 a <|> b ,它解析 abmany a ,它解析尽可能多的 a s)。请注意 Parsec 默认不回溯。如果解析器在使用字符后可能会失败,请在其前面加上 try为一个实例启用回溯。 try减慢解析速度。

结果是解析器 csv它将我们的 CSV 文档解析为抽象语法树。现在很容易将其转换为另一种语言(例如 TSV):
xsvToTSV :: XSV -> String
xsvToTSV xst = unlines (map toLines xst) where
toLines = intersperse '\t'

将这两件事联系起来,就得到了一个转换函数:
csvToTSV :: String -> Maybe String
csvToTSV document = case parse csv "" document of
Left _ -> Nothing
Right xsv -> xsvToTSV xsv

仅此而已! Parsec 有许多其他功能来构建极其复杂的解析器。本书 Real World Haskell有一个关于解析器的好章节,但它有点过时了。不过,其中大部分仍然是正确的。如果您还有其他问题,请随时提问。

关于parsing - 使用 Haskell 的 Parsec 进行编程语言转换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11401766/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com