|
|
|
@ -98,6 +98,47 @@ lineToList (Line tokens) = tokens
|
|
|
|
|
|
|
|
|
|
specialChars = "\\#*_[\n "
|
|
|
|
|
|
|
|
|
|
-- Makes a parser greedy. Instead of returning all possible parses, only the longest one is returned.
|
|
|
|
|
greedyParse :: ReadP a -> ReadP [a]
|
|
|
|
|
greedyParse parser = do
|
|
|
|
|
greedyParse1 parser <++ return []
|
|
|
|
|
|
|
|
|
|
-- Like greedyParse, but the parser must succeed atleast once.
|
|
|
|
|
greedyParse1 :: ReadP a -> ReadP [a]
|
|
|
|
|
greedyParse1 parser = do
|
|
|
|
|
parsed1 <- parser
|
|
|
|
|
parsed2 <- greedyParse1 parser <++ return []
|
|
|
|
|
return (parsed1 : parsed2)
|
|
|
|
|
|
|
|
|
|
prepend :: [a] -> [a] -> [a]
|
|
|
|
|
prepend x1 x2 = x1 ++ x2
|
|
|
|
|
|
|
|
|
|
append :: [a] -> [a] -> [a]
|
|
|
|
|
append x1 x2 = x2 ++ x1
|
|
|
|
|
|
|
|
|
|
-- Sequence two parsers, running one after the other and returning the result.
|
|
|
|
|
sequenceParse :: ReadP a -> ReadP a -> ReadP [a]
|
|
|
|
|
sequenceParse p1 p2 = twoElemList <$> p1 <*> p2
|
|
|
|
|
where
|
|
|
|
|
twoElemList elem1 elem2 = [elem1, elem2]
|
|
|
|
|
|
|
|
|
|
-- Parses p1 until p2 succeeds, but doesn't actually consume anything from p2.
|
|
|
|
|
-- Similar to manyTill, except manyTill's second parser actually consumes characters.
|
|
|
|
|
manyTillLazy :: ReadP a -> ReadP b -> ReadP [a]
|
|
|
|
|
manyTillLazy p1 p2 = do
|
|
|
|
|
res <- p1
|
|
|
|
|
remaining <- look
|
|
|
|
|
let p2res = readP_to_S p2 remaining
|
|
|
|
|
case p2res of
|
|
|
|
|
[] -> do
|
|
|
|
|
res2 <- manyTillLazy p1 p2
|
|
|
|
|
return (res : res2)
|
|
|
|
|
_ -> return [res]
|
|
|
|
|
|
|
|
|
|
-- Parse until EOL or EOF
|
|
|
|
|
parseTillEol :: ReadP String
|
|
|
|
|
parseTillEol = manyTill get (void (char '\n') <++ eof)
|
|
|
|
|
|
|
|
|
|
-- ---------------
|
|
|
|
|
|
|
|
|
|
-- Parse a markdown header, denoted by 1-6 #'s followed by some text, followed by EOL.
|
|
|
|
|