1 {-# OPTIONS_GHC -XNoImplicitPrelude #-}
2 -----------------------------------------------------------------------------
5 -- Copyright : (c) The University of Glasgow 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : libraries@haskell.org
10 -- Portability : portable
12 -- The Char type and associated operations.
14 -----------------------------------------------------------------------------
20 -- * Character classification
21 -- | Unicode characters are divided into letters, numbers, marks,
22 -- punctuation, symbols, separators (including spaces) and others
23 -- (including control characters).
25 , isLower, isUpper, isAlpha, isAlphaNum, isPrint
26 , isDigit, isOctDigit, isHexDigit
27 , isLetter, isMark, isNumber, isPunctuation, isSymbol, isSeparator
31 , isAsciiUpper, isAsciiLower
33 -- ** Unicode general categories
34 , GeneralCategory(..), generalCategory
37 , toUpper, toLower, toTitle -- :: Char -> Char
39 -- * Single digit characters
40 , digitToInt -- :: Char -> Int
41 , intToDigit -- :: Int -> Char
43 -- * Numeric representations
44 , ord -- :: Char -> Int
45 , chr -- :: Int -> Char
47 -- * String representations
48 , showLitChar -- :: Char -> ShowS
49 , lexLitChar -- :: ReadS String
50 , readLitChar -- :: ReadS Char
52 -- Implementation checked wrt. Haskell 98 lib report, 1/99.
55 #ifdef __GLASGOW_HASKELL__
58 import GHC.Real (fromIntegral)
60 import GHC.Read (Read, readLitChar, lexLitChar)
67 import Hugs.Prelude (Ix)
73 import Prelude(Char,String)
77 foreign import ccall unsafe "WCsubst.h u_gencat" wgencat :: CInt -> CInt
80 -- | Convert a single digit 'Char' to the corresponding 'Int'.
81 -- This function fails unless its argument satisfies 'isHexDigit',
82 -- but recognises both upper and lower-case hexadecimal digits
83 -- (i.e. @\'0\'@..@\'9\'@, @\'a\'@..@\'f\'@, @\'A\'@..@\'F\'@).
84 digitToInt :: Char -> Int
86 | isDigit c = ord c - ord '0'
87 | c >= 'a' && c <= 'f' = ord c - ord 'a' + 10
88 | c >= 'A' && c <= 'F' = ord c - ord 'A' + 10
89 | otherwise = error ("Char.digitToInt: not a digit " ++ show c) -- sigh
91 #ifndef __GLASGOW_HASKELL__
92 isAsciiUpper, isAsciiLower :: Char -> Bool
93 isAsciiLower c = c >= 'a' && c <= 'z'
94 isAsciiUpper c = c >= 'A' && c <= 'Z'
97 -- | Unicode General Categories (column 2 of the UnicodeData table)
98 -- in the order they are listed in the Unicode standard.
101 = UppercaseLetter -- ^ Lu: Letter, Uppercase
102 | LowercaseLetter -- ^ Ll: Letter, Lowercase
103 | TitlecaseLetter -- ^ Lt: Letter, Titlecase
104 | ModifierLetter -- ^ Lm: Letter, Modifier
105 | OtherLetter -- ^ Lo: Letter, Other
106 | NonSpacingMark -- ^ Mn: Mark, Non-Spacing
107 | SpacingCombiningMark -- ^ Mc: Mark, Spacing Combining
108 | EnclosingMark -- ^ Me: Mark, Enclosing
109 | DecimalNumber -- ^ Nd: Number, Decimal
110 | LetterNumber -- ^ Nl: Number, Letter
111 | OtherNumber -- ^ No: Number, Other
112 | ConnectorPunctuation -- ^ Pc: Punctuation, Connector
113 | DashPunctuation -- ^ Pd: Punctuation, Dash
114 | OpenPunctuation -- ^ Ps: Punctuation, Open
115 | ClosePunctuation -- ^ Pe: Punctuation, Close
116 | InitialQuote -- ^ Pi: Punctuation, Initial quote
117 | FinalQuote -- ^ Pf: Punctuation, Final quote
118 | OtherPunctuation -- ^ Po: Punctuation, Other
119 | MathSymbol -- ^ Sm: Symbol, Math
120 | CurrencySymbol -- ^ Sc: Symbol, Currency
121 | ModifierSymbol -- ^ Sk: Symbol, Modifier
122 | OtherSymbol -- ^ So: Symbol, Other
123 | Space -- ^ Zs: Separator, Space
124 | LineSeparator -- ^ Zl: Separator, Line
125 | ParagraphSeparator -- ^ Zp: Separator, Paragraph
126 | Control -- ^ Cc: Other, Control
127 | Format -- ^ Cf: Other, Format
128 | Surrogate -- ^ Cs: Other, Surrogate
129 | PrivateUse -- ^ Co: Other, Private Use
130 | NotAssigned -- ^ Cn: Other, Not Assigned
131 deriving (Eq, Ord, Enum, Read, Show, Bounded, Ix)
133 -- | The Unicode general category of the character.
134 generalCategory :: Char -> GeneralCategory
135 #if defined(__GLASGOW_HASKELL__) || defined(__NHC__)
136 generalCategory c = toEnum $ fromIntegral $ wgencat $ fromIntegral $ ord c
139 generalCategory c = toEnum (primUniGenCat c)
142 -- derived character classifiers
144 -- | Selects alphabetic Unicode characters (lower-case, upper-case and
145 -- title-case letters, plus letters of caseless scripts and modifiers letters).
146 -- This function is equivalent to 'Data.Char.isAlpha'.
147 isLetter :: Char -> Bool
148 isLetter c = case generalCategory c of
149 UppercaseLetter -> True
150 LowercaseLetter -> True
151 TitlecaseLetter -> True
152 ModifierLetter -> True
156 -- | Selects Unicode mark characters, e.g. accents and the like, which
157 -- combine with preceding letters.
158 isMark :: Char -> Bool
159 isMark c = case generalCategory c of
160 NonSpacingMark -> True
161 SpacingCombiningMark -> True
162 EnclosingMark -> True
165 -- | Selects Unicode numeric characters, including digits from various
166 -- scripts, Roman numerals, etc.
167 isNumber :: Char -> Bool
168 isNumber c = case generalCategory c of
169 DecimalNumber -> True
174 -- | Selects Unicode punctuation characters, including various kinds
175 -- of connectors, brackets and quotes.
176 isPunctuation :: Char -> Bool
177 isPunctuation c = case generalCategory c of
178 ConnectorPunctuation -> True
179 DashPunctuation -> True
180 OpenPunctuation -> True
181 ClosePunctuation -> True
184 OtherPunctuation -> True
187 -- | Selects Unicode symbol characters, including mathematical and
189 isSymbol :: Char -> Bool
190 isSymbol c = case generalCategory c of
192 CurrencySymbol -> True
193 ModifierSymbol -> True
197 -- | Selects Unicode space and separator characters.
198 isSeparator :: Char -> Bool
199 isSeparator c = case generalCategory c of
201 LineSeparator -> True
202 ParagraphSeparator -> True
206 -- dummy implementation
207 toTitle :: Char -> Char