-
Notifications
You must be signed in to change notification settings - Fork 0
/
Regex.hs
47 lines (40 loc) · 1.48 KB
/
Regex.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
module Regex
( generateStrings,
parse,
)
where
import ListUtil
data Regex = Epsilon | Single Char | Seq Regex Regex | Or Regex Regex | Star Regex deriving (Show)
generateStrings :: Regex -> [String]
generateStrings Epsilon = [""]
generateStrings (Single x) = [[x]]
generateStrings (Or r1 r2) = ListUtil.interleave (generateStrings r1) (generateStrings r2)
generateStrings (Seq r1 r2) = [s1 ++ s2 | (s1, s2) <- ListUtil.cross (generateStrings r1) (generateStrings r2)]
generateStrings (Star r) = take 100 (generateStrings Epsilon ++ generateStrings (Seq r (Star r)))
parse :: String -> Regex
parse [] = Epsilon
parse ['.'] = Epsilon
parse [x] = Single x
parse x
| last x == '*' && l == length x = Star (parse (init x))
| head x == '(' && last x == ')' && l == length x = parse (tail (init x))
| head afterBracket == '+' = Or (parse insideBracket) (parse (tail afterBracket))
| otherwise = Seq (parse insideBracket) (parse afterBracket)
where
l = getBracketsLengthWithStar x
insideBracket = take l x
afterBracket = drop l x
getBracketsLengthWithStar :: String -> Int
getBracketsLengthWithStar x = l + length (takeWhile (== '*') (drop l x))
where
l = getBracketsLength x
getBracketsLength :: String -> Int
getBracketsLength x
| null x = 0
| head x /= '(' = 1
| otherwise = length (takeWhile (/= 0) (scanl countOpenBrackets 1 (tail x))) + 1
countOpenBrackets :: Int -> Char -> Int
countOpenBrackets acc x
| x == '(' = acc + 1
| x == ')' = acc - 1
| otherwise = acc