hpython-0.2: src/Language/Python/Syntax/Ident.hs
{-# language DataKinds, KindSignatures #-}
{-# language DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveGeneric #-}
{-# language FlexibleInstances #-}
{-# language InstanceSigs, ScopedTypeVariables, TypeApplications #-}
{-|
Module : Language.Python.Syntax.Ident
Copyright : (C) CSIRO 2017-2019
License : BSD3
Maintainer : Isaac Elliott <isaace71295@gmail.com>
Stability : experimental
Portability : non-portable
-}
module Language.Python.Syntax.Ident
( Ident(..)
-- * Lenses
, identAnn
, identValue
, identWhitespace
-- * Extra functions
, isIdentifierStart
, isIdentifierChar
)
where
import Control.Lens.Lens (Lens, Lens', lens)
import Data.Char (isDigit, isLetter)
import Data.Generics.Product.Typed (typed)
import Data.String (IsString(..))
import GHC.Generics (Generic)
import Language.Python.Optics.Validated (Validated)
import Language.Python.Syntax.Ann
import Language.Python.Syntax.Raw
import Language.Python.Syntax.Whitespace
-- | An identifier. Like many types in hpython, it has an optional annotation
-- and tracks its trailing whitespace.
--
-- 'Raw' 'Ident's have an 'IsString' instance.
--
-- See <https://docs.python.org/3.5/reference/lexical_analysis.html#identifiers>
data Ident (v :: [*]) a
= MkIdent
{ _identAnn :: Ann a
, _identValue :: String
, _identWhitespace :: [Whitespace]
} deriving (Eq, Show, Functor, Foldable, Traversable, Generic)
instance HasAnn (Ident v) where
annot :: forall a. Lens' (Ident v a) (Ann a)
annot = typed @(Ann a)
-- | Determine whether this character could start a valid identifier
isIdentifierStart :: Char -> Bool
isIdentifierStart = do
a <- isLetter
b <- (=='_')
pure $ a || b
-- | Determine whether this character could be part of a valid identifier
isIdentifierChar :: Char -> Bool
isIdentifierChar = do
a <- isIdentifierStart
b <- isDigit
pure $ a || b
instance IsString (Raw Ident) where
fromString s = MkIdent (Ann ()) s []
identValue :: Lens (Ident v a) (Ident '[] a) String String
identValue = lens _identValue (\s a -> s { _identValue = a })
identAnn :: Lens (Ident v a) (Ident v a) a a
identAnn = annot_
identWhitespace :: Lens (Ident v a) (Ident v a) [Whitespace] [Whitespace]
identWhitespace = lens _identWhitespace (\s ws -> s { _identWhitespace = ws })
instance HasTrailingWhitespace (Ident v a) where
trailingWhitespace = identWhitespace
instance Validated Ident where