zig*_*tar 4 parsing haskell parsec
是否可以使用其中一个解析库(例如Parsec
)来解析与String不同的东西?我该怎么做?
为简单起见,我们假设输入是一个int列表[Int]
.任务可能是
(S+L+)*
,其中S
数字小于10,并且L
是大于或等于10的数字.(Int,Int)
,其中fst
是的产品S
和snd
为的产品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
Run Code Online (Sandbox Code Playgroud)
试一试:
*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
Run Code Online (Sandbox Code Playgroud)
请注意错误消息中的笨拙的行/列格式
当然可以写一个函数 sanitiseSourcePos :: SourcePos -> MyListPosition