This repository has been archived by the owner on Jul 8, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parse.hs
136 lines (116 loc) · 4.27 KB
/
Parse.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
{-
Parsing functions.
Copyright (C) 2005 Luis Francisco Araujo
-}
module Parse
where
import Text.ParserCombinators.Parsec (Parser, char, (<|>), many, parse, manyTill,
anyChar, noneOf, string)
import 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]
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.
quotes :: String -> [[String]]
quotes [] = []
quotes e
| null b && null q && null a = []
| otherwise = ((words b) : [q] : quotes a)
where
[b, q, a] = parseQuote e
quotes' :: String -> [[String]]
quotes' [] = []
quotes' e
| null b && null q && null a = []
| otherwise = ((words b) : [q] : quotes' a)
where
[b, q, a] = parseQuote' e
parseQuote, parseQuote' :: String -> Terna
parseQuote = gParser quote
parseQuote' = gParser quote'
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]
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]
escapeseq :: Parser String
escapeseq = (P.try $ string "''") <|>
(P.try $ string "\\'")