Scanner.hs 2.8 KB

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