Hashell-0.15: Hashell/Parse.hs
{-
Parsing functions.
Copyright (C) 2005, 2008 Luis Francisco Araujo
-}
module Parse
where
import Text.ParserCombinators.Parsec
import qualified Text.ParserCombinators.Parsec.Prim as P (try)
----------------------------------------------------------------------------------
-- | Get command name.
getCmd :: String -> String
getCmd = concat . take 1 . words
-- | Get command line arguments.
getArg :: String -> [String]
getArg s = if all (== ' ') s then [] else tail $ hParse s
----------------------------------------------------------------------------------
-- | Main entry for parsing expressions (quote , special characters etc).
-- It takes the expression and returns it tokenized.
hParse :: String -> [String]
hParse = map (`esc` '\\')
. filter (not . null)
. concat
. quotes
----------------------------------------------------------------------------------
-- | Use this function to restore a whitespace
-- in some expressions needed. (Those parsed with
-- splitRegex mainly).
restoreWhiteSpace :: (String -> String)
restoreWhiteSpace = (++ " ")
----------------------------------------------------------------------------------
-- | Split into a specific element.
splitInto :: (Ord a) => a -> [a] -> [[a]]
splitInto _ [] = []
splitInto c e = let (l , e') = break (== c) e
in
l : case e' of
[] -> []
(_:e'') -> splitInto c e''
----------------------------------------------------------------------------------
-- | Returns a boolean value if it finds
-- all the elements of a list.
findSubStr :: (Eq a) => [a] -> [a] -> Bool
findSubStr [] [] = False
findSubStr as bs = let f [] _ = True
f _ [] = False
f (a:as') (b:bs')
| a == b = f as' bs'
| a /= b = f as bs'
f _ _ = False
in
f as bs
----------------------------------------------------------------------------------
-- | Concatenate a list with a specifc delimiter.
joinWith :: [String] -> String -> String
joinWith xs y = foldr (\ a b -> a ++ (if null b then [] else y ++ b)) [] xs
----------------------------------------------------------------------------------
-- | Escape the special character 'c' in the expression.
esc :: String -> Char -> String
esc [] _ = []
esc (x:y:xs) c
| c == x = y : esc xs c
esc (x:xs) c = if x == c then [] else x : esc xs c
-- | Parse command haskell expressions.
type Terna = (String, String, String)
gParser :: Parser Terna -> String -> Terna
gParser p = f
where
f e = case (parse p "" e) of
Left _ -> ("", "", (show e))
Right t -> t
parseCH :: String -> Terna
parseCH = gParser comHaskell
comHaskell :: Parser Terna
comHaskell = do{ b <- manyTill anyChar (P.try (string "(-"))
; p <- manyTill anyChar (P.try (string "-)"))
; a <- many anyChar
; return (b, p, a)
}
-- | Parse quotes.
parseQuote :: String -> Terna
parseQuote = gParser quote
quotes :: String -> [[String]]
quotes [] = []
quotes e | null b && null q && null a = []
| otherwise = ((words b) : [q] : quotes a)
where
(b, q, a) = parseQuote e
escapeseq :: Parser String
escapeseq = (P.try $ string "''") <|>
(P.try $ string "\\'")
quote :: Parser Terna
quote = do{ b <- many (noneOf ['\''])
; many (char '\'')
; s <- many $ (escapeseq <|> (noneOf "'"
>>= (\x -> return [x])))
; many (char '\'')
; a <- many anyChar
; return (b, (concat s), a)
}