{-# LANGUAGE LambdaCase #-}

{-
    BNF Converter: Latex Generator
    Copyright (C) 2004  Author:  Markus Forsberg, Aarne Ranta

-}

module BNFC.Backend.Latex where

import qualified Data.List as List
import System.FilePath ((<.>),replaceExtension)
import Text.Printf

import BNFC.Abs (Reg (..))
import BNFC.Options hiding (Backend)
import BNFC.Backend.Base
import BNFC.Backend.Common.Makefile as Makefile
import BNFC.CF
import BNFC.Utils
import BNFC.PrettyPrint hiding (empty)

-- | Entry point: create .tex file and a Makefile to compile it.
makeLatex :: SharedOptions -> CF -> Backend
makeLatex :: SharedOptions -> CF -> Backend
makeLatex SharedOptions
opts CF
cf = do
    let texfile :: [Char]
texfile = [Char]
name [Char] -> [Char] -> [Char]
<.> [Char]
"tex"
    [Char] -> ([Char] -> [Char]) -> [Char] -> Backend
forall c.
FileContent c =>
[Char] -> ([Char] -> [Char]) -> c -> Backend
mkfile [Char]
texfile [Char] -> [Char]
comment ([Char] -> CF -> [Char]
cfToLatex [Char]
name CF
cf)
    SharedOptions -> ([Char] -> Doc) -> Backend
Makefile.mkMakefile SharedOptions
opts ([Char] -> [Char] -> Doc
makefile [Char]
texfile)
  where name :: [Char]
name = SharedOptions -> [Char]
lang SharedOptions
opts

-- | Create a makefile for the given tex file
--
-- >>> makefile "myFile.tex" "Makefile"
-- all : myFile.pdf
-- <BLANKLINE>
-- myFile.pdf : myFile.tex
-- 	pdflatex myFile.tex
-- <BLANKLINE>
-- clean :
-- 	-rm myFile.pdf myFile.aux myFile.log
-- <BLANKLINE>
-- cleanall : clean
-- 	-rm Makefile myFile.tex
-- <BLANKLINE>
--
makefile :: String -> String -> Doc
makefile :: [Char] -> [Char] -> Doc
makefile [Char]
texfile [Char]
basename = [Doc] -> Doc
vcat
    [ [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
"all" [[Char]
pdffile]
        []
    , [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
pdffile [[Char]
texfile]
        [ [Char] -> [Char] -> [Char]
forall r. PrintfType r => [Char] -> r
printf [Char]
"pdflatex %s" [Char]
texfile ]
    , [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
"clean" []
        [ [[Char]] -> [Char]
unwords [ [Char]
"-rm", [Char]
pdffile, [Char]
auxfile, [Char]
logfile ]]
    , [Char] -> [[Char]] -> [[Char]] -> Doc
Makefile.mkRule [Char]
"cleanall" [[Char]
"clean"]
        [ [[Char]] -> [Char]
unwords [ [Char]
"-rm", [Char]
basename, [Char]
texfile ]]
    ]
  where pdffile :: [Char]
pdffile = [Char] -> [Char] -> [Char]
replaceExtension [Char]
texfile [Char]
"pdf"
        auxfile :: [Char]
auxfile = [Char] -> [Char] -> [Char]
replaceExtension [Char]
texfile [Char]
"aux"
        logfile :: [Char]
logfile = [Char] -> [Char] -> [Char]
replaceExtension [Char]
texfile [Char]
"log"

comment :: String -> String
comment :: [Char] -> [Char]
comment = ([Char]
"%% " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++)

-- | Create content of .tex file.
cfToLatex :: String -> CF -> String
cfToLatex :: [Char] -> CF -> [Char]
cfToLatex [Char]
name CF
cf = [[Char]] -> [Char]
unlines
  -- Overall structure of created LaTeX document:
  [ [Char]
"\\batchmode"
  , [Char] -> [Char]
beginDocument [Char]
name
  , [Char]
macros
  , [Char]
introduction
  , [Char] -> CF -> [Char]
prtTerminals [Char]
name CF
cf
  , [Char] -> CF -> [Char]
prtBNF [Char]
name CF
cf
  , [Char]
endDocument
  ]

introduction :: String
introduction :: [Char]
introduction = [[Char]] -> [Char]
unlines
  [ [Char]
"This document was automatically generated by the {\\em BNF-Converter}."
  , [Char]
"It was generated together with the lexer, the parser, and the"
  , [Char]
"abstract syntax module, which guarantees that the document"
  , [Char]
"matches with the implementation of the language"
  , [Char]
"(provided no hand-hacking has taken place)."
  ]

prtTerminals :: String -> CF -> String
prtTerminals :: [Char] -> CF -> [Char]
prtTerminals [Char]
name CF
cf = [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
  [ [Char]
"\\section*{The lexical structure of " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}"
  , [Char]
""
  ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ CF -> [[Char]]
identSection CF
cf [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
  [ [Char]
"\\subsection*{Literals}"
  , [Char] -> CF -> [Char]
prtLiterals [Char]
name CF
cf
  ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ (([Char], Reg) -> [Char]) -> [([Char], Reg)] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], Reg) -> [Char]
prtOwnToken (CF -> [([Char], Reg)]
forall f. CFG f -> [([Char], Reg)]
tokenPragmas CF
cf) [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
  [ [Char]
"\\subsection*{Reserved words and symbols}"
  , [Char] -> CF -> [Char]
prtReserved [Char]
name CF
cf
  , [Char] -> CF -> [Char]
prtSymb [Char]
name CF
cf
  , [Char]
"\\subsection*{Comments}"
  , ([([Char], [Char])], [[Char]]) -> [Char]
prtComments (([([Char], [Char])], [[Char]]) -> [Char])
-> ([([Char], [Char])], [[Char]]) -> [Char]
forall a b. (a -> b) -> a -> b
$ CF -> ([([Char], [Char])], [[Char]])
comments CF
cf
  ]

identSection :: CF -> [String]
identSection :: CF -> [[Char]]
identSection CF
cf
  | CF -> Bool
forall f. CFG f -> Bool
hasIdent CF
cf = [ [Char]
"\\subsection*{Identifiers}" ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
prtIdentifiers
  | Bool
otherwise   = []

prtIdentifiers :: [String]
prtIdentifiers :: [[Char]]
prtIdentifiers =
  [ [Char]
"Identifiers \\nonterminal{Ident} are unquoted strings beginning with a letter,"
  , [Char]
"followed by any combination of letters, digits, and the characters {\\tt \\_ '},"
  , [Char]
"reserved words excluded."
  ]

prtLiterals :: String -> CF -> String
prtLiterals :: [Char] -> CF -> [Char]
prtLiterals [Char]
_ CF
cf =
  [[Char]] -> [Char]
unlines ([[Char]] -> [Char])
-> ([[Char]] -> [[Char]]) -> [[Char]] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[[Char]]] -> [[Char]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[[Char]]] -> [[Char]])
-> ([[Char]] -> [[[Char]]]) -> [[Char]] -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> [[[Char]]] -> [[[Char]]]
forall a. a -> [a] -> [a]
List.intersperse [[Char]
""] ([[[Char]]] -> [[[Char]]])
-> ([[Char]] -> [[[Char]]]) -> [[Char]] -> [[[Char]]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> [[Char]]) -> [[Char]] -> [[[Char]]]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [[Char]]
stringLit ([[Char]] -> [[[Char]]])
-> ([[Char]] -> [[Char]]) -> [[Char]] -> [[[Char]]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> Bool) -> [[Char]] -> [[Char]]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
/= [Char]
catIdent) ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ CF -> [[Char]]
forall f. CFG f -> [[Char]]
literals CF
cf

stringLit :: TokenCat -> [String]
stringLit :: [Char] -> [[Char]]
stringLit = \case
  [Char]
"Char" ->
    [ [Char]
"Character literals \\nonterminal{Char}\\ have the form"
    , [Char]
"\\terminal{'}$c$\\terminal{'}, where $c$ is any single character."
    ]
  [Char]
"String" ->
    [ [Char]
"String literals \\nonterminal{String}\\ have the form"
    , [Char]
"\\terminal{\"}$x$\\terminal{\"}, where $x$ is any sequence of any characters"
    , [Char]
"except \\terminal{\"}\\ unless preceded by \\verb6\\6."
    ]
  [Char]
"Integer" ->
    [ [Char]
"Integer literals \\nonterminal{Int}\\ are nonempty sequences of digits."
    ]
  [Char]
"Double" ->
    [ [Char]
"Double-precision float literals \\nonterminal{Double}\\ have the structure"
    , [Char]
"indicated by the regular expression" [Char] -> [Char] -> [Char]
+++
      [Char]
"$\\nonterminal{digit}+ \\mbox{{\\it `.'}} \\nonterminal{digit}+ (\\mbox{{\\it `e'}} \\mbox{{\\it `-'}}? \\nonterminal{digit}+)?$ i.e.\\"
    , [Char]
"two sequences of digits separated by a decimal point, optionally"
    , [Char]
"followed by an unsigned or negative exponent."
    ]
  [Char]
_ -> []

prtOwnToken :: ([Char], Reg) -> [Char]
prtOwnToken ([Char]
name,Reg
reg) = [[Char]] -> [Char]
unlines
  [ [Char]
name [Char] -> [Char] -> [Char]
+++ [Char]
"literals are recognized by the regular expression",
   [Char]
"\\(" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
   Reg -> [Char]
latexRegExp Reg
reg [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
   [Char]
"\\)"
  ]

prtComments :: ([(String,String)],[String]) -> String
prtComments :: ([([Char], [Char])], [[Char]]) -> [Char]
prtComments ([([Char], [Char])]
xs,[[Char]]
ys) =
    (if [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
ys
        then [Char]
"There are no single-line comments in the grammar. \\\\"
        else [Char]
"Single-line comments begin with " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
sing [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++[Char]
". \\\\")
    [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
    (if [([Char], [Char])] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [([Char], [Char])]
xs
        then [Char]
"There are no multiple-line comments in the grammar."
        else [Char]
"Multiple-line comments are  enclosed with " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
mult [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++[Char]
".")
 where
 sing :: [Char]
sing = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
List.intercalate [Char]
", " ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char]
symbol([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[Char] -> [Char]
prt) [[Char]]
ys
 mult :: [Char]
mult = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
List.intercalate [Char]
", " ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
         (([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (\([Char]
x,[Char]
y) -> [Char] -> [Char]
symbol ([Char] -> [Char]
prt [Char]
x)
                       [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" and " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                      [Char] -> [Char]
symbol ([Char] -> [Char]
prt [Char]
y)) [([Char], [Char])]
xs

prtSymb :: String -> CF -> String
prtSymb :: [Char] -> CF -> [Char]
prtSymb [Char]
name CF
cf = case CF -> [[Char]]
forall f. CFG f -> [[Char]]
cfgSymbols CF
cf of
                   [] -> [Char]
"\nThere are no symbols in " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".\\\\\n"
                   [[Char]]
xs -> [Char]
"The symbols used in " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" are the following: \\\\\n"
                         [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                         Int -> [[[Char]]] -> [Char]
tabular Int
3 ([[Char]] -> [[[Char]]]
forall a. Monoid a => [a] -> [[a]]
three ([[Char]] -> [[[Char]]]) -> [[Char]] -> [[[Char]]]
forall a b. (a -> b) -> a -> b
$ ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char]
symbol([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[Char] -> [Char]
prt) [[Char]]
xs)

prtReserved :: String -> CF -> String
prtReserved :: [Char] -> CF -> [Char]
prtReserved [Char]
name CF
cf = case CF -> [[Char]]
forall f. CFG f -> [[Char]]
reservedWords CF
cf of
                       [] -> [Char] -> [Char]
stringRes [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                             [Char]
"\nThere are no reserved words in " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
".\\\\\n"
                       [[Char]]
xs -> [Char] -> [Char]
stringRes [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                             Int -> [[[Char]]] -> [Char]
tabular Int
3 ([[Char]] -> [[[Char]]]
forall a. Monoid a => [a] -> [[a]]
three ([[Char]] -> [[[Char]]]) -> [[Char]] -> [[[Char]]]
forall a b. (a -> b) -> a -> b
$ ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char]
reserved([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[Char] -> [Char]
prt) [[Char]]
xs)

stringRes :: String -> String
stringRes :: [Char] -> [Char]
stringRes [Char]
name = [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
                 [[Char]
"The set of reserved words is the set of terminals ",
                  [Char]
"appearing in the grammar. Those reserved words ",
                  [Char]
"that consist of non-letter characters are called symbols, and ",
                  [Char]
"they are treated in a different way from those that ",
                  [Char]
"are similar to identifiers. The lexer ",
                  [Char]
"follows rules familiar from languages ",
                  [Char]
"like Haskell, C, and Java, including longest match ",
                  [Char]
"and spacing conventions.",
                  [Char]
"\n\n",
                  [Char]
"The reserved words used in " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" are the following: \\\\\n"]

-- | Group a list into blocks of 3 elements.
three :: Monoid a => [a] -> [[a]]
three :: forall a. Monoid a => [a] -> [[a]]
three []         = []
three [a
x]        = [[a
x,a
forall a. Monoid a => a
mempty,a
forall a. Monoid a => a
mempty]]
three [a
x,a
y]      = [[a
x,a
y,a
forall a. Monoid a => a
mempty]]
three (a
x:a
y:a
z:[a]
xs) = [a
x,a
y,a
z] [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [a] -> [[a]]
forall a. Monoid a => [a] -> [[a]]
three [a]
xs

prtBNF :: String -> CF -> String
prtBNF :: [Char] -> CF -> [Char]
prtBNF [Char]
name CF
cf = [[Char]] -> [Char]
unlines
  [ [Char]
"\\section*{The syntactic structure of " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}"
  , [Char]
""
  , [Char]
"Non-terminals are enclosed between $\\langle$ and $\\rangle$."
  , [Char]
"The symbols " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
arrow [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (production), " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
delimiter [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (union)"
  , [Char]
"and " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
empty [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (empty rule) belong to the BNF notation."
  , [Char]
"All other symbols are terminals.\\\\"
  , [(Cat, [Rule])] -> [Char]
prtRules (CF -> [(Cat, [Rule])]
ruleGroups CF
cf)
  ]

prtRules :: [(Cat,[Rule])] -> String
prtRules :: [(Cat, [Rule])] -> [Char]
prtRules          [] = []
prtRules ((Cat
c,[]):[(Cat, [Rule])]
xs)
    = Int -> [[[Char]]] -> [Char]
tabular Int
3 [[Cat -> [Char]
nonterminal Cat
c,[Char]
arrow,[]]] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [(Cat, [Rule])] -> [Char]
prtRules [(Cat, [Rule])]
xs
prtRules ((Cat
c, Rule
r : [Rule]
rs) : [(Cat, [Rule])]
xs)
    = Int -> [[[Char]]] -> [Char]
tabular Int
3 ([Cat -> [Char]
nonterminal Cat
c,[Char]
arrow,[Either Cat [Char]] -> [Char]
prtSymbols ([Either Cat [Char]] -> [Char]) -> [Either Cat [Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ Rule -> [Either Cat [Char]]
forall function. Rul function -> [Either Cat [Char]]
rhsRule Rule
r] [[Char]] -> [[[Char]]] -> [[[Char]]]
forall a. a -> [a] -> [a]
:
                 [[[],[Char]
delimiter,[Either Cat [Char]] -> [Char]
prtSymbols (Rule -> [Either Cat [Char]]
forall function. Rul function -> [Either Cat [Char]]
rhsRule Rule
y)] | Rule
y <-  [Rule]
rs]) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
      [(Cat, [Rule])] -> [Char]
prtRules [(Cat, [Rule])]
xs

prtSymbols :: [Either Cat String] -> String
prtSymbols :: [Either Cat [Char]] -> [Char]
prtSymbols [] = [Char]
empty
prtSymbols [Either Cat [Char]]
xs = (Either Cat [Char] -> [Char] -> [Char])
-> [Char] -> [Either Cat [Char]] -> [Char]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ([Char] -> [Char] -> [Char]
(+++) ([Char] -> [Char] -> [Char])
-> (Either Cat [Char] -> [Char])
-> Either Cat [Char]
-> [Char]
-> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either Cat [Char] -> [Char]
p) [] [Either Cat [Char]]
xs
 where p :: Either Cat [Char] -> [Char]
p (Left  Cat
r) = Cat -> [Char]
nonterminal Cat
r --- (prt r)
       p (Right [Char]
r) = [Char] -> [Char]
terminal    ([Char] -> [Char]
prt [Char]
r)


prt :: String -> String
prt :: [Char] -> [Char]
prt = (Char -> [Char]) -> [Char] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> [Char]
escape
  where escape :: Char -> [Char]
escape Char
'\\'                               = [Char]
"$\\backslash$"
        escape Char
'~'                                = [Char]
"\\~{}"
        escape Char
'^'                                = [Char]
"{\\textasciicircum}"
        escape Char
c | Char
c Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ([Char]
"$&%#_{}" :: String) = [Char
'\\', Char
c]
        escape Char
c | Char
c Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ([Char]
"+=|<>-" :: String)  = [Char]
"{$"  [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char
c] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"$}"
        escape Char
c                                  = [Char
c]

macros :: String
macros :: [Char]
macros = [[Char]] -> [Char]
unlines
  [ [Char]
"\\newcommand{\\emptyP}{\\mbox{$\\epsilon$}}"
  , [Char]
"\\newcommand{\\terminal}[1]{\\mbox{{\\texttt {#1}}}}"
  , [Char]
"\\newcommand{\\nonterminal}[1]{\\mbox{$\\langle \\mbox{{\\sl #1 }} \\! \\rangle$}}"
  , [Char]
"\\newcommand{\\arrow}{\\mbox{::=}}"
  , [Char]
"\\newcommand{\\delimit}{\\mbox{$|$}}"
  , [Char]
"\\newcommand{\\reserved}[1]{\\mbox{{\\texttt {#1}}}}"
  , [Char]
"\\newcommand{\\literal}[1]{\\mbox{{\\texttt {#1}}}}"
  , [Char]
"\\newcommand{\\symb}[1]{\\mbox{{\\texttt {#1}}}}"
  ]

reserved :: String -> String
reserved :: [Char] -> [Char]
reserved [Char]
s = [Char]
"{\\reserved{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}}"

literal :: String -> String
literal :: [Char] -> [Char]
literal [Char]
s = [Char]
"{\\literal{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}}"

empty :: String
empty :: [Char]
empty = [Char]
"{\\emptyP}"

symbol :: String -> String
symbol :: [Char] -> [Char]
symbol [Char]
s = [Char]
"{\\symb{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}}"

tabular :: Int -> [[String]] -> String
tabular :: Int -> [[[Char]]] -> [Char]
tabular Int
n [[[Char]]]
xs = [Char]
"\n\\begin{tabular}{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Int -> [Char] -> [[Char]]
forall a. Int -> a -> [a]
replicate Int
n [Char]
"l") [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
               ([[Char]] -> [Char]) -> [[[Char]]] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\([Char]
a:[[Char]]
as) -> ([Char] -> [Char] -> [Char]) -> [Char] -> [[Char]] -> [Char]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr [Char] -> [Char] -> [Char]
(+++) [Char]
"\\\\\n" ([Char]
a[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (Char
'&'Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:) [[Char]]
as)) [[[Char]]]
xs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
               [Char]
"\\end{tabular}\\\\\n"

terminal :: String -> String
terminal :: [Char] -> [Char]
terminal [Char]
s = [Char]
"{\\terminal{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}}"

nonterminal :: Cat -> String
nonterminal :: Cat -> [Char]
nonterminal Cat
s = [Char]
"{\\nonterminal{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
mkId (Cat -> [Char]
identCat Cat
s) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}}" where
 mkId :: [Char] -> [Char]
mkId = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
mk
 mk :: Char -> Char
mk Char
c = case Char
c of
   Char
'_' -> Char
'-' ---
   Char
_ -> Char
c


arrow :: String
arrow :: [Char]
arrow = [Char]
" {\\arrow} "

delimiter :: String
delimiter :: [Char]
delimiter = [Char]
" {\\delimit} "

beginDocument :: String -> String
beginDocument :: [Char] -> [Char]
beginDocument [Char]
name = [[Char]] -> [Char]
unlines
 [ [Char]
""
 , [Char]
"\\documentclass[a4paper,11pt]{article}"
 , [Char]
"\\usepackage[T1]{fontenc}"
 , [Char]
"\\usepackage[utf8x]{inputenc}"
 , [Char]
"\\setlength{\\parindent}{0mm}"
 , [Char]
"\\setlength{\\parskip}{1mm}"
 , [Char]
""
 , [Char]
"\\title{The Language " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}"
 , [Char]
"\\author{BNF-converter}"
 , [Char]
""
 , [Char]
"\\begin{document}"
 , [Char]
"\\maketitle"
 , [Char]
""
 ]

endDocument :: String
endDocument :: [Char]
endDocument = [[Char]] -> [Char]
unlines
  [ [Char]
""
  , [Char]
"\\end{document}"
  ]

latexRegExp :: Reg -> String
latexRegExp :: Reg -> [Char]
latexRegExp = Int -> Reg -> [Char]
rex Int
0
  where
  rex :: Int -> Reg -> String
  rex :: Int -> Reg -> [Char]
rex Int
i = \case
    RSeq Reg
r0 Reg
r   -> Int -> Int -> [Char] -> [Char]
forall {a}. Ord a => a -> a -> [Char] -> [Char]
ifPar Int
i Int
2 ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Int -> Reg -> [Char]
rex Int
2 Reg
r0 [Char] -> [Char] -> [Char]
+++ Int -> Reg -> [Char]
rex Int
2 Reg
r
    RAlt Reg
r0 Reg
r   -> Int -> Int -> [Char] -> [Char]
forall {a}. Ord a => a -> a -> [Char] -> [Char]
ifPar Int
i Int
1 ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Int -> Reg -> [Char]
rex Int
1 Reg
r0 [Char] -> [Char] -> [Char]
+++ [Char]
"\\mid" [Char] -> [Char] -> [Char]
+++ Int -> Reg -> [Char]
rex Int
1 Reg
r
    RMinus Reg
r0 Reg
r -> Int -> Int -> [Char] -> [Char]
forall {a}. Ord a => a -> a -> [Char] -> [Char]
ifPar Int
i Int
1 ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Int -> Reg -> [Char]
rex Int
2 Reg
r0 [Char] -> [Char] -> [Char]
+++ [Char]
"-" [Char] -> [Char] -> [Char]
+++ Int -> Reg -> [Char]
rex Int
2 Reg
r
    RStar Reg
r     -> Int -> Reg -> [Char]
rex Int
3 Reg
r [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"*"
    RPlus Reg
r     -> Int -> Reg -> [Char]
rex Int
3 Reg
r [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"+"
    ROpt Reg
r      -> Int -> Reg -> [Char]
rex Int
3 Reg
r [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"?"
    Reg
REps        -> [Char]
"\\epsilon"
    RChar Char
c     -> [Char]
"\\mbox{`" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
prt [Char
c] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'}"
    RAlts [Char]
s     -> [Char]
"[" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\\mbox{``" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
prt [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"''}" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]"
    RSeqs [Char]
s     -> [Char]
"\\{" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\\mbox{``" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
prt [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"''}" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\\}"
    Reg
RDigit      -> [Char]
"{\\nonterminal{digit}}"
    Reg
RLetter     -> [Char]
"{\\nonterminal{letter}}"
    Reg
RUpper      -> [Char]
"{\\nonterminal{upper}}"
    Reg
RLower      -> [Char]
"{\\nonterminal{lower}}"
    Reg
RAny        -> [Char]
"{\\nonterminal{anychar}}"
  ifPar :: a -> a -> [Char] -> [Char]
ifPar a
i a
j [Char]
s = if a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
j then [Char]
"(" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")" else [Char]
s