module Hpack.Haskell (
  isModule
, isQualifiedIdentifier
, isIdentifier
) where

import           Data.Char

isModule :: [String] -> Bool
isModule :: [String] -> Bool
isModule name :: [String]
name = (Bool -> Bool
not (Bool -> Bool) -> ([String] -> Bool) -> [String] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) [String]
name Bool -> Bool -> Bool
&& (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all String -> Bool
isModuleName [String]
name

isModuleName :: String -> Bool
isModuleName :: String -> Bool
isModuleName name :: String
name = case String
name of
  x :: Char
x : xs :: String
xs -> Char -> Bool
isUpper Char
x Bool -> Bool -> Bool
&& (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isIdChar String
xs
  _ -> Bool
False

isQualifiedIdentifier :: [String] -> Bool
isQualifiedIdentifier :: [String] -> Bool
isQualifiedIdentifier name :: [String]
name = case [String] -> [String]
forall a. [a] -> [a]
reverse [String]
name of
  x :: String
x : xs :: [String]
xs  -> String -> Bool
isIdentifier String
x Bool -> Bool -> Bool
&& [String] -> Bool
isModule [String]
xs
  _ -> Bool
False

isIdentifier :: String -> Bool
isIdentifier :: String -> Bool
isIdentifier name :: String
name = case String
name of
  x :: Char
x : xs :: String
xs -> Char -> Bool
isLower Char
x Bool -> Bool -> Bool
&& (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isIdChar String
xs Bool -> Bool -> Bool
&& String
name String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String]
reserved
  _ -> Bool
False

reserved :: [String]
reserved :: [String]
reserved = [
    "case"
  , "class"
  , "data"
  , "default"
  , "deriving"
  , "do"
  , "else"
  , "foreign"
  , "if"
  , "import"
  , "in"
  , "infix"
  , "infixl"
  , "infixr"
  , "instance"
  , "let"
  , "module"
  , "newtype"
  , "of"
  , "then"
  , "type"
  , "where"
  , "_"
  ]

isIdChar :: Char -> Bool
isIdChar :: Char -> Bool
isIdChar c :: Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '_' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '\''