    {-# LANGUAGE CPP #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Internal.Lexeme
    -- Copyright   :  (c) The GHC Team
    --
    -- Maintainer  :  ghc-devs@haskell.org
    -- Portability :  portable
    --
    -- Functions to evaluate whether or not a string is a valid identifier.
    --
    module GHC.Internal.Lexeme (
              -- * Lexical characteristics of Haskell names
            startsVarSym, startsVarId, startsConSym, startsConId,
            startsVarSymASCII, isVarSymChar, okSymChar
      ) where

    #ifdef BOOTSTRAP_TH
    import Prelude -- See note [Why do we import Prelude here?]
    import Data.Char
    #else
    import GHC.Internal.Base
    import GHC.Internal.Unicode
    import GHC.Internal.List (elem)
    #endif

    -- | Is this character acceptable in a symbol (after the first char)?
    -- See alexGetByte in GHC.Parser.Lexer
    okSymChar :: Char -> Bool
    okSymChar :: Char -> Bool
    okSymChar Char
    c
      | Char
    c Char -> [Char] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Char]
    "(),;[]`{}_\"'"
      = Bool
    False
      | Bool
    otherwise
      = case Char -> GeneralCategory
    generalCategory Char
    c of
          GeneralCategory
    ConnectorPunctuation -> Bool
    True
          GeneralCategory
    DashPunctuation      -> Bool
    True
          GeneralCategory
    OtherPunctuation     -> Bool
    True
          GeneralCategory
    MathSymbol           -> Bool
    True
          GeneralCategory
    CurrencySymbol       -> Bool
    True
          GeneralCategory
    ModifierSymbol       -> Bool
    True
          GeneralCategory
    OtherSymbol          -> Bool
    True
          GeneralCategory
    _                    -> Bool
    False

    startsVarSym, startsVarId, startsConSym, startsConId :: Char -> Bool
    startsVarSym :: Char -> Bool
    startsVarSym Char
    c = Char -> Bool
    okSymChar Char
    c Bool -> Bool -> Bool
    && Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Char
    ':' -- Infix Ids
    startsConSym :: Char -> Bool
    startsConSym Char
    c = Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ':'                -- Infix data constructors
    startsVarId :: Char -> Bool
    startsVarId Char
    c  = Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '_' Bool -> Bool -> Bool
    || case Char -> GeneralCategory
    generalCategory Char
    c of  -- Ordinary Ids
      GeneralCategory
    LowercaseLetter -> Bool
    True
      GeneralCategory
    OtherLetter     -> Bool
    True   -- See #1103
      GeneralCategory
    _               -> Bool
    False
    startsConId :: Char -> Bool
    startsConId Char
    c  = Char -> Bool
    isUpper Char
    c Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '('  -- Ordinary type constructors and data constructors

    startsVarSymASCII :: Char -> Bool
    startsVarSymASCII :: Char -> Bool
    startsVarSymASCII Char
    c = Char
    c Char -> [Char] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Char]
    "!#$%&*+./<=>?@\\^|~-"

    isVarSymChar :: Char -> Bool
    isVarSymChar :: Char -> Bool
    isVarSymChar Char
    c = Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ':' Bool -> Bool -> Bool
    || Char -> Bool
    startsVarSym Char
    c