首页 > 解决方案 > 理解 Text.ParserCombinators.ReadP.sepBy1

问题描述

我对sepBy1的结果感到困惑

以下代码在 ghci 中运行

λ> import Text.ParserCombinators.ReadP
λ> import Data.Char

λ> readP_to_S ((munch1 isAlpha) `sepBy1` (char '-')) "dish-dash-dosh"
[(["dish"],"-dash-dosh"),(["dish","dash"],"-dosh"),["dish","dash","dosh"],"")]

  1. 为什么输出不是这种情况[(["dish","dash","dosh"],"")]

以下doctest只是失败的一个

-- |
-- >>> readP_to_S readValues "dish-dash-dosh"
-- [(V ["dish","dash","dosh"],"")
readValues :: ReadP Value
readValues = do
  xs <- (munch isAlpha) `sepBy1` (char '-')
  pure $ V xs
Main.hs:64: failure in expression `readP_to_S readValues "dish-dash-dosh"'
expected: [(V ["dish","dash","dosh"],"")
 but got: [(V ["dish"],"-dash-dosh"),(V ["dish","dash"],"-dosh"),(V ["dish","dash","dosh"],"")]

我正在使用我的数据ReadPRead例如,代码Read正在运行,但我很困惑。

没有做过复杂的解析,我一直认为运行ReadP会以单元素列表的形式返回输出[(result,"")],显然不是这样。

data Value = V [String]
  deriving Show

-- |
-- >>> read "dish-dash-dosh" :: Value
-- V ["dish","dash","dosh"]
--
instance Read Value where
  readPrec = readP_to_Prec (const readValues)

  1. 是否read只有在sndlast中没有任何内容时才会成功[(Value,String)],此列表中的其他元素在任何地方都未使用?

我知道这样做的替代方法。这个问题完全是关于理解sepBy输出和它的使用。

标签: parsinghaskellparser-combinators

解决方案


运行ReadP将返回所有可能的解析。您可以通过指定解析后应该发生的事情来限制有效解析的数量sepBy1,例如输入结束或其他一些句法元素。

例如,尝试类似:

readValues = do
  xs <- (munch isAlpha) `sepBy1` (char '-')
  eof
  pure $ V xs

附录...

ReadS类型遵循经典 Hutton 和 Meijer 论文Monadic Parsing in Haskell中介绍的 monadic parsing 的发展。从那里的小文档中,我收集到ReadP实现所有替代方案的并行探索。ReadP对创建动作有很多支持,而不是ReadS对. 当我使用该模块时,我刚刚进行了该操作的第一个匹配项(如果它是空列表,则返回一个解析错误。)ReadPreadP_to_SReadS

ReadPrecmonad 用于支持优先级,它基本上是——ReaderT Int ReadP这里Int是当前的优先级。同样,看起来您从ReadP解析器开始,然后使用or将其转换为ReadPrec操作。要运行它,您可以像在案例中一样使用它。liftreadP_to_PrecreadPrec_to_SReadP


推荐阅读