Skip to content

Instantly share code, notes, and snippets.

@rgrinberg
Created August 17, 2013 06:02
Show Gist options
  • Save rgrinberg/6255522 to your computer and use it in GitHub Desktop.
Save rgrinberg/6255522 to your computer and use it in GitHub Desktop.
simple ini parser using attoparsec
{-# LANGUAGE OverloadedStrings #-}
module Inisec where
import Prelude as P
import Data.Attoparsec.Text
import Data.Text.IO as T
import Data.Text
import Control.Applicative
data Section = Section
{ entries :: [(Text, Text)]
, name :: Maybe Text
} deriving (Show)
type IniFile = [Section]
comment :: Parser ()
comment = do
char ';'
skipWhile (/= '\n')
try $ char '\n'
return ()
sectionName :: Parser Text
sectionName = do
char '['
name <- takeTill (== ']')
char ']'
return name
entry :: Parser (Text, Text)
entry = do
key <- takeTill (== '=')
char '='
value <- manyTill anyChar (try endOfLine <|> try comment <|> try endOfInput)
return (strip key, strip . pack $ value)
-- | take a parser and wrap it around garbage stripping
wrapStrip :: Parser a -> Parser a
wrapStrip p = do
crap
x <- p
crap
return x
where crap = (try $ skipMany comment) <|> (try skipSpace)
section :: Parser Section
section = do
sectionName <- sectionName
sectionEntries <- many $ wrapStrip entry
return $ Section sectionEntries (Just sectionName)
anonSection :: Parser Section
anonSection = do
sectionEntries <- many $ wrapStrip entry
return $ Section sectionEntries Nothing
parseIni :: Parser IniFile
parseIni = many $ wrapStrip section
parseIniFile :: FilePath -> IO (Either String IniFile)
parseIniFile path = do
file <- T.readFile path
return $ parseOnly parseIni file
main :: IO ()
main = do
file <- T.readFile "sample.ini"
case parseOnly parseIni file of
Left error -> P.putStrLn $ "Error parsing: " ++ error
Right x -> P.putStrLn (show x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment