{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module BNFC.Backend.Haskell.Utils
( comment, commentWithEmacsModeHint
, posType, posConstr, noPosConstr
, hasPositionClass, hasPositionMethod
, noWarnUnusedMatches
, parserName
, hsReservedWords, avoidReservedWords, mkDefName
, typeToHaskell, typeToHaskell'
, catToType
, catToVar, catvars
, tokenTextImport, tokenTextType
, tokenTextPack, tokenTextPackParens, tokenTextUnpack
) where
import Data.Char
import Data.String (IsString)
import BNFC.PrettyPrint
import qualified BNFC.PrettyPrint as P
import BNFC.CF (Cat(..), catToStr, identCat, baseTokenCatNames, Base, Type(FunT), IsFun(..))
import BNFC.Options (TokenText(..))
import BNFC.Utils (mkNames, NameStyle(..))
comment :: String -> String
= (String
"-- " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
commentWithEmacsModeHint :: String -> String
= String -> String
comment (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"-*- haskell -*- " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
noWarnUnusedMatches :: IsString a => a
noWarnUnusedMatches :: forall a. IsString a => a
noWarnUnusedMatches =
a
"{-# OPTIONS_GHC -fno-warn-unused-matches #-}"
posType, posConstr, noPosConstr :: IsString a => a
posType :: forall a. IsString a => a
posType = a
"BNFC'Position"
posConstr :: forall a. IsString a => a
posConstr = a
"BNFC'Position"
noPosConstr :: forall a. IsString a => a
noPosConstr = a
"BNFC'NoPosition"
hasPositionClass, hasPositionMethod :: IsString a => a
hasPositionClass :: forall a. IsString a => a
hasPositionClass = a
"HasPosition"
hasPositionMethod :: forall a. IsString a => a
hasPositionMethod = a
"hasPosition"
tokenTextImport :: TokenText -> [String]
tokenTextImport :: TokenText -> [String]
tokenTextImport = \case
TokenText
StringToken -> []
TokenText
ByteStringToken -> [ String
"import qualified Data.ByteString.Char8 as BS" ]
TokenText
TextToken -> [ String
"import qualified Data.Text" ]
tokenTextType :: TokenText -> String
tokenTextType :: TokenText -> String
tokenTextType = \case
TokenText
StringToken -> String
"String"
TokenText
ByteStringToken -> String
"BS.ByteString"
TokenText
TextToken -> String
"Data.Text.Text"
tokenTextPack :: TokenText -> String -> String
tokenTextPack :: TokenText -> String -> String
tokenTextPack = \case
TokenText
StringToken -> String -> String
forall a. a -> a
id
TokenText
ByteStringToken -> (String
"BS.pack " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
TokenText
TextToken -> (String
"Data.Text.pack " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
tokenTextPackParens :: TokenText -> String -> String
tokenTextPackParens :: TokenText -> String -> String
tokenTextPackParens = \case
TokenText
StringToken -> String -> String
forall a. a -> a
id
TokenText
ByteStringToken -> String -> String
parens (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"BS.pack " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
TokenText
TextToken -> String -> String
parens (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"Data.Text.pack " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
where
parens :: String -> String
parens :: String -> String
parens String
s = String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
tokenTextUnpack :: TokenText -> String -> String
tokenTextUnpack :: TokenText -> String -> String
tokenTextUnpack TokenText
t String
s = case TokenText
t of
TokenText
StringToken -> String
s
TokenText
ByteStringToken -> String
"(BS.unpack " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
TokenText
TextToken -> String
"(Data.Text.unpack " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
parserName :: Cat -> Doc
parserName :: Cat -> Doc
parserName = (Doc
"p" Doc -> Doc -> Doc
P.<>) (Doc -> Doc) -> (Cat -> Doc) -> Cat -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Doc
text (String -> Doc) -> (Cat -> String) -> Cat -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cat -> String
identCat
hsReservedWords :: [String]
hsReservedWords :: [String]
hsReservedWords =
[ String
"as"
, String
"case"
, String
"class"
, String
"data"
, String
"default"
, String
"deriving"
, String
"do"
, String
"else"
, String
"family"
, String
"forall"
, String
"foreign"
, String
"hiding"
, String
"if"
, String
"import"
, String
"in"
, String
"infix"
, String
"infixl"
, String
"infixr"
, String
"instance"
, String
"let"
, String
"mdo"
, String
"module"
, String
"newtype"
, String
"of"
, String
"pattern"
, String
"proc"
, String
"qualified"
, String
"rec"
, String
"then"
, String
"type"
, String
"where"
]
avoidReservedWords :: [String] -> String -> String
avoidReservedWords :: [String] -> String -> String
avoidReservedWords [String]
additionalReserved String
x
| String
x String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
reserved = String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'"
| Bool
otherwise = String
x
where
reserved :: [String]
reserved = [String]
additionalReserved [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
hsReservedWords
mkDefName :: IsFun f => f -> String
mkDefName :: forall f. IsFun f => f -> String
mkDefName = [String] -> String -> String
avoidReservedWords [] (String -> String) -> (f -> String) -> f -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f -> String
forall f. IsFun f => f -> String
funName
catToType :: (Doc -> Doc) -> Doc -> Cat -> Doc
catToType :: (Doc -> Doc) -> Doc -> Cat -> Doc
catToType Doc -> Doc
qualify Doc
param Cat
cat = Bool -> Doc -> Doc
parensIf Bool
isApp (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Cat -> Doc
loop Cat
cat
where
isApp :: Bool
isApp = case Cat
cat of
Cat String
_ -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Doc -> Bool
isEmpty Doc
param
Cat
_ -> Bool
False
loop :: Cat -> Doc
loop = \case
ListCat Cat
c -> Doc -> Doc
brackets (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ Cat -> Doc
loop Cat
c
Cat String
c -> Doc -> Doc
qualify (String -> Doc
text String
c) Doc -> Doc -> Doc
<+> Doc
param
CoercCat String
c Integer
_ -> Doc -> Doc
qualify (String -> Doc
text String
c) Doc -> Doc -> Doc
<+> Doc
param
TokenCat String
c
| String
c String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
baseTokenCatNames
-> String -> Doc
text String
c
| Bool
otherwise -> Doc -> Doc
qualify (String -> Doc
text String
c)
baseTypeToHaskell :: Base -> String
baseTypeToHaskell :: Base -> String
baseTypeToHaskell = Base -> String
forall a. Show a => a -> String
show
typeToHaskell :: Type -> String
typeToHaskell :: Type -> String
typeToHaskell = String -> Type -> String
typeToHaskell' String
"->"
typeToHaskell' :: String -> Type -> String
typeToHaskell' :: String -> Type -> String
typeToHaskell' String
arr (FunT [Base]
ts Base
t) =
(String -> String -> String) -> String -> [String] -> String
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr String -> String -> String
f (Base -> String
baseTypeToHaskell Base
t) ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (Base -> String) -> [Base] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Base -> String
baseTypeToHaskell [Base]
ts
where f :: String -> String -> String
f String
a String
b = [String] -> String
unwords [String
a, String
arr, String
b]
catToVar :: [String] -> Cat -> String
catToVar :: [String] -> Cat -> String
catToVar [String]
rs = [String] -> String -> String
avoidReservedWords [String]
rs (String -> String) -> (Cat -> String) -> Cat -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cat -> String
var
where
var :: Cat -> String
var (ListCat Cat
cat) = Cat -> String
var Cat
cat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"s"
var (Cat String
"Ident") = String
"x"
var (Cat String
"Integer") = String
"n"
var (Cat String
"String") = String
"str"
var (Cat String
"Char") = String
"c"
var (Cat String
"Double") = String
"d"
var Cat
xs = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Cat -> String
catToStr Cat
xs
catvars :: [String] -> [Cat] -> [Doc]
catvars :: [String] -> [Cat] -> [Doc]
catvars [String]
rs = (String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text ([String] -> [Doc]) -> ([Cat] -> [String]) -> [Cat] -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> NameStyle -> [String] -> [String]
mkNames ([String]
rs [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
hsReservedWords) NameStyle
LowerCase ([String] -> [String]) -> ([Cat] -> [String]) -> [Cat] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cat -> String) -> [Cat] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> String
var
where
var :: Cat -> String
var (ListCat Cat
c) = Cat -> String
var Cat
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"s"
var Cat
c = Cat -> String
catToStr Cat
c