{-# LANGUAGE NoImplicitPrelude #-}

{-
    BNF Converter: Java Top File
    Copyright (C) 2004  Author:  Markus Forsberg, Peter Gammie,
                                 Michael Pellauer, Bjorn Bringert

-}

-------------------------------------------------------------------
-- |
-- Module      :  JavaTop
-- Copyright   :  (C)opyright 2003, {markus, aarne, pellauer, peteg, bringert} at cs dot chalmers dot se
--
-- Maintainer  :  {markus, aarne} at cs dot chalmers dot se
-- Stability   :  alpha
-- Portability :  Haskell98
--
-- Top-level for the Java back end.
--
-- > $Id: JavaTop15.hs,v 1.12 2007/01/08 18:20:23 aarne Exp $
-------------------------------------------------------------------

module BNFC.Backend.Java ( makeJava ) where

import Prelude hiding ((<>))

import System.FilePath (pathSeparator, isPathSeparator)
import Data.Foldable (toList)
import Data.List ( intersperse )

import BNFC.Utils
import BNFC.CF
import BNFC.Options as Options
import BNFC.Backend.Base
import BNFC.Backend.Java.Utils
import BNFC.Backend.Java.CFtoCup15 ( cf2Cup )
import BNFC.Backend.Java.CFtoJLex15
import BNFC.Backend.Java.CFtoAntlr4Lexer
import BNFC.Backend.Java.CFtoAntlr4Parser
import BNFC.Backend.Java.CFtoJavaAbs15 ( cf2JavaAbs )
import BNFC.Backend.Java.CFtoJavaPrinter15
import BNFC.Backend.Java.CFtoVisitSkel15
import BNFC.Backend.Java.CFtoComposVisitor
import BNFC.Backend.Java.CFtoAbstractVisitor
import BNFC.Backend.Java.CFtoFoldVisitor
import BNFC.Backend.Java.CFtoAllVisitor
import BNFC.Backend.Common.NamedVariables (SymEnv, firstLowerCase)
import qualified BNFC.Backend.Common.Makefile as Makefile
import BNFC.PrettyPrint

-------------------------------------------------------------------
-- | Build the Java output.
-------------------------------------------------------------------

-- | This creates the Java files.
makeJava :: SharedOptions -> CF -> MkFiles ()
makeJava :: SharedOptions -> CF -> MkFiles ()
makeJava SharedOptions
opt = SharedOptions -> CF -> MkFiles ()
makeJava' SharedOptions
opt{ lang :: [Char]
lang = [[Char]] -> NameStyle -> [Char] -> [Char]
mkName [[Char]]
javaReserved NameStyle
SnakeCase ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ SharedOptions -> [Char]
lang SharedOptions
opt }
  -- issue #212: make a legal package name, see also
  -- https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html

makeJava' :: SharedOptions -> CF -> MkFiles ()
makeJava' :: SharedOptions -> CF -> MkFiles ()
makeJava' options :: SharedOptions
options@Options{Bool
Int
[Char]
Maybe [Char]
TokenText
RecordPositions
JavaLexerParser
OCamlParser
HappyMode
AlexVersion
Target
wcf :: SharedOptions -> Bool
visualStudio :: SharedOptions -> Bool
javaLexerParser :: SharedOptions -> JavaLexerParser
ocamlParser :: SharedOptions -> OCamlParser
agda :: SharedOptions -> Bool
xml :: SharedOptions -> Int
glr :: SharedOptions -> HappyMode
tokenText :: SharedOptions -> TokenText
alexMode :: SharedOptions -> AlexVersion
generic :: SharedOptions -> Bool
functor :: SharedOptions -> Bool
inDir :: SharedOptions -> Bool
linenumbers :: SharedOptions -> RecordPositions
inPackage :: SharedOptions -> Maybe [Char]
make :: SharedOptions -> Maybe [Char]
target :: SharedOptions -> Target
force :: SharedOptions -> Bool
outDir :: SharedOptions -> [Char]
lbnfFile :: SharedOptions -> [Char]
wcf :: Bool
visualStudio :: Bool
javaLexerParser :: JavaLexerParser
ocamlParser :: OCamlParser
agda :: Bool
xml :: Int
glr :: HappyMode
tokenText :: TokenText
alexMode :: AlexVersion
generic :: Bool
functor :: Bool
inDir :: Bool
linenumbers :: RecordPositions
inPackage :: Maybe [Char]
make :: Maybe [Char]
target :: Target
force :: Bool
outDir :: [Char]
lang :: [Char]
lbnfFile :: [Char]
lang :: SharedOptions -> [Char]
..} CF
cf = do
     -- Create the package directories if necessary.
    let packageBase :: [Char]
packageBase  = ([Char] -> [Char])
-> ([Char] -> [Char] -> [Char]) -> Maybe [Char] -> [Char] -> [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char] -> [Char]
forall a. a -> a
id [Char] -> [Char] -> [Char]
(+.+) Maybe [Char]
inPackage [Char]
lang
        packageAbsyn :: [Char]
packageAbsyn = [Char]
packageBase [Char] -> [Char] -> [Char]
+.+ [Char]
"Absyn"
        dirBase :: [Char]
dirBase      = [Char] -> [Char]
pkgToDir [Char]
packageBase
        dirAbsyn :: [Char]
dirAbsyn     = [Char] -> [Char]
pkgToDir [Char]
packageAbsyn
        javaex :: [Char] -> [Char]
javaex [Char]
str   = [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
str [Char] -> [Char] -> [Char]
+.+ [Char]
"java"
        bnfcfiles :: BNFCGeneratedEntities
bnfcfiles    =
          [Char]
-> [Char]
-> CF
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> BNFCGeneratedEntities
bnfcVisitorsAndTests
            [Char]
packageBase
            [Char]
packageAbsyn
            CF
cf
            CFToJava
cf2JavaPrinter
            CFToJava
cf2VisitSkel
            CFToJava
cf2ComposVisitor
            CFToJava
cf2AbstractVisitor
            CFToJava
cf2FoldVisitor
            CFToJava
cf2AllVisitor
            (ParserLexerSpecification -> TestClass
testclass ParserLexerSpecification
parselexspec
                ([[Char]] -> [Char]
forall a. [a] -> a
head ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ MakeFileDetails -> [[Char]]
results MakeFileDetails
lexmake) -- lexer class
                ([[Char]] -> [Char]
forall a. [a] -> a
head ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake) -- parser class
            )
        makebnfcfile :: (BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], c)
x = [Char] -> c -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile ([Char] -> [Char]
javaex (([Char], c) -> [Char]
forall a b. (a, b) -> a
fst (([Char], c) -> [Char]) -> ([Char], c) -> [Char]
forall a b. (a -> b) -> a -> b
$ BNFCGeneratedEntities -> ([Char], c)
x BNFCGeneratedEntities
bnfcfiles))
                                        (([Char], c) -> c
forall a b. (a, b) -> b
snd (([Char], c) -> c) -> ([Char], c) -> c
forall a b. (a -> b) -> a -> b
$ BNFCGeneratedEntities -> ([Char], c)
x BNFCGeneratedEntities
bnfcfiles)

    let absynFiles :: [([Char], [Char])]
absynFiles = [([Char], [Char])] -> [([Char], [Char])]
forall {a} {b}. Eq a => [(a, b)] -> [(a, b)]
remDups ([([Char], [Char])] -> [([Char], [Char])])
-> [([Char], [Char])] -> [([Char], [Char])]
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char] -> CF -> RecordPositions -> [([Char], [Char])]
cf2JavaAbs [Char]
packageBase [Char]
packageAbsyn CF
cf RecordPositions
rp
        absynBaseNames :: [[Char]]
