1 module Rakka.Wiki.Parser
7 import Text.ParserCombinators.Parsec
10 wikiPage :: Parser WikiPage
11 wikiPage = do xs <- many (try blockElement)
14 (newline >> return ())
20 blockElement :: Parser BlockElement
21 blockElement = skipMany ( comment
23 (newline >> return ())
32 heading :: Parser BlockElement
33 heading = foldr (<|>) pzero (map heading' [1..5])
37 heading' :: Int -> Parser BlockElement
38 heading' n = do try $ do count n (char '=')
39 notFollowedBy (char '=')
41 x <- notFollowedBy (char '=') >> anyChar
42 xs <- manyTill anyChar (try $ ws >> ( count n (char '=')
44 ("trailing " ++ take n (repeat '='))
49 return (Heading n (x:xs))
52 paragraph :: Parser BlockElement
53 paragraph = paragraph' >>= return . Paragraph
55 paragraph' :: Parser [InlineElement]
56 paragraph' = do x <- inlineElement
57 xs <- try ( do newline
65 ((oneOf ('\n':blockSymbols) >> pzero) <|> return ())
66 ys <- (paragraph' <|> return [])
67 return (Text "\n" : ys)
69 -- blockSymbols があれば、fail して
70 -- 最初の newline を讀んだ所まで卷き
75 -- それ以外の場合は次の inlineElement から
76 -- を讀んで見る。但し一つも無くても良い。
78 return [] -- 全部失敗したらここで終了。
82 inlineElement :: Parser InlineElement
83 inlineElement = skipMany comment
91 text :: Parser InlineElement
92 text = many1 (noneOf ('\n':inlineSymbols)) >>= return . Text
95 pageLink :: Parser InlineElement
96 pageLink = do string "[["
97 page <- option Nothing
98 (many1 (noneOf "#|]") >>= return . Just)
99 fragment <- option Nothing
100 (char '#' >> many1 (noneOf "|]") >>= return . Just)
101 text <- option Nothing
102 (char '|' >> many1 (noneOf "]") >>= return . Just)
104 case (page, fragment) of
105 (Nothing, Nothing) -> pzero
109 return $ PageLink page fragment text
115 comment = (try (string "<!--") >> skipTillEnd 1)
119 skipTillEnd :: Int -> Parser ()
120 skipTillEnd level = ( (try (string "<!--") >> skipTillEnd (level + 1))
122 (try (string "-->") >> case level of
124 n -> skipTillEnd (n - 1))
126 (anyChar >> skipTillEnd level)
130 blockSymbols :: [Char]
134 inlineSymbols :: [Char]
139 ws = skipMany ( (oneOf " \t" >> return ())
146 eol = ( (newline >> return ())