0 | module Text.Lex.Manual
2 | import Data.List.Quantifiers
3 | import public Text.Bounds
4 | import public Text.ParseError
5 | import public Data.List.Suffix
6 | import public Data.List.Suffix.Result
12 | 0 LexRes : (b : Bool) -> List Char -> (e,a : Type) -> Type
13 | LexRes b ts e a = Result b Char ts (InnerError e) a
21 | public export %inline
22 | move : Position -> Suffix b xs ys -> Position
23 | move p s = addCol (toNat s) p
25 | calcEnd : (line,col : Nat) -> (cs : List Char) -> Suffix b ys cs -> Position
26 | calcEnd l c ys Same = P l c
27 | calcEnd l c ('\n' :: t) (Uncons x) = calcEnd (S l) 0 t (unconsBoth x)
28 | calcEnd l c (_ :: t) (Uncons x) = calcEnd l (S c) t (unconsBoth x)
29 | calcEnd l c [] (Uncons x) = absurd x
42 | endPos pos = calcEnd pos.line pos.col cs
47 | -> {ts,errStart : List Char}
49 | -> (start : Suffix False errStart ts)
50 | -> (0 errEnd : List Char)
51 | -> {auto end : Suffix False errEnd errStart}
54 | boundedErr pos start errEnd err =
55 | let ps := endPos pos start
57 | in bounded err ps pe
66 | -> Lazy (Result b t ts r a)
67 | -> Result b t ts r a
68 | s@(Succ {}) <|> _ = s
76 | public export %inline
77 | isSpaceChar : Char -> Bool
78 | isSpaceChar ' ' = True
79 | isSpaceChar _ = False
82 | public export %inline
83 | isLineFeed : Char -> Bool
84 | isLineFeed '\n' = True
85 | isLineFeed _ = False
87 | public export %inline
88 | Cast (SnocList Char) String where
89 | cast = pack . (<>> [])
95 | octDigit : Char -> Nat
109 | digit : Char -> Nat
112 | digit c = octDigit c
118 | hexDigit : Char -> Nat
119 | hexDigit c = case toLower c of
130 | isBinDigit : Char -> Bool
131 | isBinDigit '0' = True
132 | isBinDigit '1' = True
133 | isBinDigit _ = False
139 | binDigit : Char -> Nat
150 | 0 Tok : (b : Bool) -> (e,a : Type) -> Type
151 | Tok b e a = (cs : List Char) -> LexRes b cs e a
157 | 0 AutoTok : (e,a : Type) -> Type
160 | -> (cs : List Char)
161 | -> {auto p : Suffix True cs orig}
162 | -> LexRes True orig e a
166 | 0 SafeTok : (a : Type) -> Type
169 | -> {orig : List Char}
170 | -> (cs : List Char)
171 | -> {auto p : Suffix True cs orig}
172 | -> LexRes True orig e a
177 | 0 StrictTok : (e,a : Type) -> Type
180 | -> (cs : List Char)
181 | -> {auto p : Suffix False cs orig}
182 | -> LexRes True orig e a
184 | public export %inline
185 | tok : StrictTok e a -> Tok True e a
188 | public export %inline
189 | autoTok : StrictTok e a -> AutoTok e a
190 | autoTok f ts @{p} = weakens $
f ts @{weaken p}
192 | public export %inline
193 | safeTok : SafeTok a -> AutoTok e a
194 | safeTok f ts = f ts
196 | public export %inline
199 | -> {orig : List Char}
200 | -> {errBegin : List Char}
201 | -> (err : InnerError e)
202 | -> (suffixCur : Suffix b errBegin orig)
203 | -> (0 errEnd : List Char)
204 | -> {auto sr : Suffix False errEnd errBegin}
205 | -> LexRes bres orig e a
206 | range err sc errEnd = Fail (weaken sc) errEnd err
208 | public export %inline
211 | -> {orig : List Char}
212 | -> {errBegin : List Char}
213 | -> (suffixCur : Suffix b errBegin orig)
214 | -> (0 errEnd : List Char)
215 | -> {auto sr : Suffix False errEnd errBegin}
216 | -> LexRes bres orig e a
217 | invalidEscape = range InvalidEscape
219 | public export %inline
222 | -> {orig : List Char}
223 | -> {errBegin : List Char}
224 | -> (suffixCur : Suffix b errBegin orig)
225 | -> (0 errEnd : List Char)
226 | -> {auto sr : Suffix False errEnd errBegin}
227 | -> LexRes bres orig e a
228 | unknownRange sc ee = range (Unknown $
packPrefix sr) sc ee
230 | public export %inline
234 | -> {orig,errEnd : List Char}
235 | -> (err : InnerError e)
236 | -> (suffixCur : Suffix b (c::errEnd) orig)
237 | -> LexRes bres orig e a
238 | single r p = range r p errEnd
240 | public export %inline
244 | -> {orig,errEnd : List Char}
245 | -> (suffixCur : Suffix b (c::errEnd) orig)
246 | -> LexRes bres orig e a
247 | unknown sc = unknownRange sc errEnd
249 | public export %inline
252 | -> {orig : List Char}
253 | -> (suffixCur : Suffix b [] orig)
254 | -> LexRes bres orig e a
255 | eoiAt sc = range EOI sc []
257 | public export %inline
261 | -> {orig,errEnd : List Char}
262 | -> (class : CharClass)
263 | -> (suffixCur : Suffix b (c::errEnd) orig)
264 | -> LexRes bres orig e a
265 | failCharClass cc = single (ExpectedChar cc)
267 | public export %inline
271 | -> {orig,errEnd : List Char}
272 | -> (tpe : DigitType)
273 | -> (suffixCur : Suffix b (c::errEnd) orig)
274 | -> LexRes bres orig e a
275 | failDigit = failCharClass . Digit
277 | public export %inline
280 | -> {errBegin : List Char}
281 | -> {orig : List Char}
282 | -> (suffixCur : Suffix b errBegin orig)
283 | -> LexRes bres orig e a
284 | fail {errBegin = x::xs} p = unknown p
285 | fail {errBegin = []} p = eoiAt p
293 | dec1 : (n : Nat) -> SafeTok Nat
294 | dec1 n (x::xs) = if isDigit x then dec1 (n*10 + digit x) xs else succ n p
295 | dec1 n [] = succ n p
300 | dec : StrictTok e Nat
301 | dec (x::xs) = if isDigit x then dec1 (digit x) xs else failDigit Dec p
307 | dec_1 : (n : Nat) -> AutoTok e Nat
308 | dec_1 n ('_'::x::xs) =
309 | if isDigit x then dec_1 (n*10 + digit x) xs else failDigit Dec (uncons p)
310 | dec_1 n (x::xs) = if isDigit x then dec_1 (n*10 + digit x) xs else succ n p
311 | dec_1 n [] = Succ n []
316 | decSep : StrictTok e Nat
317 | decSep (x::xs) = if isDigit x then dec_1 (digit x) xs else failDigit Dec p
318 | decSep [] = eoiAt p
322 | bin1 : (n : Nat) -> SafeTok Nat
323 | bin1 n (x :: xs) = if isBinDigit x then bin1 (n*2 + binDigit x) xs else succ n p
324 | bin1 n [] = succ n p
329 | bin : StrictTok e Nat
330 | bin (x::xs) = if isBinDigit x then bin1 (binDigit x) xs else failDigit Bin p
336 | bin_1 : (n : Nat) -> AutoTok e Nat
337 | bin_1 n ('_' :: x :: xs) =
338 | if isBinDigit x then bin_1 (n*2 + binDigit x) xs else failDigit Bin (uncons p)
339 | bin_1 n (x :: xs) =
340 | if isBinDigit x then bin_1 (n*2 + binDigit x) xs else succ n p
341 | bin_1 n [] = succ n p
347 | binSep : StrictTok e Nat
348 | binSep (x::xs) = if isBinDigit x then bin_1 (binDigit x) xs else failDigit Bin p
349 | binSep [] = eoiAt p
353 | oct1 : (n : Nat) -> SafeTok Nat
354 | oct1 n (x :: xs) = if isOctDigit x then oct1 (n*8 + octDigit x) xs else succ n p
355 | oct1 n [] = succ n p
360 | oct : StrictTok e Nat
361 | oct (x::xs) = if isOctDigit x then oct1 (octDigit x) xs else failDigit Oct p
367 | oct_1 : (n : Nat) -> AutoTok e Nat
368 | oct_1 n ('_' :: x :: xs) =
369 | if isOctDigit x then oct_1 (n*8 + octDigit x) xs else failDigit Oct (uncons p)
370 | oct_1 n (x :: xs) =
371 | if isOctDigit x then oct_1 (n*8 + octDigit x) xs else succ n p
372 | oct_1 n [] = succ n p
378 | octSep : StrictTok e Nat
379 | octSep (x::xs) = if isOctDigit x then oct_1 (octDigit x) xs else failDigit Oct p
380 | octSep [] = eoiAt p
384 | hex1 : (n : Nat) -> SafeTok Nat
385 | hex1 n (x :: xs) = if isHexDigit x then hex1 (n*16 + hexDigit x) xs else succ n p
386 | hex1 n [] = succ n p
391 | hex : StrictTok e Nat
392 | hex (x::xs) = if isHexDigit x then hex1 (hexDigit x) xs else failDigit Hex p
398 | hex_1 : (n : Nat) -> AutoTok e Nat
399 | hex_1 n ('_' :: x :: xs) =
400 | if isHexDigit x then hex_1 (n*16 + hexDigit x) xs else failDigit Hex (uncons p)
401 | hex_1 n (x :: xs) =
402 | if isHexDigit x then hex_1 (n*16 + hexDigit x) xs else succ n p
403 | hex_1 n [] = succ n p
409 | hexSep : StrictTok e Nat
410 | hexSep (x::xs) = if isHexDigit x then hex_1 (hexDigit x) xs else failDigit Hex p
411 | hexSep [] = eoiAt p
419 | int : StrictTok e Integer
420 | int ('-' :: xs) = negate . cast <$> dec xs
421 | int xs = cast <$> dec xs
425 | intPlus : StrictTok e Integer
426 | intPlus ('+'::xs) = cast <$> dec xs
427 | intPlus xs = int xs
434 | takeJustOnto : SnocList y -> (Char -> Maybe y) -> SafeTok (SnocList y)
435 | takeJustOnto sx f (x :: xs) = case f x of
436 | Just vb => takeJustOnto (sx :< vb) f xs
437 | Nothing => Succ sx (x::xs)
438 | takeJustOnto sx f [] = Succ sx []
442 | public export %inline
443 | takeJust : (Char -> Maybe y) -> SafeTok (SnocList y)
444 | takeJust f = takeJustOnto [<] f
448 | public export %inline
449 | takeJust1 : (Char -> Maybe y) -> StrictTok e (SnocList y)
450 | takeJust1 f (x::xs) = case f x of
451 | Just vb => takeJustOnto [<vb] f xs
452 | Nothing => unknown p
453 | takeJust1 _ [] = eoiAt p
471 | singleLineDropSpaces :
474 | -> Either (Bounded $
InnerError e) (List $
Bounded a)
475 | singleLineDropSpaces f s = go begin [<] (unpack s) suffixAcc
479 | -> SnocList (Bounded a)
480 | -> (ts : List Char)
481 | -> (0 acc : SuffixAcc ts)
482 | -> Either (Bounded $
InnerError e) (List $
Bounded a)
483 | go p1 sx [] _ = Right $
sx <>> []
484 | go p1 sx ('\n'::cs) (SA r) = go (incLine p1) sx cs r
485 | go p1 sx (c::cs) (SA r) =
486 | if isSpace c then go (incCol p1) sx cs r
487 | else case f (c::cs) of
489 | let p2 := move p1 p
490 | in go p2 (sx :< bounded v p1 p2) xs2 r
491 | Fail s e r => Left $
boundedErr p1 s e r
499 | multiLineDropSpaces :
502 | -> Either (Bounded $
InnerError e) (List $
Bounded a)
503 | multiLineDropSpaces f s = go begin [<] (unpack s) suffixAcc
507 | -> SnocList (Bounded a)
508 | -> (ts : List Char)
509 | -> (0 acc : SuffixAcc ts)
510 | -> Either (Bounded $
InnerError e) (List $
Bounded a)
511 | go p1 sx [] _ = Right $
sx <>> []
512 | go p1 sx ('\n'::cs) (SA r) = go (incLine p1) sx cs r
513 | go p1 sx (c::cs) (SA r) =
514 | if isSpace c then go (incCol p1) sx cs r
515 | else case f (c::cs) of
517 | let p2 := endPos p1 p
518 | in go p2 (sx :< bounded v p1 p2) xs2 r
519 | Fail s e r => Left $
boundedErr p1 s e r
531 | -> Either (Bounded $
InnerError e) (List $
Bounded a)
532 | lexManual f s = go begin [<] (unpack s) suffixAcc
536 | -> SnocList (Bounded a)
537 | -> (ts : List Char)
538 | -> (0 acc : SuffixAcc ts)
539 | -> Either (Bounded $
InnerError e) (List $
Bounded a)
540 | go p1 sx [] _ = Right $
sx <>> []
541 | go p1 sx cs (SA r) = case f cs of
543 | let p2 := endPos p1 p
544 | in go p2 (sx :< bounded v p1 p2) xs2 r
545 | Fail s e r => Left $
boundedErr p1 s e r