I'm learning Haskell at the moment, and have just written my first useful module - a parser fo INI files. I used Parsec. I'd like to know what can be improved here - or maybe I did some things completely wrong and there is a better way. Thanks.
module IniFile (iniFileToMap) where
import Text.ParserCombinators.Parsec
import qualified Data.Map as Map
import Char
parseIniFile :: Parser ([(String, [(String, String)])])
parseSection :: Parser (String, [(String, String)])
parseSectionHeader :: Parser String
parseNameValue :: Parser (String, String)
parseComment :: Parser ()
parseNormalValue :: Parser String
parseQuotedValue :: Parser String
parseValue :: Parser String
parseName :: Parser String
parseInsideQuotes :: Parser String
parseCmtOrSpace :: Parser ()
iniFileToMap :: FilePath -> IO (Map.Map String (Map.Map String String))
parseCmtOrSpace = do{
spaces;
skipMany parseComment;
}
parseInsideQuotes = many (noneOf "\"")
parseQuotedValue = between (char '"') (char '"') parseInsideQuotes
parseNormalValue = many1 (satisfy (\c -> isPrint c && not (isSpace c)))
parseValue = parseQuotedValue <|> parseNormalValue
parseName = many1 (satisfy (\c -> isAlpha c || isDigit c || c == '_' || c == '.'));
parseComment = do{
skipMany1 (char ';');
skipMany (noneOf "\n");
spaces;
}
parseNameValue = do{
name <- parseName;
between (skipMany (oneOf " \t")) (skipMany (oneOf " \t")) (char '=');
value <- parseValue;
return (name, value);
}
parseSectionHeader = do{
name <- between (char '[') (char ']') parseName;
return name;
}
parseSection = do{
name <- between parseCmtOrSpace parseCmtOrSpace parseSectionHeader;
values <- endBy1 (parseNameValue) (parseCmtOrSpace);
return (name, values);
}
parseIniFile = do{
result <- many1 (parseSection);
return result;
}
list2Map list = Map.fromList (map (\e -> (fst e, Map.fromList (snd e))) list)
iniFileToMap path = do{
result <- parseFromFile parseIniFile path;
case (result) of
Left err -> error (show err)
Right xs -> return (list2Map(xs));
}