inchworm-1.1.1.1: examples/mlish/Scanner/Named.hs
module Scanner.Named
(scanNamed)
where
import Token
import Text.Lexer.Inchworm.Char
import qualified Data.Char as Char
-- Named ---------------------------------------------------------------------
-- | Scan a named thing.
scanNamed :: Scanner IO Location [Char] (Range Location, Token)
scanNamed = alt scanKeyVar scanCon
-- Variables and Keywords -----------------------------------------------------
keywords
= [ "import", "export"
, "box", "run"
, "let", "in"
, "case", "of"
, "do"
, "if", "then", "else"]
-- | Scan a keyword or variable.
scanKeyVar :: Scanner IO Location [Char] (Range Location, Token)
scanKeyVar
= munchPred Nothing matchKeyVar acceptKeyVar
where
matchKeyVar :: Int -> Char -> Bool
matchKeyVar 0 c = isVarStart c
matchKeyVar _ c = isVarBody c
acceptKeyVar :: [Char] -> Maybe Token
acceptKeyVar cs
| elem cs keywords = Just $ KKeyWord cs
| otherwise = Just $ KVar cs
isVarStart :: Char -> Bool
isVarStart c
= Char.isLower c
|| c == '?'
isVarBody :: Char -> Bool
isVarBody c
= Char.isAlpha c
|| Char.isDigit c
|| c == '_' || c == '\'' || c == '$' || c == '#'
-- Constructors ---------------------------------------------------------------
scanCon :: Scanner IO Location [Char] (Range Location, Token)
scanCon
= munchPred Nothing matchCon acceptCon
where
matchCon 0 c = isConStart c
matchCon _ c = isConBody c
acceptCon cs = Just $ KCon cs
-- | Character can start a constructor name
isConStart :: Char -> Bool
isConStart c
= Char.isUpper c
-- | Character can be in the body of a constructor name.
isConBody :: Char -> Bool
isConBody c
= Char.isAlpha c
|| Char.isDigit c
|| c == '_' || c == '\'' || c == '#'