summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYuchen Pei <hi@ypei.me>2022-09-12 16:08:18 +1000
committerYuchen Pei <hi@ypei.me>2022-09-12 16:08:18 +1000
commit3afa538c7af2d2e092b482a67a25e8547d386820 (patch)
treef73f8f15ded66eafc551109979c852eebf562089 /src
parent0566547e07065581e2f45288eed63e4fb5874cf4 (diff)
separating out wikiparser and types and added config
Diffstat (limited to 'src')
-rw-r--r--src/Servall/Types.hs13
-rw-r--r--src/Servall/WikiParser.hs105
2 files changed, 118 insertions, 0 deletions
diff --git a/src/Servall/Types.hs b/src/Servall/Types.hs
new file mode 100644
index 0000000..e179e2c
--- /dev/null
+++ b/src/Servall/Types.hs
@@ -0,0 +1,13 @@
+module Servall.Types
+ ( WikiTemplate(..)
+ ) where
+
+import qualified Data.HashMap.Lazy as HM
+import Data.Text ( Text )
+
+data WikiTemplate = WikiTemplate
+ { wtName :: Text
+ -- , wtSubName :: Maybe Text
+ , wtFields :: HM.HashMap Text Text
+ }
+ deriving Show
diff --git a/src/Servall/WikiParser.hs b/src/Servall/WikiParser.hs
new file mode 100644
index 0000000..ec15e1c
--- /dev/null
+++ b/src/Servall/WikiParser.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Servall.WikiParser
+ ( parseWikiTemplates
+ ) where
+
+import Control.Applicative ( (<|>) )
+import Data.Attoparsec.Combinator ( lookAhead )
+import Data.Attoparsec.Text ( Parser
+ , anyChar
+ , char
+ , choice
+ , many'
+ , manyTill
+ , parse
+ , parseOnly
+ , sepBy
+ , skipMany
+ , skipSpace
+ , skipWhile
+ , space
+ , string
+ , takeTill
+ , takeWhile1
+ )
+import Data.Char ( isAlpha
+ , isAlphaNum
+ )
+import qualified Data.HashMap.Lazy as HM
+import Data.Maybe ( catMaybes )
+import qualified Data.Text as T
+import Data.Text ( Text )
+import GHC.Generics ( Generic )
+import Servall.Types
+
+parseWikiTemplates :: Text -> Either String [WikiTemplate]
+parseWikiTemplates = parseOnly wikiP
+
+wikiP :: Parser [WikiTemplate]
+wikiP = sepBy templateP (commentP <|> skipSpace)
+
+templateP :: Parser WikiTemplate
+templateP = do
+ string "{{"
+ name <- tempHeaderP
+ fields <- many' (choice [tempFieldP, commentP >> return Nothing])
+ string "}}"
+ return $ WikiTemplate name (HM.fromList (catMaybes fields))
+
+tempHeaderP :: Parser Text
+tempHeaderP = do
+ -- Not sure whether name can contain numbers
+ skipSpace
+ -- Does not consider multiple words like Short description
+ name <- takeWhile1 isAlpha
+ manyTill anyChar (lookAhead ((char '|' >> return "") <|> string "}}"))
+ return name
+
+tempFieldP :: Parser (Maybe (Text, Text))
+tempFieldP = do
+ skipSpace >> char '|' >> skipSpace
+ choice [namedField, tempFieldValueP >> return Nothing]
+ where
+ namedField = do
+ key <- takeWhile1 (\c -> isAlphaNum c || c == '_')
+ skipSpace
+ char '='
+ skipSpace
+ value <- tempFieldValueP
+ return $ if T.null value then Nothing else Just (key, value)
+
+tempFieldValueP :: Parser Text
+tempFieldValueP = do
+ skipSpace
+ T.concat <$> many'
+ (choice [templateP >> return "", commentP >> return "", wikilinkP, simpleP])
+ where
+ simpleP :: Parser Text
+ simpleP = do
+ t <- T.pack <$> manyTill
+ anyChar
+ (lookAhead
+ ( string "[["
+ <|> string "{{"
+ <|> string "<!--"
+ <|> (char '|' >> return "")
+ <|> string "}}"
+ )
+ )
+ if T.null t then fail "simpleP" else return $ T.unwords $ T.words t
+
+commentP :: Parser ()
+commentP = do
+ skipSpace >> string "<!--" >> untilCommentEnd ""
+ where
+ untilCommentEnd :: Text -> Parser ()
+ untilCommentEnd xs | T.isSuffixOf "--" xs = char '>' >> return ()
+ untilCommentEnd _ = do
+ xs <- takeWhile1 (/= '>')
+ untilCommentEnd xs
+
+wikilinkP :: Parser Text
+wikilinkP = do
+ beg <- string "[["
+ content <- T.pack <$> manyTill anyChar (string "]]")
+ return $ beg <> content <> "]]"