git.iko.soy/typeable/attoparsec
on master help sign in
Add asciiCI, as suggested in #9
commit59dd31b31fd2f9de9c065344e57a9aa4e6f82541 authorSimon Hengel <sol@typeful.net> dateSun 17 Jun 2012, 12:19 (14 years ago) parent64a5602
3 files changed+34
Data/Attoparsec/Text.hs+1 Data/Attoparsec/Text/Internal.hs+22 tests/QC/Text.hs+11
Data/Attoparsec/Text.hs+1
@@ -66,6 +66,7 @@ module Data.Attoparsec.Text
6666 -- * Efficient string handling
6767 , I.string
6868 , I.stringCI
69+ , I.asciiCI
6970 , skipSpace
7071 , I.skipWhile
7172 , I.scan
Data/Attoparsec/Text/Internal.hs+22
@@ -45,6 +45,7 @@ module Data.Attoparsec.Text.Internal
4545 , skipWhile
4646 , string
4747 , stringCI
48+ , asciiCI
4849 , take
4950 , scan
5051 , takeWhile
@@ -70,6 +71,7 @@ import Data.Attoparsec.Internal.Types hiding (Parser, Input, Added, Failure, Suc
7071import Data.String (IsString(..))
7172import Data.Text (Text)
7273import Prelude hiding (getChar, take, takeWhile)
74+import Data.Char (chr, ord)
7375import qualified Data.Attoparsec.Internal.Types as T
7476import qualified Data.Attoparsec.Text.FastSet as Set
7577import qualified Data.Text as T
@@ -245,6 +247,26 @@ stringCI s = go 0
245247 fs = T.toCaseFold s
246248{-# INLINE stringCI #-}
247249
250+-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
251+asciiCI :: Text -> Parser Text
252+asciiCI input = do
253+ t <- ensure n
254+ let h = unsafeTake n t
255+ if asciiToLower h == s
256+ then put (unsafeDrop n t) >> return h
257+ else fail "asciiCI"
258+ where
259+ n = T.length input
260+ s = asciiToLower input
261+
262+ -- convert letters in the ASCII range to lower-case
263+ asciiToLower = T.map f
264+ where
265+ offset = ord 'a' - ord 'A'
266+ f c | 'A' <= c && c <= 'Z' = chr (ord c + offset)
267+ | otherwise = c
268+{-# INLINE asciiCI #-}
269+
248270-- | Skip past input for as long as the predicate returns 'True'.
249271skipWhile :: (Char -> Bool) -> Parser ()
250272skipWhile p = go
tests/QC/Text.hs+11
@@ -6,6 +6,7 @@ import Control.Applicative ((<$>), (<*>))
66import Prelude hiding (takeWhile)
77import Test.Framework.Providers.QuickCheck2 (testProperty)
88import Test.QuickCheck
9+import qualified Data.Char as Char
910import qualified Data.Attoparsec.Text as P
1011import qualified Data.Attoparsec.Text.Lazy as PL
1112import qualified Data.Text as T
@@ -59,6 +60,15 @@ string s t = maybeP (P.string s') (s `L.append` t) == Just s'
5960stringCI s = P.parseOnly (P.stringCI fs) s == Right s
6061 where fs = T.toCaseFold s
6162
63+asciiCI x =
64+ (\s i -> P.parseOnly (P.asciiCI s) i == Right i)
65+ <$> maybeModifyCase x
66+ <*> maybeModifyCase x
67+ where
68+ maybeModifyCase s = elements [s, toLower s, toUpper s]
69+ toLower = T.map (\c -> if c < Char.chr 127 then Char.toLower c else c)
70+ toUpper = T.map (\c -> if c < Char.chr 127 then Char.toUpper c else c)
71+
6272toStrict = T.concat . L.toChunks
6373
6474skipWhile w s =
@@ -105,6 +115,7 @@ tests = [
105115 testProperty "peekChar" peekChar,
106116 testProperty "string" string,
107117 testProperty "stringCI" stringCI,
118+ testProperty "asciiCI" asciiCI,
108119 testProperty "skipWhile" skipWhile,
109120 testProperty "takeCount" takeCount,
110121 testProperty "takeWhile" takeWhile,