Haskell 秒差距解析字符串块以映射值
Haskell Parsec parsing chunks of string to map values
我正在尝试解析一个字符串,例如
AA{A}{END}}
使用给定地图:fromList [("{",43),("}",44),("{END}",255),("A",65)]
、
所以期望的输出是:[65,65,43,65,44,255,44]
看起来是直接在地图中搜索最长的前缀 Haskell,但我如何使用 Parsec 解析它?它类似于 this question,但这里我应该 return Word8
值而不是 'choice'.
解析的字符串
您首先需要编写一个解析器,将 (Word8, Int)
元组和 returns Parser Word8
值作为输入。
keyValParser :: (String, Word8) -> Parser Word8
keyValParser (s,v) = try (string s) >> return v
上面的解析器使用 try
而不是 string
解析器,因为 Parsec 有即使失败也会消耗匹配字符的坏习惯。如果 try (string s)
部分成功,它 returns 来自元组的 Word8
值。
现在您可以将您的输入列表映射到 keyValParser
以构建您正在寻找的解析器:
parser :: [(String, Word8)] -> Parser [Word8]
parser = many . choice . map keyValParser
运行 这个在 GHCi 中使用 parseTest
的解析器产生:
> let lookup = [("{",43),("}",44),("{END}",255),("A",65)]
> parseTest (parser lookup) "AA{A}{END}}"
[65,65,43,65,44,43]
但是等等!这不太对。现在的问题是 choice
在第一个匹配的解析器处停止,字符串 {END}
首先匹配 {
,因此 returns 43
。您可以通过首先使用 sortBy (flip $ comparing (length . fst))
:
按最长文本排序 lookup
值来解决此问题
parser :: [(String, Word8)] -> Parser [Word8]
parser = many . choice . map keyValParser . sortBy (flip $ comparing (length . fst))
现在你得到了正确的结果:
> let lookup = [("{",43),("}",44),("{END}",255),("A",65)]
> parseTest (parser lookup) "AA{A}{END}}"
[65,65,43,65,44,255,44]
我正在尝试解析一个字符串,例如
AA{A}{END}}
使用给定地图:fromList [("{",43),("}",44),("{END}",255),("A",65)]
、
所以期望的输出是:[65,65,43,65,44,255,44]
看起来是直接在地图中搜索最长的前缀 Haskell,但我如何使用 Parsec 解析它?它类似于 this question,但这里我应该 return Word8
值而不是 'choice'.
您首先需要编写一个解析器,将 (Word8, Int)
元组和 returns Parser Word8
值作为输入。
keyValParser :: (String, Word8) -> Parser Word8
keyValParser (s,v) = try (string s) >> return v
上面的解析器使用 try
而不是 string
解析器,因为 Parsec 有即使失败也会消耗匹配字符的坏习惯。如果 try (string s)
部分成功,它 returns 来自元组的 Word8
值。
现在您可以将您的输入列表映射到 keyValParser
以构建您正在寻找的解析器:
parser :: [(String, Word8)] -> Parser [Word8]
parser = many . choice . map keyValParser
运行 这个在 GHCi 中使用 parseTest
的解析器产生:
> let lookup = [("{",43),("}",44),("{END}",255),("A",65)]
> parseTest (parser lookup) "AA{A}{END}}"
[65,65,43,65,44,43]
但是等等!这不太对。现在的问题是 choice
在第一个匹配的解析器处停止,字符串 {END}
首先匹配 {
,因此 returns 43
。您可以通过首先使用 sortBy (flip $ comparing (length . fst))
:
lookup
值来解决此问题
parser :: [(String, Word8)] -> Parser [Word8]
parser = many . choice . map keyValParser . sortBy (flip $ comparing (length . fst))
现在你得到了正确的结果:
> let lookup = [("{",43),("}",44),("{END}",255),("A",65)]
> parseTest (parser lookup) "AA{A}{END}}"
[65,65,43,65,44,255,44]