packages feed

cgrep-9.0.0: src/CGrep/FileTypeMap.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE KindSignatures #-}
--
-- Copyright (c) 2013-2025 Nicola Bonelli <nicola@larthia.com>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
--
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}

module CGrep.FileTypeMap (
    FileTypeMap (..),
    FileTypeInfo (..),
    FileTypeInfoMap (..),
    CharSet (..),
    WordType (..),
    IsCharSet (..),
    CharIdentifierF,
    (~~),
    reserved,
    types,
) where

import CGrep.Boundary (Boundary (..))
import CGrep.FileKind
import CGrep.FileType (FileSelector (..), FileType (..))
import CGrep.Parser.Char
import Language.Haskell.TH.Syntax (Lift)

import qualified Data.HashMap.Strict as HM
import qualified Data.Map as Map
import qualified Data.Text as T

newtype FileTypeInfoMap = FileTypeInfoMap
    { unMapInfo :: Map.Map FileType FileTypeInfo
    }
    deriving stock (Eq, Show, Lift)

newtype FileTypeMap = FileTypeMap
    { unMap :: Map.Map FileSelector (FileType, FileKind)
    }

type CharIdentifierF = (Char -> Bool)

data WordType = Keyword | NativeType
    deriving stock (Eq, Ord, Show, Lift)

data FileTypeInfo = FileTypeInfo
    { ftSelector :: [FileSelector]
    , ftKind :: FileKind
    , ftChar :: [Boundary]
    , ftString :: [Boundary]
    , ftRawString :: [Boundary]
    , ftComment :: [Boundary]
    , ftIdentCharSet :: Maybe (CharSet, CharSet)
    , ftKeywords :: HM.HashMap T.Text WordType
    }
    deriving stock (Eq, Show, Lift)

data CharSet
    = None
    | Alpha
    | Alpha_
    | AlphaDollar_
    | AlphaNum
    | AlphaNum_
    | AlphaNum_'
    | AlphaNumDollar_
    | AlphaNumClojure_
    | AlphaDash_
    | AlphaNumDash_
    | Unicode_
    | UnicodeNum_
    | UnicodeDollar_
    | UnicodeNumDollar_
    | UnicodeNum_'
    | UnicodeXIDStart_
    | UnicodeNumXIDCont_
    | ClojureIdentStart
    | ClojureIdentCont
    | CSharpIdentStart
    | CSharpIdentCont
    | HtmlIdentStart
    | HtmlIdentCont
    | JavaIdentStart
    | JavaIdentCont
    | JuliaIdentStart
    | JuliaIdentCont
    | ListIdent
    | AgdaIdent
    deriving stock (Eq, Show, Lift)

class IsCharSet (cs :: CharSet) where
    isValidChar :: Char -> Bool

instance IsCharSet 'None where
    isValidChar _ = False
    {-# INLINE isValidChar #-}

instance IsCharSet 'Alpha where
    isValidChar = isAlpha
    {-# INLINE isValidChar #-}

instance IsCharSet 'Alpha_ where
    isValidChar = isAlpha_
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaNum where
    isValidChar = isAlphaNum
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaNum_ where
    isValidChar = isAlphaNum_
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaNum_' where
    isValidChar = isAlphaNum_'
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaDollar_ where
    isValidChar = isAlphaDollar_
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaNumDollar_ where
    isValidChar = isAlphaNumDollar_
    {-# INLINE isValidChar #-}

instance IsCharSet 'ClojureIdentStart where
    isValidChar = isClojureIdentStart
    {-# INLINE isValidChar #-}

instance IsCharSet 'ClojureIdentCont where
    isValidChar = isClojureIdentCont
    {-# INLINE isValidChar #-}

instance IsCharSet 'CSharpIdentStart where
    isValidChar = isCSharpIdentStart
    {-# INLINE isValidChar #-}

instance IsCharSet 'CSharpIdentCont where
    isValidChar = isCSharpIdentCont
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaDash_ where
    isValidChar = isAlphaDash_
    {-# INLINE isValidChar #-}

instance IsCharSet 'AlphaNumDash_ where
    isValidChar = isAlphaNumDash_
    {-# INLINE isValidChar #-}

instance IsCharSet 'HtmlIdentStart where
    isValidChar = isHtmlIdentStart
    {-# INLINE isValidChar #-}

instance IsCharSet 'HtmlIdentCont where
    isValidChar = isHtmlIdentCont
    {-# INLINE isValidChar #-}

instance IsCharSet 'JavaIdentStart where
    isValidChar = isJavaIdentStart
    {-# INLINE isValidChar #-}

instance IsCharSet 'JavaIdentCont where
    isValidChar = isJavaIdentCont
    {-# INLINE isValidChar #-}

instance IsCharSet 'JuliaIdentStart where
    isValidChar = isJuliaIdentStart
    {-# INLINE isValidChar #-}

instance IsCharSet 'JuliaIdentCont where
    isValidChar = isJuliaIdentCont
    {-# INLINE isValidChar #-}

instance IsCharSet 'ListIdent where
    isValidChar = isLispIdent
    {-# INLINE isValidChar #-}

instance IsCharSet 'Unicode_ where
    isValidChar = isUnicode_
    {-# INLINE isValidChar #-}

instance IsCharSet 'UnicodeNum_ where
    isValidChar = isUnicodeNum_
    {-# INLINE isValidChar #-}

instance IsCharSet 'UnicodeNum_' where
    isValidChar = isUnicodeNum_'
    {-# INLINE isValidChar #-}

instance IsCharSet 'UnicodeDollar_ where
    isValidChar = isUnicodeDollar_
    {-# INLINE isValidChar #-}

instance IsCharSet 'UnicodeNumDollar_ where
    isValidChar = isUnicodeNumDollar_
    {-# INLINE isValidChar #-}

instance IsCharSet 'UnicodeXIDStart_ where
    isValidChar = isUnicodeXIDStart_
    {-# INLINE isValidChar #-}

instance IsCharSet 'UnicodeNumXIDCont_ where
    isValidChar = isUnicodeNumXIDCont_
    {-# INLINE isValidChar #-}

instance IsCharSet 'AgdaIdent where
    isValidChar = isAgdaIdent
    {-# INLINE isValidChar #-}

(~~) :: T.Text -> T.Text -> Boundary
b ~~ e = Boundary{bBegin = b, bBeginLen = T.length b, bEnd = e, bEndLen = T.length e}
{-# INLINE (~~) #-}

reserved :: [T.Text] -> HM.HashMap T.Text WordType
reserved = HM.fromList . map (,Keyword)
{-# INLINE reserved #-}

types :: [T.Text] -> HM.HashMap T.Text WordType
types = HM.fromList . map (,NativeType)
{-# INLINE types #-}