diff options
| author | Yuchen Pei <hi@ypei.me> | 2022-09-12 16:08:18 +1000 | 
|---|---|---|
| committer | Yuchen Pei <hi@ypei.me> | 2022-09-12 16:08:18 +1000 | 
| commit | 3afa538c7af2d2e092b482a67a25e8547d386820 (patch) | |
| tree | f73f8f15ded66eafc551109979c852eebf562089 /src/Servall | |
| parent | 0566547e07065581e2f45288eed63e4fb5874cf4 (diff) | |
separating out wikiparser and types and added config
Diffstat (limited to 'src/Servall')
| -rw-r--r-- | src/Servall/Types.hs | 13 | ||||
| -rw-r--r-- | src/Servall/WikiParser.hs | 105 | 
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 <> "]]"  | 
