{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE OverloadedStrings #-} module HNormalise.Common.Parser where -------------------------------------------------------------------------------- import Control.Applicative ((<|>)) import Data.Attoparsec.Text import Data.Char (isSpace) import Data.Text (Text) import qualified Data.Text as T import qualified Net.IPv4.Text as IPv4 import qualified Net.IPv6.Text as IPv6 -------------------------------------------------------------------------------- import HNormalise.Common.Internal -------------------------------------------------------------------------------- hostnameParser :: Parser Text hostnameParser = sepBy' (takeWhile1 (inClass "a-z0-9-")) (char '.') >>= \hns -> return $ T.intercalate "." hns {-# INLINE hostnameParser #-} -------------------------------------------------------------------------------- hostnameOrIPParser :: Parser Host hostnameOrIPParser = choice [ IPv4.parser >>= \ip -> return $ IPv4 ip , IPv6.parser >>= \ip -> return $ IPv6 ip , hostnameParser >>= \h -> return $ Hostname h ] {-# INLINE hostnameOrIPParser #-} -------------------------------------------------------------------------------- keyParser k = string k *> char '=' {-# INLINE keyParser #-} -------------------------------------------------------------------------------- kvParser :: Parser (Text, Text) kvParser = do key <- takeTill (== '=') value <- char '=' *> takeTill isSpace return (key, value) {-# INLINE kvParser #-} -------------------------------------------------------------------------------- kvTextParser :: Text -> Parser Text kvTextParser key = kvTextDelimParser key " \n\t" {-# INLINE kvTextParser #-} -------------------------------------------------------------------------------- kvTextDelimParser :: Text -> String -> Parser Text kvTextDelimParser key ds = keyParser key *> takeTill (`elem` ds) {-# INLINE kvTextDelimParser #-} -------------------------------------------------------------------------------- kvNumParser :: Integral a => Text -> Parser a kvNumParser key = keyParser key *> decimal {-# INLINE kvNumParser #-} -------------------------------------------------------------------------------- kvYesNoParser :: Text -> Parser Bool kvYesNoParser key = do keyParser key yn <- asciiCI "yes" <|> asciiCI "no" return $ case T.toLower yn of "yes" -> True "no" -> False {-# INLINE kvYesNoParser #-} -------------------------------------------------------------------------------- kvHostOrIPParser :: Text -> Parser Host kvHostOrIPParser key = keyParser key *> hostnameOrIPParser {-# INLINE kvHostOrIPParser #-} -------------------------------------------------------------------------------- maybeOption :: Parser a -> Parser (Maybe a) maybeOption p = option Nothing (Just <$> p) {-# INLINE maybeOption #-}