{-# LANGUAGE LambdaCase #-}
module BNFC.Backend.OCaml.CFtoOCamlShow (cf2show, showsFunQual) where
import Data.Char(toLower)
import Data.List (intersperse)
import Data.Maybe (fromJust)
import BNFC.CF
import BNFC.Utils
import BNFC.Backend.OCaml.OCamlUtil
cf2show :: String -> ModuleName -> CF -> String
cf2show :: [Char] -> [Char] -> CF -> [Char]
cf2show [Char]
_name [Char]
absMod CF
cf = [[Char]] -> [Char]
unlines
[ [Char]
prologue
, [Char]
integerRule
, [Char]
doubleRule
, if CF -> Bool
forall f. CFG f -> Bool
hasIdent CF
cf then [Char] -> CF -> [Char]
identRule [Char]
absMod CF
cf else [Char]
""
, [[Char]] -> [Char]
unlines [ [Char] -> CF -> [Char] -> [Char]
ownPrintRule [Char]
absMod CF
cf [Char]
own | ([Char]
own,Reg
_) <- CF -> [([Char], Reg)]
forall f. CFG f -> [([Char], Reg)]
tokenPragmas CF
cf ]
, [Char] -> CF -> [Char]
rules [Char]
absMod CF
cf
]
prologue :: String
prologue :: [Char]
prologue = [[Char]] -> [Char]
unlines [
[Char]
"(* show functions *)",
[Char]
"",
[Char]
"(* use string buffers for efficient string concatenations *)",
[Char]
"type showable = Buffer.t -> unit",
[Char]
"",
[Char]
"let show (s : showable) : string = ",
[Char]
" let init_size = 16 in (* you may want to adjust this *)",
[Char]
" let b = Buffer.create init_size in",
[Char]
" s b;",
[Char]
" Buffer.contents b",
[Char]
" ",
[Char]
"let emptyS : showable = fun buf -> ()",
[Char]
"",
[Char]
"let c2s (c:char) : showable = fun buf -> Buffer.add_char buf c",
[Char]
"let s2s (s:string) : showable = fun buf -> Buffer.add_string buf s",
[Char]
"",
[Char]
"let ( >> ) (s1 : showable) (s2 : showable) : showable = fun buf -> s1 buf; s2 buf",
[Char]
"",
[Char]
"let showChar (c:char) : showable = fun buf -> ",
[Char]
" Buffer.add_string buf (\"'\" ^ Char.escaped c ^ \"'\")",
[Char]
"",
[Char]
"let showString (s:string) : showable = fun buf -> ",
[Char]
" Buffer.add_string buf (\"\\\"\" ^ String.escaped s ^ \"\\\"\")",
[Char]
"",
[Char]
"let showList (showFun : 'a -> showable) (xs : 'a list) : showable = fun buf -> ",
[Char]
" let rec f ys = match ys with",
[Char]
" [] -> ()",
[Char]
" | [y] -> showFun y buf",
[Char]
" | y::ys -> showFun y buf; Buffer.add_string buf \"; \"; f ys ",
[Char]
" in",
[Char]
" Buffer.add_char buf '[';",
[Char]
" f xs;",
[Char]
" Buffer.add_char buf ']'",
[Char]
""
]
integerRule :: [Char]
integerRule = [Char]
"let showInt (i:int) : showable = s2s (string_of_int i)"
doubleRule :: [Char]
doubleRule = [Char]
"let showFloat (f:float) : showable = s2s (string_of_float f)"
identRule :: [Char] -> CF -> [Char]
identRule [Char]
absMod CF
cf = [Char] -> CF -> [Char] -> [Char]
ownPrintRule [Char]
absMod CF
cf [Char]
catIdent
ownPrintRule :: ModuleName -> CF -> TokenCat -> String
ownPrintRule :: [Char] -> CF -> [Char] -> [Char]
ownPrintRule [Char]
absMod CF
cf [Char]
own =
[Char]
"let rec" [Char] -> [Char] -> [Char]
+++ Cat -> [Char]
showsFun ([Char] -> Cat
TokenCat [Char]
own) [Char] -> [Char] -> [Char]
+++ [Char]
"(" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
absMod [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"." [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
own [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
posn [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
") : showable = s2s \""
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
own [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" \" >> showString i"
where
posn :: [Char]
posn = if CF -> [Char] -> Bool
forall f. CFG f -> [Char] -> Bool
isPositionCat CF
cf [Char]
own then [Char]
" (_,i)" else [Char]
" i"
rules :: ModuleName -> CF -> String
rules :: [Char] -> CF -> [Char]
rules [Char]
absMod CF
cf = [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [[Char]]
mutualDefs ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$
((Cat, [([Char], [Cat])]) -> [Char])
-> [(Cat, [([Char], [Cat])])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (\ (Cat
s, [([Char], [Cat])]
xs) -> [Char]
-> Cat
-> [(([Char], [[Char]]), (Cat, [Either Cat [Char]]))]
-> [Char]
forall {a} {b}.
[Char]
-> Cat -> [(([Char], [[Char]]), (a, [Either Cat b]))] -> [Char]
case_fun [Char]
absMod Cat
s ([(([Char], [[Char]]), (Cat, [Either Cat [Char]]))] -> [Char])
-> [(([Char], [[Char]]), (Cat, [Either Cat [Char]]))] -> [Char]
forall a b. (a -> b) -> a -> b
$ (([Char], [Cat])
-> (([Char], [[Char]]), (Cat, [Either Cat [Char]])))
-> [([Char], [Cat])]
-> [(([Char], [[Char]]), (Cat, [Either Cat [Char]]))]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Cat]) -> (([Char], [[Char]]), (Cat, [Either Cat [Char]]))
toArgs [([Char], [Cat])]
xs) ([(Cat, [([Char], [Cat])])] -> [[Char]])
-> [(Cat, [([Char], [Cat])])] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ CF -> [(Cat, [([Char], [Cat])])]
cf2data CF
cf
where
toArgs :: ([Char], [Cat]) -> (([Char], [[Char]]), (Cat, [Either Cat [Char]]))
toArgs ([Char]
cons,[Cat]
args) = (([Char]
cons, [[Char]] -> Int -> [[Char]]
forall {t}. (Show t, Num t) => [[Char]] -> t -> [[Char]]
names ((Cat -> [Char]) -> [Cat] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char]
checkRes ([Char] -> [Char]) -> (Cat -> [Char]) -> Cat -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cat -> [Char]
var) [Cat]
args) (Int
0 :: Int)),
[Char] -> (Cat, [Either Cat [Char]])
ruleOf [Char]
cons)
names :: [[Char]] -> t -> [[Char]]
names [] t
_ = []
names ([Char]
x:[[Char]]
xs) t
n
| [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem [Char]
x [[Char]]
xs = ([Char]
x [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ t -> [Char]
forall a. Show a => a -> [Char]
show t
n) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [[Char]] -> t -> [[Char]]
names [[Char]]
xs (t
nt -> t -> t
forall a. Num a => a -> a -> a
+t
1)
| Bool
otherwise = [Char]
x [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [[Char]] -> t -> [[Char]]
names [[Char]]
xs t
n
var :: Cat -> [Char]
var (ListCat Cat
c) = Cat -> [Char]
var Cat
c [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"s"
var (Cat [Char]
"Ident") = [Char]
"id"
var (Cat [Char]
"Integer") = [Char]
"n"
var (Cat [Char]
"String") = [Char]
"str"
var (Cat [Char]
"Char") = [Char]
"c"
var (Cat [Char]
"Double") = [Char]
"d"
var Cat
cat = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (Cat -> [Char]
catToStr Cat
cat)
checkRes :: [Char] -> [Char]
checkRes [Char]
s
| [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem [Char]
s [[Char]]
reservedOCaml = [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
| Bool
otherwise = [Char]
s
ruleOf :: [Char] -> (Cat, [Either Cat [Char]])
ruleOf [Char]
s = Maybe (Cat, [Either Cat [Char]]) -> (Cat, [Either Cat [Char]])
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (Cat, [Either Cat [Char]]) -> (Cat, [Either Cat [Char]]))
-> Maybe (Cat, [Either Cat [Char]]) -> (Cat, [Either Cat [Char]])
forall a b. (a -> b) -> a -> b
$ WithPosition [Char]
-> [Rul (WithPosition [Char])] -> Maybe (Cat, [Either Cat [Char]])
forall f. Eq f => f -> [Rul f] -> Maybe (Cat, [Either Cat [Char]])
lookupRule ([Char] -> WithPosition [Char]
forall a. a -> WithPosition a
noPosition [Char]
s) (CF -> [Rul (WithPosition [Char])]
forall function. CFG function -> [Rul function]
cfgRules CF
cf)
case_fun :: [Char]
-> Cat -> [(([Char], [[Char]]), (a, [Either Cat b]))] -> [Char]
case_fun [Char]
absMod Cat
cat [(([Char], [[Char]]), (a, [Either Cat b]))]
xs = [[Char]] -> [Char]
unlines [
Cat -> [Char]
showsFun Cat
cat [Char] -> [Char] -> [Char]
+++ [Char]
"(e : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> Cat -> [Char]
fixTypeQual [Char]
absMod Cat
cat [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
") : showable = match e with",
[[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [[Char]]
insertBar ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ ((([Char], [[Char]]), (a, [Either Cat b])) -> [Char])
-> [(([Char], [[Char]]), (a, [Either Cat b]))] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (\ (([Char]
c,[[Char]]
xx),(a, [Either Cat b])
r) ->
[Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
absMod [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"." [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
c [Char] -> [Char] -> [Char]
+++ [[Char]] -> [Char]
mkTuple [[Char]]
xx [Char] -> [Char] -> [Char]
+++ [Char]
"->" [Char] -> [Char] -> [Char]
+++
[Char]
"s2s" [Char] -> [Char] -> [Char]
+++ [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
c [Char] -> [Char] -> [Char]
+++
case [[Char]] -> [Either Cat b] -> [Char]
forall {b}. [[Char]] -> [Either Cat b] -> [Char]
mkRhs [[Char]]
xx ((a, [Either Cat b]) -> [Either Cat b]
forall a b. (a, b) -> b
snd (a, [Either Cat b])
r) of {[] -> []; [Char]
str -> [Char]
">> c2s ' ' >> " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
str}
)
[(([Char], [[Char]]), (a, [Either Cat b]))]
xs
]
mkRhs :: [[Char]] -> [Either Cat b] -> [Char]
mkRhs [[Char]]
args [Either Cat b]
its =
case [[Char]] -> [Char]
unwords ([Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
intersperse [Char]
" >> s2s \", \" >> " ([[Char]] -> [Either Cat b] -> [[Char]]
forall {b}. [[Char]] -> [Either Cat b] -> [[Char]]
mk [[Char]]
args [Either Cat b]
its)) of
[] -> [Char]
""
[Char]
str -> [Char]
"c2s '(' >> " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
str [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" >> c2s ')'"
where
mk :: [[Char]] -> [Either Cat b] -> [[Char]]
mk ([Char]
arg:[[Char]]
args) (Left Cat
c : [Either Cat b]
items) = (Cat -> [Char]
showsFun Cat
c [Char] -> [Char] -> [Char]
+++ [Char]
arg) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [[Char]] -> [Either Cat b] -> [[Char]]
mk [[Char]]
args [Either Cat b]
items
mk [[Char]]
args (Right b
_ : [Either Cat b]
items) = [[Char]] -> [Either Cat b] -> [[Char]]
mk [[Char]]
args [Either Cat b]
items
mk [[Char]]
_ [Either Cat b]
_ = []
showsFun :: Cat -> String
showsFun :: Cat -> [Char]
showsFun = ([Char] -> [Char]) -> Cat -> [Char]
showsFunQual [Char] -> [Char]
forall a. a -> a
id
showsFunQual :: (String -> String) -> Cat -> String
showsFunQual :: ([Char] -> [Char]) -> Cat -> [Char]
showsFunQual [Char] -> [Char]
qual = Cat -> [Char]
loop where
loop :: Cat -> [Char]
loop = \case
ListCat Cat
c -> [Char] -> [Char]
qual [Char]
"showList" [Char] -> [Char] -> [Char]
+++ Cat -> [Char]
loop Cat
c
Cat
c -> [Char] -> [Char]
qual [Char]
"show" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Cat -> [Char]
fixTypeUpper (Cat -> [Char]) -> Cat -> [Char]
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
c)