Scanner.hs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. module System.IO.Uniform.Streamline.Scanner (
  2. IOScanner,
  3. IOScannerState(..),
  4. textScanner,
  5. anyScanner
  6. )where
  7. import Data.Default.Class
  8. import Data.Word8 (Word8)
  9. -- | State of an IO scanner.
  10. -- Differently from a parser scanner, an IO scanner
  11. -- must deal with blocking behavior.
  12. data IOScannerState a =
  13. -- | A scanner returns Finished when the current input is not
  14. -- part of the result, and the scanning must stop before this
  15. -- input.
  16. Finished |
  17. -- | A scanner returns LastPass when the current input is the
  18. -- last one of the result, and the scanning must stop before
  19. -- after this input, without consuming more data.
  20. LastPass a |
  21. -- | A scanner returns Running when the current input is part
  22. -- of the result, and the scanning must continue.
  23. Running a
  24. instance Functor IOScannerState where
  25. fmap _ Finished = Finished
  26. fmap f (LastPass x) = LastPass $ f x
  27. fmap f (Running x) = Running $ f x
  28. instance Applicative IOScannerState where
  29. pure = Running
  30. Finished <*> _ = Finished
  31. _ <*> Finished = Finished
  32. (LastPass f) <*> (LastPass x) = LastPass $ f x
  33. (LastPass f) <*> (Running x) = LastPass $ f x
  34. (Running f) <*> (LastPass x) = LastPass $ f x
  35. (Running f) <*> (Running x) = Running $ f x
  36. instance Monad IOScannerState where
  37. return = pure
  38. Finished >>= _ = Finished
  39. (LastPass x) >>= f = case f x of
  40. Finished -> Finished
  41. LastPass y -> LastPass y
  42. Running y -> LastPass y
  43. (Running x) >>= f = f x
  44. type IOScanner a = a -> Word8 -> IOScannerState a
  45. -- | Creates a scanner that'll finish when any of the given scanners finish.
  46. anyScanner :: Default a => [IOScanner a] -> IOScanner [a]
  47. anyScanner scanners = scan
  48. where
  49. --scan :: IOScanner [a]
  50. scan st c = sequence $ apScanner scanners st c
  51. --apScanner :: [IOScanner a] -> [a] -> Word8 -> [IOScannerState a]
  52. apScanner [] _ _ = []
  53. apScanner (s:ss) [] h = s def h : apScanner ss [] h
  54. apScanner (s:ss) (t:tt) h = s t h : apScanner ss tt h
  55. {- |
  56. Given a sequence of bytes, creates a scanner that will scan
  57. its input untill that sequence is found.
  58. -}
  59. textScanner :: [Word8] -> IOScanner [[Word8]]
  60. textScanner [] = \_ _ -> Finished
  61. textScanner t@(c:_) = scanner
  62. where
  63. scanner st c'
  64. | c == c' = popStacks (t:st) c'
  65. | otherwise = popStacks st c'
  66. popStacks :: IOScanner [[Word8]]
  67. popStacks [] _ = Running []
  68. popStacks ([]:_) _ = Finished
  69. popStacks ((h':hh):ss) h
  70. | h == h' && null hh = case popStacks ss h of
  71. Finished -> Finished
  72. LastPass ss' -> LastPass ss'
  73. Running ss' -> LastPass ss'
  74. | h == h' = case popStacks ss h of
  75. Finished -> Finished
  76. LastPass ss' -> LastPass $ hh:ss'
  77. Running ss' -> Running $ hh:ss'
  78. | otherwise = popStacks ss h