我是 Haskell 的初学者,所以很明显我做错了什么......
在尝试解析时,我陷入了前瞻问题"1:1,2, 2:18, 3:100"
。[(1,1), (1,2), (2,18), (3,100)]
要知道一个数字是否是诗句编号,它应该向前看一个冒号,因为那样它是一个章节编号。
问题在于最后一个函数verseNr
,如果后面没有冒号,它应该解析+消耗数字,否则失败而不消耗任何东西(将数字作为章节号解析refGroupByChapter
)。
除了这个问题,它似乎工作得很好:)
import Text.ParserCombinators.Parsec
main = do
case (parse refString "(unknown)" "1:1,2, 2:18, 3:100") of
Left e -> do putStr "parse error at "; print e
Right x -> print x -- expecting: [(1,1), (1,2), (2,18), (3,100)]
refString :: GenParser Char st [(Int, Int)]
refString = do
refGroups <- many refGroupByChapter
eof
return $ concat $ map flatten refGroups
where flatten (_, []) = []
flatten (c, v:vs) = (c, v):(flatten (c, vs))
refGroupByChapter :: GenParser Char st (Int, [Int])
refGroupByChapter = do
chapterNum <- many digit
char ':'
verseNums <- verseNrs
return ((read chapterNum :: Int), verseNums)
verseNrs :: GenParser Char st [Int]
verseNrs = do
first <- verseNr
remaining <- remainingVerseNrs
return (first:remaining)
where
remainingVerseNrs = do -- allow for spaces around the commas
(spaces >> oneOf "," >> spaces >> verseNrs) <|> (return [])
verseNr = try $ do
n <- many1 digit
notFollowedBy $ char ':' -- if followed by a ':' it's a chapter number
return (read n :: Int)