@@ -1,14 +1,16 @@
1−{-# LANGUAGE CPP #-}
2−
31-- |
42-- Module : Streamly.Internal.Unicode.Char.Parser
53-- Copyright : (c) 2021 Composewell Technologies
6−--
74-- License : BSD-3-Clause
85-- Maintainer : streamly@composewell.com
96-- Stability : experimental
107-- Portability : GHC
118--
9+-- To parse a text input, use the decode routines from
10+-- "Streamly.Unicode.Stream" module to convert an input byte stream to a
11+-- Unicode Char stream and then use these parsers on the Char stream.
12+
13+-- XXX Add explicit export list.
1214module Streamly.Internal.Unicode.Char.Parser where
1315
1416import Control.Applicative (Alternative(..))
@@ -25,9 +27,17 @@ import qualified Streamly.Internal.Data.Fold as Fold
2527-- Character classification
2628--------------------------------------------------------------------------------
2729
30+-- XXX It may be possible to implement faster predicates for ASCII byte stream.
31+-- We can measure if there is a signficant difference and if so we can add such
32+-- predicates to Streamly.Unicode.Char.Parser.Latin1.
33+--
2834#define CHAR_PARSER_SIG(NAME) NAME :: MonadCatch m => Parser m Char Char
35+-- XXX Need to use the predicates from Unicode.Char module/unicode-data package
2936#define CHAR_PARSER(NAME, PREDICATE) NAME = Parser.satisfy Char.PREDICATE
3037
38+-- XXX Add haddock documentation
39+-- XXX Add INLINE pragmas
40+
3141CHAR_PARSER_SIG(space)
3242CHAR_PARSER(space,isSpace)
3343
@@ -90,6 +100,7 @@ CHAR_PARSER(asciiLower,isAsciiLower)
90100--------------------------------------------------------------------------------
91101
92102-- | Match a specific character.
103+{-# INLINE char #-}
93104char :: MonadCatch m => Char -> Parser m Char Char
94105char c = Parser.satisfy (== c)
95106
@@ -97,7 +108,9 @@ char c = Parser.satisfy (== c)
97108-- Numeric parsers
98109--------------------------------------------------------------------------------
99110
100−-- | Parse and decode an unsigned decimal number.
111+-- XXX It should fail if the number is larger than the size of the type.
112+--
113+-- | Parse and decode an unsigned integral decimal number.
101114{-# INLINE decimal #-}
102115decimal :: (MonadCatch m, Integral a) => Parser m Char a
103116decimal = Parser.takeWhile1 Char.isDigit (Fold.foldl' step 0)
@@ -106,11 +119,10 @@ decimal = Parser.takeWhile1 Char.isDigit (Fold.foldl' step 0)
106119
107120 step a c = a * 10 + fromIntegral (ord c - 48)
108121
109−
110−-- | Parse and decode an unsigned hexadecimal number. The hex digits
122+-- | Parse and decode an unsigned integral hexadecimal number. The hex digits
111123-- @\'a\'@ through @\'f\'@ may be upper or lower case.
112124--
113−-- This parser does not accept a leading @\"0x\"@ string.
125+-- Note: This parser does not accept a leading @\"0x\"@ string.
114126{-# INLINE hexadecimal #-}
115127hexadecimal :: (MonadCatch m, Integral a, Bits a) => Parser m Char a
116128hexadecimal = Parser.takeWhile1 isHexDigit (Fold.foldl' step 0)
@@ -118,20 +130,24 @@ hexadecimal = Parser.takeWhile1 isHexDigit (Fold.foldl' step 0)
118130 where
119131
120132 isHexDigit c =
121− (c >= '0' && c <= '9')
122− || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
133+ (c >= '0' && c <= '9')
134+ || (c >= 'a' && c <= 'f')
135+ || (c >= 'A' && c <= 'F')
123136
124137 step a c
125− | w >= 48 && w <= 57 = (a `shiftL` 4) .|. fromIntegral (w - 48)
126− | w >= 97 = (a `shiftL` 4) .|. fromIntegral (w - 87)
127− | otherwise = (a `shiftL` 4) .|. fromIntegral (w - 55)
138+ | w >= 48 && w <= 57 =
139+ (a `shiftL` 4) .|. fromIntegral (w - 48)
140+ | w >= 97 =
141+ (a `shiftL` 4) .|. fromIntegral (w - 87)
142+ | otherwise =
143+ (a `shiftL` 4) .|. fromIntegral (w - 55)
128144
129145 where
130146
131147 w = ord c
132148
133−-- | Parse a number with an optional leading @\'+\'@ or @\'-\'@ sign
134−-- character.
149+-- | Allow an optional leading @\'+\'@ or @\'-\'@ sign character before any
150+-- parser.
135151{-# INLINE signed #-}
136152signed :: (Num a, MonadCatch m) => Parser m Char a -> Parser m Char a
137153signed p = (negate <$> (char '-' *> p)) <|> (char '+' *> p) <|> p
@@ -145,8 +161,6 @@ signed p = (negate <$> (char '-' *> p)) <|> (char '+' *> p) <|> p
145161--
146162-- === Examples
147163--
148−-- These examples use this helper:
149−--
150164-- Examples with behaviour identical to 'read', if you feed an empty
151165-- continuation to the first result:
152166--
@@ -167,5 +181,7 @@ signed p = (negate <$> (char '-' *> p)) <|> (char '+' *> p) <|> p
167181--
168182-- This function does not accept string representations of \"NaN\" or
169183-- \"Infinity\".
184+--
185+-- /Unimplemented/
170186double :: Parser m Char Double
171187double = undefined