-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregexpparser.hs
76 lines (63 loc) · 1.6 KB
/
regexpparser.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
module RegExpParser
( RegExp(..)
, parseRegExp
) where
import Text.Parsec
data RegExp
= Normal Char
| Any
| ZeroOrMore RegExp
| Or RegExp RegExp
| Str [RegExp]
deriving (Show, Eq)
eitherToMaybe :: Either a b -> Maybe b
eitherToMaybe output = case output of
Left _ -> Nothing
Right x -> Just x
parens :: Parsec String () a -> Parsec String () a
parens = between (char '(') (char ')')
parseRegExp :: String -> Maybe RegExp
parseRegExp = eitherToMaybe . parse parseExp ""
parseExp :: Parsec String () RegExp
parseExp = do
expr <- try parseOr
<|> try parseStr
<|> parseUnit
_ <- eof
return expr
parseOr :: Parsec String () RegExp
parseOr = do
s1 <- try parseStr <|> parseUnit
_ <- char '|'
s2 <- try parseStr <|> parseUnit
return $ Or s1 s2
parseStr :: Parsec String () RegExp
parseStr = do
h <- parseUnit
t <- many1 parseUnit
return $ Str $ h : t
parseUnit :: Parsec String () RegExp
parseUnit =
try parseMany
<|> try (parens parseOr)
<|> try (parens parseStr)
<|> parseNormal
<|> parseAny
<|> parens parseUnit
parseMany :: Parsec String () RegExp
parseMany = do
expr <- parens ( try parseOr
<|> try parseStr
<|> try parseUnit)
<|> parseNormal
<|> parseAny
_ <- char '*'
return $ ZeroOrMore expr
parseNormal' :: Parsec String () Char
parseNormal' = try (parens parseNormal') <|> noneOf "()|*."
parseNormal :: Parsec String () RegExp
parseNormal = Normal <$> parseNormal'
parseAny :: Parsec String () RegExp
parseAny
= (char '.' >> return Any)
<|> parens parseAny