aboutsummaryrefslogtreecommitdiff
path: root/ch08/8_c_1.hs
blob: ce80adea74c278cea03806089c061d331eb3a946 (plain)
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
-- Write a version of globToRegex that uses the type signature earlier.

{-- From examples/examples/ch08/GlobRegex.hs modified according to the assignment --}
import Text.Regex.Posix ((=~))

type GlobError = String

globToRegex :: String -> Either GlobError String

globToRegex cs = propagateError regex
  where regex = globToRegex' cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right ('^' : s ++ "$")

globToRegex' :: String -> Either GlobError String
globToRegex' "" = Right ""

globToRegex' ('*':cs) = propagateError regex
  where regex = globToRegex' cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right (".*" ++ s)

globToRegex' ('?':cs) = propagateError regex
  where regex = globToRegex' cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right ("." ++ s)

globToRegex' ('[':'!':c:cs) = propagateError charCls
  where charCls = charClass cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right ("[^" ++ c : s)

globToRegex' ('[':c:cs) = propagateError charCls
  where charCls = charClass cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right ('['  :  c : s)

globToRegex' ('[':_) = Left "unterminated character class"

globToRegex' (c:cs) = propagateError regex
  where regex = globToRegex' cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right ((escape c) ++ s)


escape :: Char -> String
escape c | c `elem` regexChars = '\\' : [c]
         | otherwise = [c]
    where regexChars = "\\+()^$.{}]|"


charClass :: String -> Either GlobError String

charClass (']':cs) = propagateError regex
  where regex = globToRegex' cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right (']' : s)

charClass (c:cs) = propagateError charCls
  where charCls = charClass cs
        propagateError (Left e) = Left e
        propagateError (Right s) = Right (c : s)

charClass [] = Left "unterminated character class"
{-- End of code from examples --}


-- ghci> :l 8_c_1.hs
-- [1 of 1] Compiling Main             ( 8_c_1.hs, interpreted )
-- Ok, one module loaded.

-- ghci> globToRegex "["
-- Left "unterminated character class"

-- ghci> globToRegex "[]"
-- Left "unterminated character class"

-- ghci> globToRegex "a?b*c[!DE][FG]+"
-- Right "^a.b.*c[^DE][FG]\\+$"