1 module Rakka.Wiki.Parser
8 import Text.ParserCombinators.Parsec
11 wikiPage :: Parser WikiPage
12 wikiPage = do xs <- many (try wikiElement)
18 wikiElement :: Parser WikiElement
19 wikiElement = skipMany comment >>
20 ( try (blockElement >>= return . Block)
22 try (inlineElement >>= return . Inline)
26 blockElement :: Parser BlockElement
27 blockElement = ( try heading
33 heading :: Parser BlockElement
34 heading = foldr (<|>) pzero (map (try . heading') [1..5])
38 heading' :: Int -> Parser BlockElement
39 heading' n = do count n (char '=')
40 notFollowedBy (char '=')
42 x <- notFollowedBy (char '=') >> anyChar
43 xs <- manyTill anyChar (try $ ws >> (count n (char '=')))
46 return (Heading n (x:xs))
49 emptyLine :: Parser BlockElement
50 emptyLine = count 2 newline >> many newline >> return EmptyLine
55 inlineElement :: Parser InlineElement
56 inlineElement = ( try text
62 text :: Parser InlineElement
63 text = text' >>= return . Text
65 text' :: Parser String
66 text' = do x <- noneOf inlineSymbols
71 _ -> many (noneOf ('\n':inlineSymbols)) >>= return . (x:)
74 pageLink :: Parser InlineElement
75 pageLink = do string "[["
76 page <- option Nothing $
77 do x <- satisfy (\ c -> not (elem c "#|]" || isLower c))
78 xs <- many (noneOf "#|]")
80 fragment <- option Nothing
81 (char '#' >> many1 (noneOf "|]") >>= return . Just)
82 text <- option Nothing
83 (char '|' >> many1 (noneOf "]") >>= return . Just)
85 case (page, fragment) of
86 (Nothing, Nothing) -> pzero
90 return $ PageLink page fragment text
96 comment = (try (string "<!--") >> skipTillEnd 1)
100 skipTillEnd :: Int -> Parser ()
101 skipTillEnd level = ( (try (string "<!--") >> skipTillEnd (level + 1))
103 (try (string "-->") >> case level of
105 n -> skipTillEnd (n - 1))
107 (anyChar >> skipTillEnd level)
111 inlineSymbols :: [Char]
116 ws = skipMany ( (oneOf " \t" >> return ())
123 eol = ( (many1 newline >> return ())