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
}
liftIdentifierStyle :: (MonadTrans t, Monad m) => IdentifierStyle m -> IdentifierStyle (t m)
liftIdentifierStyle s =
s { styleStart = lift (styleStart s)
, styleLetter = lift (styleLetter s)
}
reserve :: MonadParser m => IdentifierStyle m -> String -> m ()
reserve s name = reserveByteString s $! UTF8.fromString name
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
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