parsing - 如何使用 Haskell 解析器解析任意列表?

标签 parsing haskell parsec

是否可以使用解析库之一(例如 Parsec)来解析与字符串不同的内容?我该怎么做?

为了简单起见,我们假设输入是一个整数列表[Int]。任务可能是

  • 删除前导零
  • 将其余部分解析为模式 (S+L+)*,其中 S 是小于 10 的数字,L 是大于或等于 10 的数字。
  • 返回元组列表(Int,Int),其中fstSsnd的乘积code> 是 L 个整数的乘积

如果有人能够展示如何编写这样的解析器(或类似的东西),那就太好了。

最佳答案

是的,正如 user5402 指出的那样,Parsec 可以解析 Stream 的任何实例,包括任意列表。由于没有预定义的标记解析器(与文本一样),您必须使用例如以下方法来推出自己的标记解析器(下面的myToken): tokenPrim

我觉得唯一有点尴尬的是“源位置”的处理。 SourcePos 是一个抽象类型(而不是类型类),迫使我使用它的“文件名/行/列”格式,这在这里感觉有点不自然。

无论如何,这是代码(为简洁起见,不跳过前导零)

import Text.Parsec

myToken ::  (Show a) => (a -> Bool) -> Parsec [a] () a
myToken test = tokenPrim show incPos $ justIf test where
  incPos pos _ _ = incSourceColumn pos 1
  justIf test x = if (test x) then Just x else Nothing

small = myToken  (< 10)
large = myToken  (>= 10)

smallLargePattern = do
  smallints <- many1 small
  largeints <- many1 large
  let prod = foldl1 (*)
  return (prod smallints, prod largeints)

myIntListParser :: Parsec [Int] () [(Int,Int)]
myIntListParser = many smallLargePattern

testMe :: [Int] -> [(Int, Int)]
testMe xs = case parse myIntListParser "your list" xs of
  Left err -> error $ show err
  Right result -> result

尝试一切:

*Main> testMe [1,2,55,33,3,5,99]
[(2,1815),(15,99)]
*Main> testMe [1,2,55,33,3,5,99,1]
*** Exception: "your list" (line 1, column 9):
unexpected end of input

请注意错误消息中尴尬的行/列格式

当然可以编写一个函数sanitiseSourcePos::SourcePos -> MyListPosition

关于parsing - 如何使用 Haskell 解析器解析任意列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27087820/

相关文章:

algorithm - 编写算术表达式解析器所需的技术

jquery - 如何解析这个 XML ajax 响应?

xml - 推出您自己的 XML 解析器/XML 解析算法?

Haskell -- 意外的预期类型

parsing - uu-parsinglib 中的计划外贪婪行为

在 Haskell 的 Parsec 中解析基于缩进的语法

haskell - 如何使用秒差距从文件中删除注释?

ios - pod 安装 [!] 错误 : Parsing unable to continue due to parsing error:

haskell - System.Plugins 加载器似乎在看到一次失败后假设失败

haskell - 映射到 RankNTypes 函数