module Data.KeywordArgs.Parse (configParser) where
import Data.Maybe (catMaybes)
import Data.Char (isSpace)
import Text.Parsec ((<|>), many, try, manyTill, char, anyChar, many1, satisfy)
import Text.Parsec.String (Parser)
import Text.ParserCombinators.Parsec.Prim hiding (try)
import Text.ParserCombinators.Parsec.Char (string, space, tab, newline,
alphaNum)
import Control.Monad (liftM2)
import Text.Parsec.Combinator (eof)
import Control.Applicative ((<*), (*>), (<$>))
configParser :: Parser [(String, String)]
configParser = catMaybes <$> many line
manyTill1 :: GenParser tok st a -> GenParser tok st end -> GenParser tok st [a]
manyTill1 p end = liftM2 (:) p (manyTill p end)
isValidKeyChar :: Char -> Bool
isValidKeyChar c = c /= '#' && (not . isSpace) c
isValidValueChar :: Char -> Bool
isValidValueChar c = c /= '#'
configurationOption :: Parser (String, String)
configurationOption = do
many space
keyword <- manyTill1 (satisfy isValidKeyChar) (many1 (char ' '))
let
endOfOption = endOfLineOrInput <|> comment
quotedValue = char '"' *>
manyTill1 (satisfy isValidValueChar) (try (char '"')) <*
endOfOption
unquotedValue = manyTill1 (satisfy isValidValueChar) endOfOption
value <- quotedValue <|> unquotedValue
return (keyword, value)
comment :: Parser ()
comment =
try (many space *> char '#')
*> manyTill anyChar endOfLineOrInput
*> return ()
endOfLineOrInput :: Parser ()
endOfLineOrInput = newline *> return () <|> eof
line :: Parser (Maybe (String, String))
line = comment *> return Nothing <|> Just <$> configurationOption