----------------------------------------------------------------------------- -- | -- Module : Text.Trifecta.Parser.Identifier -- Copyright : (c) Edward Kmett 2011 -- License : BSD3 -- -- Maintainer : ekmett@gmail.com -- Stability : provisional -- Portability : non-portable -- -- > idStyle = haskellIdentifierStyle { styleReserved = ... } -- > identifier = ident haskellIdentifierStyle -- > reserved = reserve haskellIdentifierStyle -- ----------------------------------------------------------------------------- module Text.Trifecta.Parser.Identifier ( IdentifierStyle(..) , liftIdentifierStyle , ident , reserve , reserveByteString ) where import Data.ByteString as Strict hiding (map, zip, foldl, foldr) import Data.ByteString.UTF8 as UTF8 import Data.HashSet as HashSet import Control.Applicative import Control.Monad (when) import Control.Monad.Trans.Class import Text.Trifecta.Parser.Class import Text.Trifecta.Parser.Char import Text.Trifecta.Parser.Combinators import Text.Trifecta.Parser.Token.Combinators import Text.Trifecta.Highlight.Prim data IdentifierStyle m = IdentifierStyle { styleName :: String , styleStart :: m () , styleLetter :: m () , styleReserved :: HashSet ByteString , styleHighlight :: Highlight , styleReservedHighlight :: Highlight } -- | Lift an identifier style into a monad transformer liftIdentifierStyle :: (MonadTrans t, Monad m) => IdentifierStyle m -> IdentifierStyle (t m) liftIdentifierStyle s = s { styleStart = lift (styleStart s) , styleLetter = lift (styleLetter s) } -- | parse a reserved operator or identifier using a given style reserve :: MonadParser m => IdentifierStyle m -> String -> m () reserve s name = reserveByteString s $! UTF8.fromString name -- | parse a reserved operator or identifier using a given style specified by bytestring reserveByteString :: MonadParser m => IdentifierStyle m -> ByteString -> m () reserveByteString s name = lexeme $ try $ do _ <- highlight (styleReservedHighlight s) $ byteString name notFollowedBy (styleLetter s) "end of " ++ show name -- | parse an non-reserved identifier or symbol ident :: MonadParser m => IdentifierStyle m -> m ByteString ident s = lexeme $ try $ do name <- highlight (styleHighlight s) (sliced (styleStart s *> skipMany (styleLetter s))) styleName s when (member name (styleReserved s)) $ unexpected $ "reserved " ++ styleName s ++ " " ++ show name return name