absynBaseNames = (([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst [([Char], [Char])]
absynFiles
        absynFileNames :: [[Char]]
absynFileNames = ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
dirAbsyn [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++) [[Char]]
absynBaseNames
    let writeAbsyn :: ([Char], c) -> MkFiles ()
writeAbsyn ([Char]
filename, c
contents) =
          [Char] -> c -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile ([Char]
dirAbsyn [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
filename [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".java") c
contents
    (([Char], [Char]) -> MkFiles ())
-> [([Char], [Char])] -> MkFiles ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ([Char], [Char]) -> MkFiles ()
forall {c}. FileContent c => ([Char], c) -> MkFiles ()
writeAbsyn [([Char], [Char])]
absynFiles
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
bprettyprinter
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
bskel
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
bcompos
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
babstract
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
bfold
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
ball
    (BNFCGeneratedEntities -> ([Char], [Char])) -> MkFiles ()
forall {c}.
FileContent c =>
(BNFCGeneratedEntities -> ([Char], c)) -> MkFiles ()
makebnfcfile BNFCGeneratedEntities -> ([Char], [Char])
btest
    let (Doc
lex, [([Char], [Char])]
env) = CF2LexerFunction
lexfun [Char]
packageBase CF
cf
    -- Where the lexer file is created. lex is the content!
    [Char] -> Doc -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile ([Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [Char]
inputfile MakeFileDetails
lexmake ) Doc
lex
    IO () -> MkFiles ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MkFiles ()) -> IO () -> MkFiles ()
forall a b. (a -> b) -> a -> b
$ [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"   (Tested with" [Char] -> [Char] -> [Char]
+++ MakeFileDetails -> [Char]
toolname MakeFileDetails
lexmake
                                          [Char] -> [Char] -> [Char]
+++ MakeFileDetails -> [Char]
toolversion MakeFileDetails
lexmake  [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
    -- where the parser file is created.
    [Char] -> [Char] -> MkFiles ()
forall c. FileContent c => [Char] -> c -> MkFiles ()
mkfile ([Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [Char]
inputfile MakeFileDetails
parmake)
          ([Char] -> MkFiles ()) -> [Char] -> MkFiles ()
forall a b. (a -> b) -> a -> b
$ CF2ParserFunction
parsefun [Char]
packageBase [Char]
packageAbsyn CF
cf RecordPositions
rp [([Char], [Char])]
env
    IO () -> MkFiles ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MkFiles ()) -> IO () -> MkFiles ()
forall a b. (a -> b) -> a -> b
$ [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$
      if MakeFileDetails -> Bool
supportsEntryPoints MakeFileDetails
parmake
       then [Char]
"(Parser created for all categories)"
       else [Char]
"   (Parser created only for category " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
forall a. Show a => a -> [Char]
show (CF -> Cat
firstEntry CF
cf) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
    IO () -> MkFiles ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> MkFiles ()) -> IO () -> MkFiles ()
forall a b. (a -> b) -> a -> b
$ [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"   (Tested with"  [Char] -> [Char] -> [Char]
+++ MakeFileDetails -> [Char]
toolname MakeFileDetails
parmake
                                           [Char] -> [Char] -> [Char]
+++ MakeFileDetails -> [Char]
toolversion MakeFileDetails
parmake [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
    SharedOptions -> ([Char] -> Doc) -> MkFiles ()
Makefile.mkMakefile SharedOptions
options (([Char] -> Doc) -> MkFiles ()) -> ([Char] -> Doc) -> MkFiles ()
forall a b. (a -> b) -> a -> b
$
        [Char]
-> [Char] -> [[Char]] -> ParserLexerSpecification -> [Char] -> Doc
makefile [Char]
dirBase [Char]
dirAbsyn [[Char]]
absynFileNames ParserLexerSpecification
parselexspec
  where
    remDups :: [(a, b)] -> [(a, b)]
remDups [] = []
    remDups ((a
a,b
b):[(a, b)]
as) = case a -> [(a, b)] -> Maybe b
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup a
a [(a, b)]
as of
                           Just {} -> [(a, b)] -> [(a, b)]
remDups [(a, b)]
as
                           Maybe b
Nothing -> (a
a, b
b) (a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
: [(a, b)] -> [(a, b)]
remDups [(a, b)]
as
    pkgToDir :: String -> FilePath
    pkgToDir :: [Char] -> [Char]
pkgToDir [Char]
s = Char -> Char -> [Char] -> [Char]
forall a. Eq a => a -> a -> [a] -> [a]
replace Char
'.' Char
pathSeparator [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char
pathSeparator]

    parselexspec :: ParserLexerSpecification
parselexspec = [Char]
-> JavaLexerParser -> RecordPositions -> ParserLexerSpecification
parserLexerSelector [Char]
lang JavaLexerParser
javaLexerParser RecordPositions
rp
    lexfun :: CF2LexerFunction
lexfun       = CFToLexer -> CF2LexerFunction
cf2lex (CFToLexer -> CF2LexerFunction) -> CFToLexer -> CF2LexerFunction
forall a b. (a -> b) -> a -> b
$ ParserLexerSpecification -> CFToLexer
lexer ParserLexerSpecification
parselexspec
    parsefun :: CF2ParserFunction
parsefun     = CFToParser -> CF2ParserFunction
cf2parse (CFToParser -> CF2ParserFunction)
-> CFToParser -> CF2ParserFunction
forall a b. (a -> b) -> a -> b
$ ParserLexerSpecification -> CFToParser
parser ParserLexerSpecification
parselexspec
    parmake :: MakeFileDetails
parmake      = CFToParser -> MakeFileDetails
makeparserdetails (ParserLexerSpecification -> CFToParser
parser ParserLexerSpecification
parselexspec)
    lexmake :: MakeFileDetails
lexmake      = CFToLexer -> MakeFileDetails
makelexerdetails  (ParserLexerSpecification -> CFToLexer
lexer ParserLexerSpecification
parselexspec)
    rp :: RecordPositions
rp           = (SharedOptions -> RecordPositions
Options.linenumbers SharedOptions
options)

makefile ::  FilePath -> FilePath -> [String] -> ParserLexerSpecification -> String -> Doc
makefile :: [Char]
-> [Char] -> [[Char]] -> ParserLexerSpecification -> [Char] -> Doc
makefile  [Char]
dirBase [Char]
dirAbsyn [[Char]]
absynFileNames ParserLexerSpecification
jlexpar [Char]
basename = [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$
    [([Char], [Char])] -> [Doc]
makeVars [  ([Char]
"JAVAC", [Char]
"javac"),
                ([Char]
"JAVAC_FLAGS", [Char]
"-sourcepath ."),
                ( [Char]
"JAVA", [Char]
"java"),
                ( [Char]
"JAVA_FLAGS", [Char]
""),
            -- parser executable
                ( [Char]
"PARSER", MakeFileDetails -> [Char]
executable MakeFileDetails
parmake),
            -- parser flags
                ( [Char]
"PARSER_FLAGS", MakeFileDetails -> [Char] -> [Char]
flags MakeFileDetails
parmake [Char]
dirBase),
             -- lexer executable (and flags?)
                ( [Char]
"LEXER", MakeFileDetails -> [Char]
executable MakeFileDetails
lexmake),
                ( [Char]
"LEXER_FLAGS", MakeFileDetails -> [Char] -> [Char]
flags MakeFileDetails
lexmake [Char]
dirBase)
    ]
    [Doc] -> [Doc] -> [Doc]
forall a. [a] -> [a] -> [a]
++
    [([Char], [[Char]], [[Char]])] -> [Doc]
makeRules [ ([Char]
"all", [ [Char]
"test" ], []),
                ( [Char]
"test", [Char]
"absyn" [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [[Char]]
classes, []),
                ( [Char]
".PHONY", [[Char]
"absyn"],     []),
                ([Char]
"%.class", [ [Char]
"%.java" ],  [ [Char] -> [Char]
runJavac [Char]
"$^" ]),
                ([Char]
"absyn",   [[Char]
absynJavaSrc],[ [Char] -> [Char]
runJavac [Char]
"$^" ])
                ][Doc] -> [Doc] -> [Doc]
forall a. [a] -> [a] -> [a]
++
    [-- running the lexergen: output of lexer -> input of lexer : calls lexer
    let ff :: [Char]
ff = MakeFileDetails -> [Char]
filename MakeFileDetails
lexmake -- name of input file without extension
        dirBaseff :: [Char]
dirBaseff = [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
ff -- prepend directory
        inp :: [Char]
inp = [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [Char]
inputfile MakeFileDetails
lexmake in
        [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule ([Char]
dirBaseff [Char] -> [Char] -> [Char]
+.+ [Char]
"java") [ [Char]
inp ]
        [ [Char]
"${LEXER} ${LEXER_FLAGS} "[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
inp ]

    -- running the parsergen, these there are its outputs
    -- output of parser -> input of parser : calls parser
  , let inp :: [Char]
inp = [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [Char]
inputfile MakeFileDetails
parmake in
        [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule ([[Char]] -> [Char]
unwords (([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
dirBase[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++) ([[Char]] -> [[Char]]
dotJava ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake)))
          [ [Char]
inp ] ([[Char]] -> Doc) -> [[Char]] -> Doc
forall a b. (a -> b) -> a -> b
$
          ([Char]
"${PARSER} ${PARSER_FLAGS} " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
inp) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:
          [[Char]
"mv " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords ([[Char]] -> [[Char]]
dotJava ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake) [Char] -> [Char] -> [Char]
+++ [Char]
dirBase
              | MakeFileDetails -> Bool
moveresults MakeFileDetails
parmake]
  -- Class of the output of lexer generator wants java of :
  -- output of lexer and parser generator
  , let lexerOutClass :: [Char]
lexerOutClass = [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [Char]
filename MakeFileDetails
lexmake [Char] -> [Char] -> [Char]
+.+ [Char]
"class"
        outname :: [Char] -> [Char]
outname [Char]
x = [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x [Char] -> [Char] -> [Char]
+.+ [Char]
"java"
        deps :: [[Char]]
deps = ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [Char]
outname (MakeFileDetails -> [[Char]]
results MakeFileDetails
lexmake [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake) in
        [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
lexerOutClass [[Char]]
deps []
    ][Doc] -> [Doc] -> [Doc]
forall a. [a] -> [a] -> [a]
++
  [Doc] -> [Doc]
forall a. [a] -> [a]
reverse [[Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
tar [[Char]]
dep [] |
    ([Char]
tar,[[Char]]
dep) <- [Char] -> [[Char]] -> [([Char], [[Char]])]
partialParserGoals [Char]
dirBase (MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake)]
  [Doc] -> [Doc] -> [Doc]
forall a. [a] -> [a] -> [a]
++[ [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule ([Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"PrettyPrinter.class")
        [ [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"PrettyPrinter.java" ] []
    -- Removes all the class files created anywhere
    , [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
"clean" [] [ [Char]
"rm -f " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
dirAbsyn [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"*.class" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" "
                                            [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"*.class" ]
    -- Remains the same
    , [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
"distclean" [ [Char]
"vclean" ] []
    -- removes everything
    , [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
"vclean" []
        [ [Char]
" rm -f " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
absynJavaSrc [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
absynJavaClass
        , [Char]
" rm -f " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
dirAbsyn [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"*.class"
        , [Char]
" rmdir " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
dirAbsyn
        , [Char]
" rm -f " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords (([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
dirBase [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++) ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$
                    [ MakeFileDetails -> [Char]
inputfile MakeFileDetails
lexmake
                    , MakeFileDetails -> [Char]
inputfile MakeFileDetails
parmake
                    ]
                    [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [[Char]]
dotJava (MakeFileDetails -> [[Char]]
results MakeFileDetails
lexmake)
                    [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [ [Char]
"VisitSkel.java"
                      , [Char]
"ComposVisitor.java"
                      , [Char]
"AbstractVisitor.java"
                      , [Char]
"FoldVisitor.java"
                      , [Char]
"AllVisitor.java"
                      , [Char]
"PrettyPrinter.java"
                      , [Char]
"Skeleton.java"
                      , [Char]
"Test.java"
                      ]
                    [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [[Char]]
dotJava (MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake)
                    [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]
"*.class"]
                    [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [[Char]]
other_results MakeFileDetails
lexmake
                    [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ MakeFileDetails -> [[Char]]
other_results MakeFileDetails
parmake)
        , [Char]
" rm -f " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
basename
        , [Char]
" rmdir -p " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
dirBase
        ]
    ]
    where
      makeVars :: [([Char], [Char])] -> [Doc]
makeVars [([Char], [Char])]
x = [[Char] -> [Char] -> Doc
Makefile.mkVar [Char]
n [Char]
v | ([Char]
n,[Char]
v) <- [([Char], [Char])]
x]
      makeRules :: [([Char], [[Char]], [[Char]])] -> [Doc]
makeRules [([Char], [[Char]], [[Char]])]
x = [[Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
tar [[Char]]
dep [[Char]]
recipe  | ([Char]
tar, [[Char]]
dep, [[Char]]
recipe) <- [([Char], [[Char]], [[Char]])]
x]
      parmake :: MakeFileDetails
parmake           = CFToParser -> MakeFileDetails
makeparserdetails (ParserLexerSpecification -> CFToParser
parser ParserLexerSpecification
jlexpar)
      lexmake :: MakeFileDetails
lexmake           = CFToLexer -> MakeFileDetails
makelexerdetails (ParserLexerSpecification -> CFToLexer
lexer ParserLexerSpecification
jlexpar)
      absynJavaSrc :: [Char]
absynJavaSrc      = [[Char]] -> [Char]
unwords ([[Char]] -> [[Char]]
dotJava [[Char]]
absynFileNames)
      absynJavaClass :: [Char]
absynJavaClass    = [[Char]] -> [Char]
unwords ([[Char]] -> [[Char]]
dotClass [[Char]]
absynFileNames)
      classes :: [[Char]]
classes = [Char] -> [[Char]] -> [[Char]]
prependPath [Char]
dirBase [[Char]]
lst
      lst :: [[Char]]
lst = [[Char]] -> [[Char]]
dotClass (MakeFileDetails -> [[Char]]
results MakeFileDetails
lexmake) [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [ [Char]
"PrettyPrinter.class", [Char]
"Test.class"
          , [Char]
"VisitSkel.class"
          , [Char]
"ComposVisitor.class", [Char]
"AbstractVisitor.class"
          , [Char]
"FoldVisitor.class", [Char]
"AllVisitor.class"][[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
           [[Char]] -> [[Char]]
dotClass (MakeFileDetails -> [[Char]]
results MakeFileDetails
parmake) [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]
"Test.class"]

type TestClass = String
    -- ^ class of the lexer
    -> String
    -- ^ class of the parser
    -> String
    -- ^ package where the non-abstract syntax classes are created
    -> String
    -- ^ package where the abstract syntax classes are created
    -> CF
    -- ^ the CF bundle
    -> String

-- | Record to name arguments of 'javaTest'.
data JavaTestParams = JavaTestParams
  { JavaTestParams -> [Doc]
jtpImports            :: [Doc]
      -- ^ List of imported packages.
  , JavaTestParams -> [Char]
jtpErr                :: String
      -- ^ Name of the exception thrown in case of parsing failure.
  , JavaTestParams -> [Char] -> [Doc]
jtpErrHand            :: (String -> [Doc])
      -- ^ Handler for the exception thrown.
  , JavaTestParams -> Doc -> Doc -> Doc
jtpLexerConstruction  :: (Doc -> Doc -> Doc)
      -- ^ Function formulating the construction of the lexer object.
  , JavaTestParams -> Doc -> Doc -> Doc
jtpParserConstruction :: (Doc -> Doc -> Doc)
      -- ^ As above, for parser object.
  , JavaTestParams -> [Cat] -> [Doc]
jtpShowAlternatives   :: ([Cat] -> [Doc])
      -- ^ Pretty-print the names of the methods corresponding to entry points to the user.
  , JavaTestParams -> Doc -> Doc -> Doc -> Doc -> Doc
jtpInvocation         :: (Doc -> Doc -> Doc -> Doc -> Doc)
      -- ^ Function formulating the invocation of the parser tool within Java.
  , JavaTestParams -> [Char]
jtpErrMsg             :: String
      -- ^ Error string output in consequence of a parsing failure.
  }

-- | Test class details for J(F)Lex + CUP
cuptest :: TestClass
cuptest :: TestClass
cuptest = JavaTestParams -> TestClass
javaTest (JavaTestParams -> TestClass) -> JavaTestParams -> TestClass
forall a b. (a -> b) -> a -> b
$ JavaTestParams :: [Doc]
-> [Char]
-> ([Char] -> [Doc])
-> (Doc -> Doc -> Doc)
-> (Doc -> Doc -> Doc)
-> ([Cat] -> [Doc])
-> (Doc -> Doc -> Doc -> Doc -> Doc)
-> [Char]
-> JavaTestParams
JavaTestParams
  { jtpImports :: [Doc]
jtpImports            = [Doc
"java_cup.runtime"]
  , jtpErr :: [Char]
jtpErr                = [Char]
"Throwable"
  , jtpErrHand :: [Char] -> [Doc]
jtpErrHand            = [Doc] -> [Char] -> [Doc]
forall a b. a -> b -> a
const []
  , jtpLexerConstruction :: Doc -> Doc -> Doc
jtpLexerConstruction  = \ Doc
x Doc
i -> Doc
x Doc -> Doc -> Doc
<> Doc
i Doc -> Doc -> Doc
<> Doc
";"
  , jtpParserConstruction :: Doc -> Doc -> Doc
jtpParserConstruction = \ Doc
x Doc
i -> Doc
x Doc -> Doc -> Doc
<> Doc
"(" Doc -> Doc -> Doc
<> Doc
i Doc -> Doc -> Doc
<> Doc
", " Doc -> Doc -> Doc
<> Doc
i Doc -> Doc -> Doc
<> Doc
".getSymbolFactory());"
  , jtpShowAlternatives :: [Cat] -> [Doc]
jtpShowAlternatives   = [Doc] -> [Cat] -> [Doc]
forall a b. a -> b -> a
const ([Doc] -> [Cat] -> [Doc]) -> [Doc] -> [Cat] -> [Doc]
forall a b. (a -> b) -> a -> b
$ [Doc
"not available."]
  , jtpInvocation :: Doc -> Doc -> Doc -> Doc -> Doc
jtpInvocation         = \ Doc
_ Doc
pabs Doc
dat Doc
enti -> [Doc] -> Doc
hcat [ Doc
pabs, Doc
".", Doc
dat, Doc
" ast = p.p", Doc
enti, Doc
"();" ]
  , jtpErrMsg :: [Char]
jtpErrMsg             = [[Char]] -> [Char]
unwords ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
      [ [Char]
"At line \" + String.valueOf(t.l.line_num()) + \","
      , [Char]
"near \\\"\" + t.l.buff() + \"\\\" :"
      ]
  }

-- | Test class details for ANTLR4
antlrtest :: TestClass
antlrtest :: TestClass
antlrtest = JavaTestParams -> TestClass
javaTest (JavaTestParams -> TestClass) -> JavaTestParams -> TestClass
forall a b. (a -> b) -> a -> b
$ JavaTestParams :: [Doc]
-> [Char]
-> ([Char] -> [Doc])
-> (Doc -> Doc -> Doc)
-> (Doc -> Doc -> Doc)
-> ([Cat] -> [Doc])
-> (Doc -> Doc -> Doc -> Doc -> Doc)
-> [Char]
-> JavaTestParams
JavaTestParams
  { jtpImports :: [Doc]
jtpImports =
      [ Doc
"org.antlr.v4.runtime"
      , Doc
"org.antlr.v4.runtime.atn"
      , Doc
"org.antlr.v4.runtime.dfa"
      , Doc
"java.util"
      ]
  , jtpErr :: [Char]
jtpErr =
      [Char]
"TestError"
  , jtpErrHand :: [Char] -> [Doc]
jtpErrHand =
      [Char] -> [Doc]
antlrErrorHandling
  , jtpLexerConstruction :: Doc -> Doc -> Doc
jtpLexerConstruction  =
      \ Doc
x Doc
i -> [Doc] -> Doc
vcat
        [ Doc
x Doc -> Doc -> Doc
<> Doc
"(new ANTLRInputStream" Doc -> Doc -> Doc
<> Doc
i Doc -> Doc -> Doc
<>Doc
");"
        , Doc
"l.addErrorListener(new BNFCErrorListener());"
        ]
  , jtpParserConstruction :: Doc -> Doc -> Doc
jtpParserConstruction =
      \ Doc
x Doc
i -> [Doc] -> Doc
vcat
        [ Doc
x Doc -> Doc -> Doc
<> Doc
"(new CommonTokenStream(" Doc -> Doc -> Doc
<> Doc
i Doc -> Doc -> Doc
<>Doc
"));"
        , Doc
"p.addErrorListener(new BNFCErrorListener());"
        ]
  , jtpShowAlternatives :: [Cat] -> [Doc]
jtpShowAlternatives   =
      [Cat] -> [Doc]
showOpts
  , jtpInvocation :: Doc -> Doc -> Doc -> Doc -> Doc
jtpInvocation         =
      \ Doc
pbase Doc
pabs Doc
dat Doc
enti -> [Doc] -> Doc
vcat
         [
           let rulename :: [Char]
rulename = [Char] -> [Char]
getRuleName ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
startSymbol ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Doc -> [Char]
render Doc
enti
               typename :: Doc
typename = [Char] -> Doc
text [Char]
rulename
               methodname :: Doc
methodname = [Char] -> Doc
text ([Char] -> Doc) -> [Char] -> Doc
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
firstLowerCase [Char]
rulename
           in
               Doc
pbase Doc -> Doc -> Doc
<> Doc
"." Doc -> Doc -> Doc
<> Doc
typename Doc -> Doc -> Doc
<> Doc
"Context pc = p." Doc -> Doc -> Doc
<> Doc
methodname Doc -> Doc -> Doc
<> Doc
"();"
         , Doc
pabs Doc -> Doc -> Doc
<> Doc
"." Doc -> Doc -> Doc
<> Doc
dat Doc -> Doc -> Doc
<+> Doc
"ast = pc.result;"
         ]
  , jtpErrMsg :: [Char]
jtpErrMsg             =
      [Char]
"At line \" + e.line + \", column \" + e.column + \" :"
  }
  where
    showOpts :: [Cat] -> [Doc]
showOpts [] = []
    showOpts (Cat
x:[Cat]
xs)
      | Cat -> Cat
normCat Cat
x Cat -> Cat -> Bool
forall a. Eq a => a -> a -> Bool
/= Cat
x = [Cat] -> [Doc]
showOpts [Cat]
xs
      | Bool
otherwise      = [Char] -> Doc
text ([Char] -> [Char]
firstLowerCase ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Cat -> [Char]
identCat Cat
x) Doc -> [Doc] -> [Doc]
forall a. a -> [a] -> [a]
: [Cat] -> [Doc]
showOpts [Cat]
xs

parserLexerSelector :: String
    -> JavaLexerParser
    -> RecordPositions -- ^Pass line numbers to the symbols
    -> ParserLexerSpecification
parserLexerSelector :: [Char]
-> JavaLexerParser -> RecordPositions -> ParserLexerSpecification
parserLexerSelector [Char]
_ JavaLexerParser
JLexCup RecordPositions
rp = ParseLexSpec :: CFToParser -> CFToLexer -> TestClass -> ParserLexerSpecification
ParseLexSpec
    { lexer :: CFToLexer
lexer     = RecordPositions -> CFToLexer
cf2JLex RecordPositions
rp
    , parser :: CFToParser
parser    = RecordPositions -> CFToParser
cf2cup RecordPositions
rp
    , testclass :: TestClass
testclass = TestClass
cuptest
    }
parserLexerSelector [Char]
_ JavaLexerParser
JFlexCup RecordPositions
rp =
    ([Char]
-> JavaLexerParser -> RecordPositions -> ParserLexerSpecification
parserLexerSelector [Char]
"" JavaLexerParser
JLexCup RecordPositions
rp){lexer :: CFToLexer
lexer = RecordPositions -> CFToLexer
cf2JFlex RecordPositions
rp}
parserLexerSelector [Char]
l JavaLexerParser
Antlr4 RecordPositions
_ = ParseLexSpec :: CFToParser -> CFToLexer -> TestClass -> ParserLexerSpecification
ParseLexSpec
    { lexer :: CFToLexer
lexer     = [Char] -> CFToLexer
cf2AntlrLex' [Char]
l
    , parser :: CFToParser
parser    = [Char] -> CFToParser
cf2AntlrParse' [Char]
l
    , testclass :: TestClass
testclass = TestClass
antlrtest
    }

data ParserLexerSpecification = ParseLexSpec
    { ParserLexerSpecification -> CFToParser
parser    :: CFToParser
    , ParserLexerSpecification -> CFToLexer
lexer     :: CFToLexer
    , ParserLexerSpecification -> TestClass
testclass :: TestClass
    }

-- |CF -> LEXER GENERATION TOOL BRIDGE
-- | function translating the CF to an appropriate lexer generation tool.
type CF2LexerFunction = String -> CF -> (Doc, SymEnv)

-- Chooses the translation from CF to the lexer
data CFToLexer = CF2Lex
    { CFToLexer -> CF2LexerFunction
cf2lex           :: CF2LexerFunction
    , CFToLexer -> MakeFileDetails
makelexerdetails :: MakeFileDetails
    }

-- | Instances of cf-lexergen bridges
cf2JLex, cf2JFlex :: RecordPositions -> CFToLexer

cf2JLex :: RecordPositions -> CFToLexer
cf2JLex RecordPositions
rp = CF2Lex :: CF2LexerFunction -> MakeFileDetails -> CFToLexer
CF2Lex
       { cf2lex :: CF2LexerFunction
cf2lex           = JavaLexerParser -> RecordPositions -> CF2LexerFunction
BNFC.Backend.Java.CFtoJLex15.cf2jlex JavaLexerParser
JLexCup RecordPositions
rp
       , makelexerdetails :: MakeFileDetails
makelexerdetails = MakeFileDetails
jlexmakedetails
       }

cf2JFlex :: RecordPositions -> CFToLexer
cf2JFlex RecordPositions
rp = CF2Lex :: CF2LexerFunction -> MakeFileDetails -> CFToLexer
CF2Lex
       { cf2lex :: CF2LexerFunction
cf2lex           = JavaLexerParser -> RecordPositions -> CF2LexerFunction
BNFC.Backend.Java.CFtoJLex15.cf2jlex JavaLexerParser
JFlexCup RecordPositions
rp
       , makelexerdetails :: MakeFileDetails
makelexerdetails = MakeFileDetails
jflexmakedetails
       }

cf2AntlrLex' :: String -> CFToLexer
cf2AntlrLex' :: [Char] -> CFToLexer
cf2AntlrLex' [Char]
l = CF2Lex :: CF2LexerFunction -> MakeFileDetails -> CFToLexer
CF2Lex
               { cf2lex :: CF2LexerFunction
cf2lex           =
                   CF2LexerFunction
BNFC.Backend.Java.CFtoAntlr4Lexer.cf2AntlrLex
               , makelexerdetails :: MakeFileDetails
makelexerdetails = [Char] -> MakeFileDetails
antlrmakedetails ([Char] -> MakeFileDetails) -> [Char] -> MakeFileDetails
forall a b. (a -> b) -> a -> b
$ [Char]
l[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++[Char]
"Lexer"
               }

-- | CF -> PARSER GENERATION TOOL BRIDGE
-- | function translating the CF to an appropriate parser generation tool.
type CF2ParserFunction = String -> String -> CF -> RecordPositions -> SymEnv -> String

-- | Chooses the translation from CF to the parser
data CFToParser = CF2Parse
    { CFToParser -> CF2ParserFunction
cf2parse          :: CF2ParserFunction
    , CFToParser -> MakeFileDetails
makeparserdetails :: MakeFileDetails
    }

-- | Instances of cf-parsergen bridges
cf2cup :: RecordPositions -> CFToParser
cf2cup :: RecordPositions -> CFToParser
cf2cup RecordPositions
rp = CF2Parse :: CF2ParserFunction -> MakeFileDetails -> CFToParser
CF2Parse
    { cf2parse :: CF2ParserFunction
cf2parse          = CF2ParserFunction
BNFC.Backend.Java.CFtoCup15.cf2Cup
    , makeparserdetails :: MakeFileDetails
makeparserdetails = RecordPositions -> MakeFileDetails
cupmakedetails RecordPositions
rp
    }

cf2AntlrParse' :: String -> CFToParser
cf2AntlrParse' :: [Char] -> CFToParser
cf2AntlrParse' [Char]
l = CF2Parse :: CF2ParserFunction -> MakeFileDetails -> CFToParser
CF2Parse
                { cf2parse :: CF2ParserFunction
cf2parse          =
                    CF2ParserFunction
BNFC.Backend.Java.CFtoAntlr4Parser.cf2AntlrParse
                , makeparserdetails :: MakeFileDetails
makeparserdetails = [Char] -> MakeFileDetails
antlrmakedetails ([Char] -> MakeFileDetails) -> [Char] -> MakeFileDetails
forall a b. (a -> b) -> a -> b
$ [Char]
l[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++[Char]
"Parser"
                }


-- | shorthand for Makefile command running javac or java
runJavac , runJava:: String -> String
runJava :: [Char] -> [Char]
runJava   = [Char] -> [Char] -> [Char]
mkRunProgram [Char]
"JAVA"
runJavac :: [Char] -> [Char]
runJavac  = [Char] -> [Char] -> [Char]
mkRunProgram [Char]
"JAVAC"

-- | function returning a string executing a program contained in a variable j
-- on input s
mkRunProgram :: String -> String -> String
mkRunProgram :: [Char] -> [Char] -> [Char]
mkRunProgram [Char]
j [Char]
s = [Char] -> [Char]
Makefile.refVar [Char]
j [Char] -> [Char] -> [Char]
+++ [Char] -> [Char]
Makefile.refVar ([Char]
j [Char] -> [Char] -> [Char]
+-+ [Char]
"FLAGS") [Char] -> [Char] -> [Char]
+++ [Char]
s

type OutputDirectory = String

-- | Makefile details from running the parser-lexer generation tools.
data MakeFileDetails = MakeDetails
    { -- | The string that executes the generation tool
      MakeFileDetails -> [Char]
executable          :: String
      -- | Flags to pass to the tool
    , MakeFileDetails -> [Char] -> [Char]
flags               :: OutputDirectory -> String
      -- | Input file to the tool
    , MakeFileDetails -> [Char]
filename            :: String
      -- | Extension of input file to the tool
    , MakeFileDetails -> [Char]
fileextension       :: String
      -- | name of the tool
    , MakeFileDetails -> [Char]
toolname            :: String
      -- | Tool version
    , MakeFileDetails -> [Char]
toolversion         :: String
      -- | true if the tool is a parser and supports entry points,
      -- false otherwise
    , MakeFileDetails -> Bool
supportsEntryPoints :: Bool
      -- | list of names (without extension!) of files resulting from the
      -- application of the tool which are relevant to a make rule
    , MakeFileDetails -> [[Char]]
results             :: [String]
      -- | list of names of files resulting from the application of
      -- the tool which are irrelevant to the make rules but need to
      -- be cleaned
    , MakeFileDetails -> [[Char]]
other_results       :: [String]
      -- | if true, the files are moved to the base directory, otherwise
      -- they are left where they are
    , MakeFileDetails -> Bool
moveresults         :: Bool
    }


mapEmpty :: a -> String
mapEmpty :: forall a. a -> [Char]
mapEmpty a
_ = [Char]
""

-- Instances of makefile details.
jflexmakedetails, jlexmakedetails :: MakeFileDetails
cupmakedetails :: RecordPositions -> MakeFileDetails

jlexmakedetails :: MakeFileDetails
jlexmakedetails = MakeDetails :: [Char]
-> ([Char] -> [Char])
-> [Char]
-> [Char]
-> [Char]
-> [Char]
-> Bool
-> [[Char]]
-> [[Char]]
-> Bool
-> MakeFileDetails
MakeDetails
    { executable :: [Char]
executable          = [Char] -> [Char]
runJava [Char]
"JLex.Main"
    , flags :: [Char] -> [Char]
flags               = [Char] -> [Char]
forall a. a -> [Char]
mapEmpty
    , filename :: [Char]
filename            = [Char]
"Yylex"
    , fileextension :: [Char]
fileextension       = [Char]
""
    , toolname :: [Char]
toolname            = [Char]
"JLex"
    , toolversion :: [Char]
toolversion         = [Char]
"1.2.6"
    , supportsEntryPoints :: Bool
supportsEntryPoints = Bool
False
    , results :: [[Char]]
results             = [[Char]
"Yylex"]
    , other_results :: [[Char]]
other_results       = []
    , moveresults :: Bool
moveresults         = Bool
False
    }

jflexmakedetails :: MakeFileDetails
jflexmakedetails = MakeFileDetails
jlexmakedetails
    { executable :: [Char]
executable  = [Char]
"jflex"
    , toolname :: [Char]
toolname    = [Char]
"JFlex"
    , toolversion :: [Char]
toolversion = [Char]
"1.4.3 - 1.7.0"
    }

cupmakedetails :: RecordPositions -> MakeFileDetails
cupmakedetails RecordPositions
rp = MakeDetails :: [Char]
-> ([Char] -> [Char])
-> [Char]
-> [Char]
-> [Char]
-> [Char]
-> Bool
-> [[Char]]
-> [[Char]]
-> Bool
-> MakeFileDetails
MakeDetails
    { executable :: [Char]
executable          = [Char] -> [Char]
runJava [Char]
"java_cup.Main"
    , flags :: [Char] -> [Char]
flags               = [Char] -> [Char] -> [Char]
forall a b. a -> b -> a
const ([Char]
lnFlags [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" -expect 100")
    , filename :: [Char]
filename            = [Char]
"_cup"
    , fileextension :: [Char]
fileextension       = [Char]
"cup"
    , toolname :: [Char]
toolname            = [Char]
"CUP"
    , toolversion :: [Char]
toolversion         = [Char]
"0.11b"
    , supportsEntryPoints :: Bool
supportsEntryPoints = Bool
False
    , results :: [[Char]]
results             = [[Char]
"parser", [Char]
"sym"]
    , other_results :: [[Char]]
other_results       = []
    , moveresults :: Bool
moveresults         = Bool
True
    }
  where
    lnFlags :: [Char]
lnFlags = if RecordPositions
rp RecordPositions -> RecordPositions -> Bool
forall a. Eq a => a -> a -> Bool
== RecordPositions
RecordPositions then [Char]
"-locations" else [Char]
"-nopositions"


antlrmakedetails :: String -> MakeFileDetails
antlrmakedetails :: [Char] -> MakeFileDetails
antlrmakedetails [Char]
l = MakeDetails :: [Char]
-> ([Char] -> [Char])
-> [Char]
-> [Char]
-> [Char]
-> [Char]
-> Bool
-> [[Char]]
-> [[Char]]
-> Bool
-> MakeFileDetails
MakeDetails
    { executable :: [Char]
executable = [Char] -> [Char]
runJava [Char]
"org.antlr.v4.Tool"
    , flags :: [Char] -> [Char]
flags               = \[Char]
x -> [[Char]] -> [Char]
unwords ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
                                    let path :: [Char]
path    = Int -> [Char] -> [Char]
forall a. Int -> [a] -> [a]
take ([Char] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Char]
x
                                        pointed :: [Char]
pointed = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
cnv [Char]
path
                                        cnv :: Char -> Char
cnv Char
y   = if Char -> Bool
isPathSeparator Char
y
                                                        then Char
'.'
                                                        else Char
y
                                        in [ [Char]
"-lib", [Char]
path
                                           , [Char]
"-package", [Char]
pointed]
    , filename :: [Char]
filename            = [Char]
l
    , fileextension :: [Char]
fileextension       = [Char]
"g4"
    , toolname :: [Char]
toolname            = [Char]
"ANTLRv4"
    , toolversion :: [Char]
toolversion         = [Char]
"4.9"
    , supportsEntryPoints :: Bool
supportsEntryPoints = Bool
True
    , results :: [[Char]]
results             = [[Char]
l]
    , other_results :: [[Char]]
other_results       = ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
l [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++)
        [ [Char]
".interp"              -- added after ANTLR 4.5
        , [Char]
".tokens"
        , [Char]
"BaseListener.java"
        ,[Char]
"Listener.java"
        ]
    , moveresults :: Bool
moveresults         = Bool
False
    }

prependPath , appendExtension :: String -> [String] -> [String]
prependPath :: [Char] -> [[Char]] -> [[Char]]
prependPath [Char]
s [[Char]]
fi     = [ [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x  | [Char]
x <- [[Char]]
fi ]
appendExtension :: [Char] -> [[Char]] -> [[Char]]
appendExtension [Char]
s [[Char]]
fi = [ [Char]
x [Char] -> [Char] -> [Char]
+.+ [Char]
s | [Char]
x <- [[Char]]
fi ]

dotJava,dotClass :: [String] -> [String]
dotJava :: [[Char]] -> [[Char]]
dotJava  = [Char] -> [[Char]] -> [[Char]]
appendExtension [Char]
"java"
dotClass :: [[Char]] -> [[Char]]
dotClass = [Char] -> [[Char]] -> [[Char]]
appendExtension [Char]
"class"

type CFToJava = String -> String -> CF -> String

-- | Contains the pairs filename/content for all the non-abstract syntax files
-- generated by BNFC.
data BNFCGeneratedEntities = BNFCGenerated
    { BNFCGeneratedEntities -> ([Char], [Char])
bprettyprinter :: (String, String)
    , BNFCGeneratedEntities -> ([Char], [Char])
btest          :: (String, String)
    , BNFCGeneratedEntities -> ([Char], [Char])
bcompos        :: (String, String)
    , BNFCGeneratedEntities -> ([Char], [Char])
babstract      :: (String, String)
    , BNFCGeneratedEntities -> ([Char], [Char])
bfold          :: (String, String)
    , BNFCGeneratedEntities -> ([Char], [Char])
ball           :: (String, String)
    , BNFCGeneratedEntities -> ([Char], [Char])
bskel          :: (String, String)
    }

bnfcVisitorsAndTests :: String   -> String    -> CF      ->
                        CFToJava -> CFToJava -> CFToJava ->
                        CFToJava -> CFToJava -> CFToJava ->
                        CFToJava -> BNFCGeneratedEntities
bnfcVisitorsAndTests :: [Char]
-> [Char]
-> CF
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> CFToJava
-> BNFCGeneratedEntities
bnfcVisitorsAndTests [Char]
pbase [Char]
pabsyn CF
cf CFToJava
cf0 CFToJava
cf1 CFToJava
cf2 CFToJava
cf3 CFToJava
cf4 CFToJava
cf5 CFToJava
cf6 =
    BNFCGenerated :: ([Char], [Char])
-> ([Char], [Char])
-> ([Char], [Char])
-> ([Char], [Char])
-> ([Char], [Char])
-> ([Char], [Char])
-> ([Char], [Char])
-> BNFCGeneratedEntities
BNFCGenerated
    { bprettyprinter :: ([Char], [Char])
bprettyprinter = ( [Char]
"PrettyPrinter" , CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf0)
    , bskel :: ([Char], [Char])
bskel          = ( [Char]
"VisitSkel", CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf1)
    , bcompos :: ([Char], [Char])
bcompos        = ( [Char]
"ComposVisitor" , CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf2)
    , babstract :: ([Char], [Char])
babstract      = ( [Char]
"AbstractVisitor" , CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf3)
    , bfold :: ([Char], [Char])
bfold          = ( [Char]
"FoldVisitor", CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf4)
    , ball :: ([Char], [Char])
ball           = ( [Char]
"AllVisitor", CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf5)
    , btest :: ([Char], [Char])
btest          = ( [Char]
"Test" , CFToJava -> [Char]
forall {t}. ([Char] -> [Char] -> CF -> t) -> t
app CFToJava
cf6)
    }
  where app :: ([Char] -> [Char] -> CF -> t) -> t
app [Char] -> [Char] -> CF -> t
x = [Char] -> [Char] -> CF -> t
x [Char]
pbase [Char]
pabsyn CF
cf

inputfile :: MakeFileDetails -> [Char]
inputfile MakeFileDetails
x = MakeFileDetails -> [Char]
filename MakeFileDetails
x [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ case MakeFileDetails -> [Char]
fileextension MakeFileDetails
x of
                                [Char]
"" -> [Char]
""
                                [Char]
a -> Char
'.'Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
a

-- |  constructs the rules regarding the parser in the makefile
partialParserGoals :: String -> [String] -> [(String, [String])]
partialParserGoals :: [Char] -> [[Char]] -> [([Char], [[Char]])]
partialParserGoals [Char]
_ []          = []
partialParserGoals [Char]
dbas ([Char]
x:[[Char]]
rest) =
    ([Char]
dbas [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x [Char] -> [Char] -> [Char]
+.+ [Char]
"class", ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (\ [Char]
y -> [Char]
dbas [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
y [Char] -> [Char] -> [Char]
+.+ [Char]
"java") ([Char]
x[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:[[Char]]
rest))
        ([Char], [[Char]]) -> [([Char], [[Char]])] -> [([Char], [[Char]])]
forall a. a -> [a] -> [a]
: [Char] -> [[Char]] -> [([Char], [[Char]])]
partialParserGoals [Char]
dbas [[Char]]
rest

-- | Creates the Test.java class.
javaTest :: JavaTestParams -> TestClass
javaTest :: JavaTestParams -> TestClass
javaTest (JavaTestParams
    [Doc]
imports
    [Char]
err
    [Char] -> [Doc]
errhand
    Doc -> Doc -> Doc
lexerconstruction
    Doc -> Doc -> Doc
parserconstruction
    [Cat] -> [Doc]
showOpts
    Doc -> Doc -> Doc -> Doc -> Doc
invocation
    [Char]
errmsg)
    [Char]
lexer
    [Char]
parser
    [Char]
packageBase
    [Char]
packageAbsyn
    CF
cf =
    Doc -> [Char]
render (Doc -> [Char]) -> Doc -> [Char]
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ [[Doc]] -> [Doc]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Doc]] -> [Doc]) -> [[Doc]] -> [Doc]
forall a b. (a -> b) -> a -> b
$
      [ [ Doc
"package" Doc -> Doc -> Doc
<+> [Char] -> Doc
text [Char]
packageBase Doc -> Doc -> Doc
<> Doc
";"
        , Doc
""
        , Doc
"import" Doc -> Doc -> Doc
<+> [Char] -> Doc
text [Char]
packageBase Doc -> Doc -> Doc
<> Doc
".*;"
        , Doc
"import java.io.*;"
        ]
      , (Doc -> Doc) -> [Doc] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Doc -> Doc
importfun [Doc]
imports
      , [ Doc
"" ]
      , [Char] -> [Doc]
errhand [Char]
err
      , [ Doc
""
        , Doc
"public class Test"
        , Int -> [Doc] -> Doc
codeblock Int
2
            [ Doc
lx Doc -> Doc -> Doc
<+> Doc
"l;"
            , Doc
px Doc -> Doc -> Doc
<+> Doc
"p;"
            , Doc
""
            , Doc
"public Test(String[] args)"
            , Int -> [Doc] -> Doc
codeblock Int
2
                [ Doc
"try"
                , Int -> [Doc] -> Doc
codeblock Int
2
                    [ Doc
"Reader input;"
                    , Doc
"if (args.length == 0) input = new InputStreamReader(System.in);"
                    , Doc
"else input = new FileReader(args[0]);"
                    , Doc
"l = new " Doc -> Doc -> Doc
<> Doc -> Doc -> Doc
lexerconstruction Doc
lx Doc
"(input)"
                    ]
                , Doc
"catch(IOException e)"
                , Int -> [Doc] -> Doc
codeblock Int
2
                    [ Doc
"System.err.println(\"Error: File not found: \" + args[0]);"
                    , Doc
"System.exit(1);"
                    ]
                , Doc
"p = new "Doc -> Doc -> Doc
<> Doc -> Doc -> Doc
parserconstruction Doc
px Doc
"l"
                ]
            , Doc
""
            , Doc
"public" Doc -> Doc -> Doc
<+> [Char] -> Doc
text [Char]
packageAbsyn Doc -> Doc -> Doc
<> Doc
"." Doc -> Doc -> Doc
<> Doc
dat
                Doc -> Doc -> Doc
<+> Doc
"parse() throws Exception"
            , Int -> [Doc] -> Doc
codeblock Int
2 ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ [[Doc]] -> [Doc]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
                [ [ Doc
"/* The default parser is the first-defined entry point. */" ]
                , [Cat] -> ([Cat] -> [Doc]) -> [Doc]
forall m a. Monoid m => [a] -> ([a] -> m) -> m
unlessNull (Int -> [Cat] -> [Cat]
forall a. Int -> [a] -> [a]
drop Int
1 [Cat]
eps) (([Cat] -> [Doc]) -> [Doc]) -> ([Cat] -> [Doc]) -> [Doc]
forall a b. (a -> b) -> a -> b
$ \ [Cat]
eps' ->
                  [ Doc
"/* Other options are: */"
                  , Doc
"/* " Doc -> Doc -> Doc
<> [Doc] -> Doc
fsep (Doc -> [Doc] -> [Doc]
punctuate Doc
"," ([Cat] -> [Doc]
showOpts [Cat]
eps')) Doc -> Doc -> Doc
<> Doc
" */"
                  ]
                , [ Doc -> Doc -> Doc -> Doc -> Doc
invocation Doc
px ([Char] -> Doc
text [Char]
packageAbsyn) Doc
dat Doc
absentity
                  , [[Char]] -> Doc
printOuts
                     [ [Char]
"\"Parse Succesful!\""
                     , [Char]
"\"[Abstract Syntax]\""
                     , [Char]
"PrettyPrinter.show(ast)"
                     , [Char]
"\"[Linearized Tree]\""
                     , [Char]
"PrettyPrinter.print(ast)"
                     ]
                  , Doc
"return ast;"
                  ]
                ]
            , Doc
""
            , Doc
"public static void main(String args[]) throws Exception"
            , Int -> [Doc] -> Doc
codeblock Int
2
                [ Doc
"Test t = new Test(args);"
                , Doc
"try"
                , Int -> [Doc] -> Doc
codeblock Int
2 [ Doc
"t.parse();" ]
                ,Doc
"catch(" Doc -> Doc -> Doc
<> [Char] -> Doc
text [Char]
err Doc -> Doc -> Doc
<+> Doc
"e)"
                , Int -> [Doc] -> Doc
codeblock Int
2
                    [ Doc
"System.err.println(\"" Doc -> Doc -> Doc
<> [Char] -> Doc
text [Char]
errmsg Doc -> Doc -> Doc
<> Doc
"\");"
                    , Doc
"System.err.println(\"     \" + e.getMessage());"
                    , Doc
"System.exit(1);"
                    ]
                ]
            ]
        ]
      ]
    where
      printOuts :: [[Char]] -> Doc
printOuts [[Char]]
x    = [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ ([Char] -> Doc) -> [[Char]] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> Doc
javaPrintOut ([[Char]] -> [[Char]]
forall {a}. IsString a => [a] -> [a]
messages [[Char]]
x)
      messages :: [a] -> [a]
messages [a]
x     = a
"" a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a -> [a] -> [a]
forall a. a -> [a] -> [a]
intersperse a
"" [a]
x
      javaPrintOut :: [Char] -> Doc
javaPrintOut [Char]
x = [Char] -> Doc
text ([Char] -> Doc) -> [Char] -> Doc
forall a b. (a -> b) -> a -> b
$ [Char]
"System.out.println(" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
");"
      importfun :: Doc -> Doc
importfun Doc
x    = Doc
"import" Doc -> Doc -> Doc
<+> Doc
x Doc -> Doc -> Doc
<> Doc
".*;"
      lx :: Doc
lx             = [Char] -> Doc
text [Char]
lexer
      px :: Doc
px             = [Char] -> Doc
text [Char]
parser
      dat :: Doc
dat            = [Char] -> Doc
text ([Char] -> Doc) -> [Char] -> Doc
forall a b. (a -> b) -> a -> b
$ Cat -> [Char]
identCat (Cat -> [Char]) -> Cat -> [Char]
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
def  -- Use for AST types.
      absentity :: Doc
absentity      = [Char] -> Doc
text ([Char] -> Doc) -> [Char] -> Doc
forall a b. (a -> b) -> a -> b
$ Cat -> [Char]
identCat Cat
def            -- Use for parser/printer name.
      eps :: [Cat]
eps            = NonEmpty Cat -> [Cat]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall a b. (a -> b) -> a -> b
$ CF -> NonEmpty Cat
forall f. CFG f -> NonEmpty Cat
allEntryPoints CF
cf
      def :: Cat
def            = [Cat] -> Cat
forall a. [a] -> a
head [Cat]
eps

-- | Error handling in ANTLR.
-- By default, ANTLR does not stop after any parsing error and attempts to go
-- on, delivering what it has been able to parse.
-- It does not throw any exception, unlike J(F)lex+CUP.
-- The below code makes the test class behave as with J(F)lex+CUP.
antlrErrorHandling :: String -> [Doc]
antlrErrorHandling :: [Char] -> [Doc]
antlrErrorHandling [Char]
te =
    [ Doc
"class"Doc -> Doc -> Doc
<+>Doc
tedocDoc -> Doc -> Doc
<+>Doc
"extends RuntimeException"
    , Int -> [Doc] -> Doc
codeblock Int
2 [ Doc
"int line;"
        , Doc
"int column;"
        , Doc
"public"Doc -> Doc -> Doc
<+>Doc
tedocDoc -> Doc -> Doc
<>Doc
"(String msg, int l, int c)"
        , Int -> [Doc] -> Doc
codeblock Int
2 [ Doc
"super(msg);"
            , Doc
"line = l;"
            , Doc
"column = c;"
            ]
        ]
    , Doc
"class BNFCErrorListener implements ANTLRErrorListener"
    , Int -> [Doc] -> Doc
codeblock Int
2 [ Doc
"@Override"
        , Doc
"public void syntaxError(Recognizer<?, ?> recognizer, Object o, int i"
            Doc -> Doc -> Doc
<> Doc
", int i1, String s, RecognitionException e)"
        , Int -> [Doc] -> Doc
codeblock Int
2 [ Doc
"throw new"Doc -> Doc -> Doc
<+>Doc
tedocDoc -> Doc -> Doc
<>Doc
"(s,i,i1);"]
        , Doc
"@Override"
        , Doc
"public void reportAmbiguity(Parser parser, DFA dfa, int i, int i1, "
            Doc -> Doc -> Doc
<>Doc
"boolean b, BitSet bitSet, ATNConfigSet atnConfigSet)"
        , Int -> [Doc] -> Doc
codeblock Int
2[ Doc
"throw new"Doc -> Doc -> Doc
<+>Doc
tedocDoc -> Doc -> Doc
<>Doc
"(\"Ambiguity at\",i,i1);" ]
        , Doc
"@Override"
        , Doc
"public void reportAttemptingFullContext(Parser parser, DFA dfa, "
            Doc -> Doc -> Doc
<>Doc
"int i, int i1, BitSet bitSet, ATNConfigSet atnConfigSet)"
        , Int -> [Doc] -> Doc
codeblock Int
2 []
        , Doc
"@Override"
        ,Doc
"public void reportContextSensitivity(Parser parser, DFA dfa, int i, "
            Doc -> Doc -> Doc
<>Doc
"int i1, int i2, ATNConfigSet atnConfigSet)"
        ,Int -> [Doc] -> Doc
codeblock Int
2 []
        ]
    ]
    where tedoc :: Doc
tedoc = [Char] -> Doc
text [Char]
te