Scanner.hs 2.8 KB

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