module Data.KeywordArgs.Parse (configParser) where
import Data.Maybe (catMaybes)
import Text.Parsec ((<|>), many, try, manyTill, char, anyChar, many1)
import Text.Parsec.String (Parser)
import Text.ParserCombinators.Parsec.Prim (GenParser)
import Text.ParserCombinators.Parsec.Char (space, newline, oneOf, noneOf)
import Control.Monad (liftM2)
import Text.Parsec.Combinator (eof)
import Control.Applicative ((<*), (*>), (<$>))
configParser :: Parser [(String, String)]
configParser = catMaybes <$> many line
line :: Parser (Maybe (String, String))
line = comment *> return Nothing <|> Just <$> configurationOption
configurationOption :: Parser (String, String)
configurationOption = do
_ <- many space
keyword <- manyTill1 anyChar keywordArgSeparator
val <- value
return (keyword, val)
value :: Parser String
value =
unquotedValue <|> quotedValue
where
endOfOption = endOfLineOrInput <|> comment
quotedValue = quote
*> manyTill1 argumentChar quote
<* endOfOption
unquotedValue = manyTill1 argumentChar endOfOption
comment :: Parser ()
comment =
try (many space *> char '#')
*> manyTill anyChar endOfLineOrInput
*> return ()
endOfLineOrInput :: Parser ()
endOfLineOrInput = newline *> return () <|> eof
manyTill1 :: GenParser tok st a -> GenParser tok st end -> GenParser tok st [a]
manyTill1 p end = liftM2 (:) p (manyTill p end)
argumentChar :: Parser Char
argumentChar = noneOf "#\""
keywordArgSeparator :: Parser ()
keywordArgSeparator = many1 (oneOf "\t ") *> return ()
quote :: Parser Char
quote = char '"'