]> gitweb @ CieloNegro.org - Rakka.git/blobdiff - Rakka/Wiki/Parser.hs
The experimental change worked well.
[Rakka.git] / Rakka / Wiki / Parser.hs
index 968e6451673a72ad680a5b9c4c391d68b3cdfc81..0125419c45d6d3fda915dfb8785462ec3572b00e 100644 (file)
@@ -3,80 +3,99 @@ module Rakka.Wiki.Parser
     )
     where
 
-import           Data.Char
 import           Rakka.Wiki
 import           Text.ParserCombinators.Parsec
 
 
 wikiPage :: Parser WikiPage
-wikiPage = do xs <- many (try wikiElement)
-              skipMany comment
+wikiPage = do xs <- many (try blockElement)
+              skipMany ( comment
+                         <|>
+                         (newline >> return ())
+                       )
               eof
               return xs
 
 
-wikiElement :: Parser WikiElement
-wikiElement = skipMany comment >>
-              ( try (blockElement >>= return . Block)
-                <|>
-                try (inlineElement >>= return . Inline)
-              )
-
-
 blockElement :: Parser BlockElement
-blockElement = ( try heading
+blockElement = skipMany ( comment
+                          <|>
+                          (newline >> return ())
+                        )
+               >>
+               ( heading
                  <|>
-                 try emptyLine
+                 paragraph
                )
 
 
 heading :: Parser BlockElement
-heading = foldr (<|>) pzero (map (try . heading') [1..5])
+heading = foldr (<|>) pzero (map heading' [1..5])
           <?>
           "heading"
     where
       heading' :: Int -> Parser BlockElement
-      heading' n = do count n (char '=')
-                      notFollowedBy (char '=')
+      heading' n = do try $ do count n (char '=')
+                               notFollowedBy (char '=')
                       ws
                       x  <- notFollowedBy (char '=') >> anyChar
-                      xs <- manyTill anyChar (try $ ws >> (count n (char '=')))
+                      xs <- manyTill anyChar (try $ ws >> ( count n (char '=')
+                                                            <?>
+                                                            ("trailing " ++ take n (repeat '='))
+                                                          )
+                                             )
                       ws
                       eol
                       return (Heading n (x:xs))
 
 
-emptyLine :: Parser BlockElement
-emptyLine = count 2 newline >> many newline >> return EmptyLine
-            <?>
-            "empty line"
+paragraph :: Parser BlockElement
+paragraph = paragraph' >>= return . Paragraph
+    where
+      paragraph' :: Parser [InlineElement]
+      paragraph' = do x  <- inlineElement
+                      xs <- try ( do newline
+                                     eof
+                                     return []
+                                  -- \n で文字列が終はってゐたら、ここ
+                                  -- で終了。
+                                )
+                            <|>
+                            try ( do newline
+                                     ((oneOf ('\n':blockSymbols) >> pzero) <|> return ())
+                                     ys <- (paragraph' <|> return [])
+                                     return (Text "\n" : ys)
+                                  -- \n があり、その次に \n または
+                                  -- blockSymbols があれば、fail して
+                                  -- 最初の newline を讀んだ所まで卷き
+                                  -- 戻す。
+                                )
+                            <|>
+                            try paragraph'
+                            -- それ以外の場合は次の inlineElement から
+                            -- を讀んで見る。但し一つも無くても良い。
+                            <|>
+                            return [] -- 全部失敗したらここで終了。
+                      return (x:xs)
 
 
 inlineElement :: Parser InlineElement
-inlineElement = ( try text
+inlineElement = skipMany comment
+                >>
+                ( try text
                   <|>
                   try pageLink
                 )
 
 
 text :: Parser InlineElement
-text = text' >>= return . Text
-    where
-      text' :: Parser String
-      text' = do x <- noneOf inlineSymbols
-                 case x of
-                   -- 單獨の \n は受け入れる。
-                   '\n' -> return [x]
-                   -- それ以外では \n を受け入れない。
-                   _    -> many (noneOf ('\n':inlineSymbols)) >>= return . (x:)
+text = many1 (noneOf ('\n':inlineSymbols)) >>= return . Text
 
 
 pageLink :: Parser InlineElement
 pageLink = do string "[["
-              page     <- option Nothing $
-                          do x  <- satisfy (\ c -> not (elem c "#|]" || isLower c))
-                             xs <- many (noneOf "#|]")
-                             return $ Just (x:xs)
+              page     <- option Nothing 
+                          (many1 (noneOf "#|]") >>= return . Just)
               fragment <- option Nothing
                           (char '#' >> many1 (noneOf "|]") >>= return . Just)
               text     <- option Nothing
@@ -108,6 +127,10 @@ comment = (try (string "<!--") >> skipTillEnd 1)
                           )
 
 
+blockSymbols :: [Char]
+blockSymbols = "="
+
+
 inlineSymbols :: [Char]
 inlineSymbols = "<["
 
@@ -120,7 +143,7 @@ ws = skipMany ( (oneOf " \t" >> return ())
 
 -- end of line
 eol :: Parser ()
-eol = ( (many1 newline >> return ())
+eol = ( (newline >> return ())
         <|>
         eof
       )