-- -- ConfigParser -- Copyright (C) 2014 Ivan Cukic -- -- Distributed under terms of the GPLv3 license. -- {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE LambdaCase #-} module StringListParser ( parseString , parseStrings , stripQuotes ) where import Data.Maybe import Data.List (intercalate) import qualified Text.ParserCombinators.Parsec as P import qualified Text.ParserCombinators.Parsec.Token as T import qualified Text.ParserCombinators.Parsec.Language as L import Text.Parsec ((<|>), ()) import Control.Monad (liftM) import Debug.Trace -- | Parses a string containing space-separated chunks into a list of strings -- | Escaping rules apply, including quotes and such parseString :: String -> [String] parseString input = do let result = P.parse parser "" input case result of Left e -> error $ show e Right r -> r -- | Parses the input kdesrc-formatted file parseStrings :: [String] -> [String] parseStrings input = parseString $ intercalate " " input -- | Removes the quotes from the start and end stripQuotes :: String -> String stripQuotes input = if (startsAndEnds '"' input) || (startsAndEnds '\'' input) then tail $ init input else input startsAndEnds :: Char -> String -> Bool startsAndEnds c cs = head cs == c && last cs == c parser :: P.Parser [String] parser = do P.many $ do P.spaces ( parseDQuotedItem <|> parseSQuotedItem <|> parseNormalItem ) parseNormalItem :: P.Parser String parseNormalItem = P.many1 (P.noneOf " \t") "Non-quoted string" parseDQuotedItem :: P.Parser String parseDQuotedItem = parseQuotedItem '"' parseSQuotedItem :: P.Parser String parseSQuotedItem = parseQuotedItem '\'' parseQuotedItem :: Char -> P.Parser String parseQuotedItem c = do _ <- P.char c content <- P.many1 (parseQuotedChar c) _ <- P.char c return $ [c] ++ content ++ [c] parseQuotedChar :: Char -> P.Parser Char parseQuotedChar c = P.try (P.char '\\' >> P.anyChar) <|> P.try (P.string [c, c] >> return c) <|> P.noneOf [c] "Character in " ++ [c] ++ "-quote string"