0 | module Text.Regex.Interface
2 | import public Data.Alternative
4 | import public Data.List.Quantifiers
5 | import public Data.List1
6 | import public Data.Vect
11 | %language ElabReflection
18 | data EdgeSide = Start | End
21 | data LineMode = Line | Text
23 | export %hint ShowEdgeSide : Show EdgeSide;
ShowEdgeSide = %runElab derive
24 | export %hint ShowLineMode : Show LineMode;
ShowLineMode = %runElab derive
27 | interface Alternative rx => Regex rx where
29 | sym' : (Char -> Maybe a) -> rx a
31 | sym : (Char -> Bool) -> rx Char
32 | sym f = sym' $
\c => whenT (f c) c
34 | char : Char -> rx Char
38 | anyChar : LineMode -> rx Char
41 | edge : LineMode -> EdgeSide -> rx ()
47 | wordBoundary : (left : Bool) -> (right : Bool) -> rx ()
50 | string : String -> rx String
51 | string = map pack . sequence . map char . unpack
54 | withMatch : rx a -> rx (String, a)
56 | matchOf : rx a -> rx String
57 | matchOf = map fst . withMatch
60 | all : All rx tys -> rx $
HList tys
64 | exists : All rx tys -> rx $
Any Prelude.id tys
68 | opt : rx a -> rx $
Maybe a
71 | rep1 : rx a -> rx $
List1 a
72 | rep1 r = [| r ::: rep r |]
73 | rep : rx a -> rx $
List a
74 | rep r = toList <$> rep1 r <|> pure []
76 | repeatN : (n : Nat) -> rx a -> rx $
Vect n a
77 | repeatN n = sequence . replicate n
79 | repeatNOrMore : (n : Nat) -> rx a -> rx $
List a
80 | repeatNOrMore n r = [| map toList (repeatN n r) ++ rep r |]
82 | repeatNOrLess : (n : Nat) -> rx a -> rx $
List a
83 | repeatNOrLess Z _ = pure []
84 | repeatNOrLess (S n) r = [| r :: repeatNOrLess n r |] <|> pure []
86 | repeatNM : (n, m : Nat) -> (0 nm : n `LTE` m) => rx a -> rx $
List a
87 | repeatNM n m r = [| map toList (repeatN n r) ++ repeatNOrLess (m `minus` n) r |]
92 | public export %inline
93 | omega : Regex rx => rx ()
96 | export infixr 7 `thenGoes`
98 | public export %inline
99 | thenGoes : Regex rx => rx a -> rx b -> rx (a, b)
100 | thenGoes x y = [| (x, y) |]
104 | public export %inline
105 | anyOf : Regex rx => List Char -> rx Char
106 | anyOf cs = sym (`elem` cs)
108 | public export %inline
109 | noneOf : Regex rx => List Char -> rx Char
110 | noneOf cs = sym $
not . (`elem` cs)
112 | public export %inline
113 | between : Regex rx => Char -> Char -> rx Char
114 | between l r = sym $
\k => l <= k && k <= r
118 | genericNL : Regex rx => rx String
119 | genericNL = string "\x0d\x0a" <|> map singleton (anyOf ['\n', '\r', '\v'])
123 | = Alpha | Digit | XDigit | Alnum | Upper | Lower | Word
124 | | Cntrl | Space | Blank | Graph | Print | Ascii | Punct
126 | public export %tcinline
127 | charClass : CharClass -> Char -> Bool
128 | charClass Alpha = isAlpha
129 | charClass Digit = isDigit
130 | charClass XDigit = isHexDigit
131 | charClass Alnum = isAlphaNum
132 | charClass Upper = isUpper
133 | charClass Lower = isLower
134 | charClass Word = \c => isAlphaNum c || c == '_'
135 | charClass Cntrl = isControl
136 | charClass Space = isSpace
137 | charClass Blank = \c => c == ' ' || c == '\t'
138 | charClass Graph = \c => chr 0x21 <= c && c <= chr 0x7E
139 | charClass Print = \c => c == ' ' || charClass Graph c
140 | charClass Ascii = \c => chr 0x00 <= c && c <= chr 0x7F
141 | charClass Punct = \c => charClass Graph c && not (isSpace c) && not (isAlphaNum c)
146 | parseDigit : (base : Nat) -> (0 _ : So (2 <= base && base <= 36)) => Char -> Maybe $
Fin base
147 | parseDigit base@(S _) c = do
148 | let tofin = \n => fromMaybe FZ $
integerToFin (cast n) base
151 | let c = if isUpper c then chr (ord c - ord 'A' + ordA) else c
152 | let pred = if base <= 10
153 | then let upDig = chr $
ord0 + cast base in '0' <= c && c <= upDig
154 | else let upLet = chr $
ordA + cast (base `minus` 10) in '0' <= c && c <= '9' || 'a' <= c && c <= upLet
155 | whenT pred $
tofin $
if c <= '9' then ord c - ord0 else ord c - ordA + 10
159 | digit' : Regex rx => (base : Nat) -> (0 _ : So (2 <= base && base <= 36)) => rx $
Fin base
160 | digit' base = sym' $
parseDigit base
163 | public export %inline
164 | digit : Regex rx => rx $
Fin 10
169 | naturalNumber' : Regex rx => (base : Nat) -> (0 _ : So (2 <= base && base <= 36)) => rx Nat
170 | naturalNumber' base = rep1 (digit' base) <&> \(h:::tl) => go (cast h) tl where
171 | go : Nat -> List (Fin base) -> Nat
173 | go acc (x::xs) = go (acc * base + cast x) xs
175 | public export %inline
176 | naturalNumber : Regex rx => rx Nat
177 | naturalNumber = naturalNumber' 10