module Database.Schema.Migrations.Filesystem.Parse
( migrationParser
, parseDepsList
, FieldName
, Field
, FieldSet
)
where
import Data.Time.Clock ()
import Data.Maybe ( catMaybes )
import Text.ParserCombinators.Parsec
type FieldName = String
type Field = (FieldName, String)
type FieldSet = [Field]
migrationParser :: Parser [Field]
migrationParser = do
result <- many (parseField <|> parseComment <|> parseEmptyLine)
return $ catMaybes result
parseDepsList :: Parser [String]
parseDepsList =
depsList <|> (many whitespace >> eol >> return [])
where
parseMID = many1 (alphaNum <|> oneOf "-._")
separator = discard $ spaces >> many (newline >> spaces)
depsList = do
many whitespace
first <- parseMID
rest <- many $ try $ do
separator
parseMID
eol
return (first : rest)
discard :: Parser a -> Parser ()
discard = (>> return ())
eol :: Parser ()
eol = (discard newline) <|> (discard eof)
whitespace :: Parser Char
whitespace = oneOf " \t"
requiredWhitespace :: Parser String
requiredWhitespace = many1 whitespace
parseFieldName :: Parser FieldName
parseFieldName = many1 (alphaNum <|> char '-')
parseComment :: Parser (Maybe Field)
parseComment = do
discard $ do
many whitespace
char '#'
manyTill anyChar eol
return Nothing
parseEmptyLine :: Parser (Maybe Field)
parseEmptyLine = newline >> return Nothing
parseField :: Parser (Maybe Field)
parseField = do
name <- parseFieldName
char ':'
many whitespace
rest <- manyTill anyChar eol
otherLines <- otherContentLines
let value = rest ++ (concat otherLines)
return $ Just (name, value)
otherContentLines :: Parser [String]
otherContentLines =
many $ try $ (discard newline >> return "") <|> do
ws <- requiredWhitespace
rest <- manyTill anyChar eol
return $ ws ++ rest ++ "\n"