ddc-core-0.4.3.1: DDC/Core/Lexer/Token/Names.hs
module DDC.Core.Lexer.Token.Names
( -- * Variable names
scanVarName
, matchVarName
, acceptVarName
, isVarName
, isVarStart
, isVarBody
-- * Constructor names
, scanConName
, matchConName
, acceptConName
, isConName
, isConStart
, isConBody)
where
import Text.Lexer.Inchworm.Char
import DDC.Data.ListUtils
import qualified Data.Char as Char
-- Variable names ---------------------------------------------------------------------------------
-- | Scanner for variable anmes.
scanVarName :: Scanner IO Location [Char] (Location, String)
scanVarName
= munchPred Nothing matchVarName acceptVarName
-- | Match a variable name.
matchVarName :: Int -> Char -> Bool
matchVarName 0 c = isVarStart c
matchVarName _ c = isVarBody c
-- | Accept a variable name.
acceptVarName :: String -> Maybe String
acceptVarName ss
| isVarName ss = Just ss
| otherwise = Nothing
-- | Check if this string is a variable name.
isVarName :: String -> Bool
isVarName str
= case str of
[] -> False
c : cs
| isVarStart c
, and (map isVarBody cs)
-> True
| _ : _ <- cs
, Just initCs <- takeInit cs
, isVarStart c
, and (map isVarBody initCs)
, last cs == '#'
-> True
| otherwise
-> False
-- | Charater can start a variable name.
isVarStart :: Char -> Bool
isVarStart c
= Char.isLower c
|| c == '?'
|| c == '_'
-- | Character can be part of a variable body.
isVarBody :: Char -> Bool
isVarBody c
= Char.isUpper c
|| Char.isLower c
|| Char.isDigit c
|| c == '_'
|| c == '\''
|| c == '$'
|| c == '#'
-- Constructor names ------------------------------------------------------------------------------
-- | Scanner for constructor names.
scanConName :: Scanner IO Location [Char] (Location, String)
scanConName
= munchPred Nothing matchConName acceptConName
-- | Match a constructor name.
matchConName :: Int -> Char -> Bool
matchConName 0 c = isConStart c
matchConName _ c = isConBody c
-- | Accept a constructor name.
acceptConName :: String -> Maybe String
acceptConName ss
| isConName ss = Just ss
| otherwise = Nothing
-- | String is a constructor name.
isConName :: String -> Bool
isConName str
= case str of
[] -> False
c : cs
| isConStart c
, and (map isConBody cs)
-> True
| _ : _ <- cs
, Just initCs <- takeInit cs
, isConStart c
, and (map isConBody initCs)
, last cs == '#'
-> True
| otherwise
-> False
-- | Character can start a constructor name.
isConStart :: Char -> Bool
isConStart
= Char.isUpper
-- | Charater can be part of a constructor body.
isConBody :: Char -> Bool
isConBody c
= Char.isUpper c
|| Char.isLower c
|| Char.isDigit c
|| c == '_'
|| c == '\''
|| c == '#'