{-# LANGUAGE OverloadedStrings #-}

module BNFC.Backend.Latex.Latex where

import BNFC.Prelude

import Control.Monad.State

import           Data.Foldable   (fold)
import           Data.List       (intercalate, intersperse)
import           Data.List.Split (chunksOf)
import qualified Data.Map        as Map
import           Data.String     (fromString)

import Prettyprinter
import System.FilePath (takeBaseName, (<.>))

import BNFC.CF

import BNFC.Backend.CommonInterface.Backend
import BNFC.Backend.Common.Utils as Utils
import BNFC.Backend.Latex.State

import BNFC.Options.GlobalOptions

import BNFC.Types.Position
import BNFC.Types.Regex

import qualified BNFC.Utils.List2 as List2


latex :: LBNF -> State LatexBackendState Result
latex :: LBNF -> State LatexBackendState Result
latex LBNF
lbnf = do
  LatexBackendState
st <- StateT LatexBackendState Identity LatexBackendState
forall s (m :: * -> *). MonadState s m => m s
get
  let cfName :: String
cfName = String -> String
takeBaseName (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ GlobalOptions -> String
optInput (GlobalOptions -> String) -> GlobalOptions -> String
forall a b. (a -> b) -> a -> b
$ LatexBackendState -> GlobalOptions
globalOpt LatexBackendState
st
  Result -> State LatexBackendState Result
forall (m :: * -> *) a. Monad m => a -> m a
return [(String
cfName String -> String -> String
<.> String
"tex", LBNF -> String -> String
cf2string LBNF
lbnf String
cfName)]

cf2string :: LBNF -> String -> String
cf2string :: LBNF -> String -> String
cf2string LBNF
lbnf String
cfName = LayoutOptions -> Doc () -> String
docToString LayoutOptions
defaultLayoutOptions (Doc () -> String) -> Doc () -> String
forall a b. (a -> b) -> a -> b
$ LBNF -> String -> Doc ()
cf2doc LBNF
lbnf String
cfName

cf2doc :: LBNF -> String -> Doc ()
cf2doc :: LBNF -> String -> Doc ()
cf2doc LBNF
lbnf String
cfName = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
forall ann. Doc ann
emptyDoc ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$
  [ Doc ()
"%% File generated by the BNF Converter."
  , String -> Doc ()
beginning String
cfName
  , Doc ()
macros
  , Doc ()
"This document was automatically generated by the {\\em BNF-Converter}."
  , LBNF -> String -> Doc ()
printTerminals LBNF
lbnf String
cfName
  , LBNF -> String -> Doc ()
printGrammar LBNF
lbnf String
cfName
  , Doc ()
"\\end{document}"
  ]

beginning :: String -> Doc ()
beginning :: String -> Doc ()
beginning String
cfName = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ Doc ()
"\\batchmode"
  , Doc ()
forall ann. Doc ann
emptyDoc
  , Doc ()
"\\documentclass[a4paper,11pt]{article}"
  , Doc ()
"\\usepackage[T1]{fontenc}"
  , Doc ()
"\\usepackage[utf8x]{inputenc}"
  , Doc ()
"\\setlength{\\parindent}{0mm}"
  , Doc ()
"\\setlength{\\parskip}{1mm}"
  , Doc ()
forall ann. Doc ann
emptyDoc
  , Doc ()
"\\title{The Language" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}"
  , Doc ()
"\\author{BNF-converter}"
  , Doc ()
forall ann. Doc ann
emptyDoc
  , Doc ()
"\\begin{document}"
  , Doc ()
"\\maketitle"
  ]

macros :: Doc ()
macros :: Doc ()
macros = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ Doc ()
"\\newcommand{\\emptyP}{\\mbox{$\\epsilon$}}"
  , Doc ()
"\\newcommand{\\terminal}[1]{\\mbox{{\\texttt {#1}}}}"
  , Doc ()
"\\newcommand{\\nonterminal}[1]{\\mbox{$\\langle \\mbox{{\\sl #1 }} \\! \\rangle$}}"
  , Doc ()
"\\newcommand{\\arrow}{\\mbox{::=}}"
  , Doc ()
"\\newcommand{\\delimit}{\\mbox{$|$}}"
  , Doc ()
"\\newcommand{\\reserved}[1]{\\mbox{{\\texttt {#1}}}}"
  , Doc ()
"\\newcommand{\\literal}[1]{\\mbox{{\\texttt {#1}}}}"
  , Doc ()
"\\newcommand{\\symb}[1]{\\mbox{{\\texttt {#1}}}}"
  ]

printTerminals :: LBNF -> String -> Doc ()
printTerminals :: LBNF -> String -> Doc ()
printTerminals LBNF
lbnf String
cfName = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
forall ann. Doc ann
emptyDoc ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$
  [ Doc ()
"\\section*{The lexical structure of" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}" ]
  [Doc ()] -> [Doc ()] -> [Doc ()]
forall a. [a] -> [a] -> [a]
++ Bool -> [Doc ()] -> [Doc ()]
forall m. Monoid m => Bool -> m -> m
Utils.when Bool
hasBuiltins
    [ Doc ()
"\\subsection*{Literals}"
    , [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
forall ann. Doc ann
emptyDoc ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ BuiltinCat -> Doc ()
printBuiltin (BuiltinCat -> Doc ()) -> [BuiltinCat] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [BuiltinCat]
usedBuiltins
    ]
  [Doc ()] -> [Doc ()] -> [Doc ()]
forall a. [a] -> [a] -> [a]
++ Bool -> [Doc ()] -> [Doc ()]
forall m. Monoid m => Bool -> m -> m
Utils.when Bool
hasTokens
    [ [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
forall ann. Doc ann
emptyDoc ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ (CatName, WithPosition TokenDef) -> Doc ()
printToken ((CatName, WithPosition TokenDef) -> Doc ())
-> [(CatName, WithPosition TokenDef)] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(CatName, WithPosition TokenDef)]
tokens ]
  [Doc ()] -> [Doc ()] -> [Doc ()]
forall a. [a] -> [a] -> [a]
++ [ Doc ()
"\\subsection*{Reserved words and symbols}"
     , Doc ()
reservedWords
     , String -> [String] -> Doc ()
printKeywords String
cfName [String]
keywords
     , String -> [String] -> Doc ()
printSymbols String
cfName [String]
symbols ]
  [Doc ()] -> [Doc ()] -> [Doc ()]
forall a. [a] -> [a] -> [a]
++ [ [String] -> Result -> Doc ()
printComments [String]
lineComments Result
blockComments ]

  where

    hasBuiltins :: Bool
    hasBuiltins :: Bool
hasBuiltins = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Map BuiltinCat (List1 Position) -> Bool
forall k a. Map k a -> Bool
Map.null (Map BuiltinCat (List1 Position) -> Bool)
-> Map BuiltinCat (List1 Position) -> Bool
forall a b. (a -> b) -> a -> b
$ LBNF -> Map BuiltinCat (List1 Position)
_lbnfASTBuiltins LBNF
lbnf

    usedBuiltins :: [BuiltinCat]
    usedBuiltins :: [BuiltinCat]
usedBuiltins = Map BuiltinCat (List1 Position) -> [BuiltinCat]
forall k a. Map k a -> [k]
Map.keys (Map BuiltinCat (List1 Position) -> [BuiltinCat])
-> Map BuiltinCat (List1 Position) -> [BuiltinCat]
forall a b. (a -> b) -> a -> b
$ LBNF -> Map BuiltinCat (List1 Position)
_lbnfASTBuiltins LBNF
lbnf

    hasTokens :: Bool
    hasTokens :: Bool
hasTokens = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Map CatName (WithPosition TokenDef) -> Bool
forall k a. Map k a -> Bool
Map.null (Map CatName (WithPosition TokenDef) -> Bool)
-> Map CatName (WithPosition TokenDef) -> Bool
forall a b. (a -> b) -> a -> b
$ LBNF -> Map CatName (WithPosition TokenDef)
_lbnfTokenDefs LBNF
lbnf

    tokens :: [(CatName, WithPosition TokenDef)]
    tokens :: [(CatName, WithPosition TokenDef)]
tokens = Map CatName (WithPosition TokenDef)
-> [(CatName, WithPosition TokenDef)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map CatName (WithPosition TokenDef)
 -> [(CatName, WithPosition TokenDef)])
-> Map CatName (WithPosition TokenDef)
-> [(CatName, WithPosition TokenDef)]
forall a b. (a -> b) -> a -> b
$ LBNF -> Map CatName (WithPosition TokenDef)
_lbnfTokenDefs LBNF
lbnf

    keywords :: [String]
    keywords :: [String]
keywords = CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (CatName -> String) -> (Keyword -> CatName) -> Keyword -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Keyword -> CatName
theKeyword (Keyword -> String) -> [Keyword] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map Keyword (List1 Position) -> [Keyword]
forall k a. Map k a -> [k]
Map.keys (LBNF -> Map Keyword (List1 Position)
_lbnfKeywords LBNF
lbnf)

    symbols :: [String]
    symbols :: [String]
symbols = CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (CatName -> String) -> (Symbol -> CatName) -> Symbol -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Symbol -> CatName
theSymbol (Symbol -> String) -> [Symbol] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map Symbol (List1 Position) -> [Symbol]
forall k a. Map k a -> [k]
Map.keys (LBNF -> Map Symbol (List1 Position)
_lbnfSymbols LBNF
lbnf)

    lineComments :: [String]
    lineComments :: [String]
lineComments =
      (\(LineComment CatName
s1) -> CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList CatName
s1) (LineComment -> String) -> [LineComment] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map Position LineComment -> [LineComment]
forall k a. Map k a -> [a]
Map.elems (LBNF -> Map Position LineComment
_lbnfLineComments LBNF
lbnf)

    blockComments :: [(String, String)]
    blockComments :: Result
blockComments =
      (\(BlockComment CatName
s1 CatName
s2) -> (CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList CatName
s1, CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList CatName
s2))
      (BlockComment -> (String, String)) -> [BlockComment] -> Result
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
      Map Position BlockComment -> [BlockComment]
forall k a. Map k a -> [a]
Map.elems (LBNF -> Map Position BlockComment
_lbnfBlockComments LBNF
lbnf)

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

printToken :: (CatName, WithPosition TokenDef) -> Doc ()
printToken :: (CatName, WithPosition TokenDef) -> Doc ()
printToken (CatName
cName, WithPosition Position
_ TokenDef
tokenDef) = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ String -> Doc ()
forall a. IsString a => String -> a
fromString (CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList CatName
cName) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"literals are recognized by the regular expression",
   Doc ()
"\\(" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Regex -> Doc ()
printRegLatex (TokenDef -> Regex
regexToken TokenDef
tokenDef) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"\\)"]

reservedWords :: Doc ()
reservedWords :: Doc ()
reservedWords = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ Doc ()
"The set of reserved words is the set of terminals "
  , Doc ()
"appearing in the grammar. Those reserved words "
  , Doc ()
"that consist of non-letter characters are called symbols, and "
  , Doc ()
"they are treated in a different way from those that "
  , Doc ()
"are similar to identifiers. The lexer "
  , Doc ()
"follows rules familiar from languages "
  , Doc ()
"like Haskell, C, and Java, including longest match "
  , Doc ()
"and spacing conventions."
  ]

tabular :: Doc () -> Doc ()
tabular :: Doc () -> Doc ()
tabular Doc ()
d = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ Doc ()
"\\begin{tabular}{lll}"
  , Doc ()
d
  , Doc ()
"\\end{tabular} \\\\"
  ]

printKeywords :: String -> [String] -> Doc ()
printKeywords :: String -> [String] -> Doc ()
printKeywords String
cfName [String]
keywords =
  if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
keywords
  then Doc ()
"There are no reserved words in" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
dot
  else [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
    [ Doc ()
"The reserved words used in" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"are the following: \\\\"
    , Doc ()
forall ann. Doc ann
emptyDoc
    , Doc () -> Doc ()
tabular (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$ [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([String] -> Doc ()
printLine ([String] -> Doc ()) -> [[String]] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [String] -> [[String]]
forall e. Int -> [e] -> [[e]]
chunksOf Int
3 [String]
keywords)
    ]

  where

    printLine :: [String] -> Doc ()
    printLine :: [String] -> Doc ()
printLine [String]
l =
      if [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3
      then ([Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
"&" ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ String -> Doc ()
reserved (String -> Doc ()) -> [String] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
l) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"\\\\"
      else ([Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
"&") (String -> Doc ()
reserved (String -> Doc ()) -> [String] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
l) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
        [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep (Int -> Doc () -> [Doc ()]
forall a. Int -> a -> [a]
replicate (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
- [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
l) (Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"&")) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"\\\\"

reserved :: String -> Doc ()
reserved :: String -> Doc ()
reserved String
s = Doc ()
"{\\reserved{" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString (String -> String
printEscape String
s) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}}"

printSymbols :: String -> [String] -> Doc ()
printSymbols :: String -> [String] -> Doc ()
printSymbols String
cfName [String]
symbols =
  if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
symbols
  then Doc ()
"There are no symbols in" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
dot
  else [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
    [ Doc ()
"The symbols used in" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"are the following: \\\\"
    , Doc ()
forall ann. Doc ann
emptyDoc
    , Doc () -> Doc ()
tabular (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$ [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([String] -> Doc ()
printLine ([String] -> Doc ()) -> [[String]] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [String] -> [[String]]
forall e. Int -> [e] -> [[e]]
chunksOf Int
3 [String]
symbols)
    ]

  where

    printLine :: [String] -> Doc ()
    printLine :: [String] -> Doc ()
printLine [String]
l =
      if [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3
      then ([Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
"&") (String -> Doc ()
symbol (String -> Doc ()) -> [String] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
l) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"\\\\"
      else ([Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ())
-> ([Doc ()] -> [Doc ()]) -> [Doc ()] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
"&") (String -> Doc ()
symbol (String -> Doc ()) -> [String] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
l) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
        [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep (Int -> Doc () -> [Doc ()]
forall a. Int -> a -> [a]
replicate (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
- [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
l) (Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"&")) Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"\\\\"

symbol :: String -> Doc ()
symbol :: String -> Doc ()
symbol String
s = Doc ()
"{\\symb{" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString (String -> String
printEscape String
s) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}}"

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

printComments :: [String] -> [(String, String)] -> Doc ()
printComments :: [String] -> Result -> Doc ()
printComments [String]
linecomments Result
blockcomments = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ Doc ()
"\\subsection*{Comments}"
  , if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
linecomments
    then Doc ()
"There are no single-line comments in the grammar."
    else Doc ()
"Single-line comments begin with" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
      ([Doc ()] -> Doc ()
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([Doc ()] -> Doc ())
-> ([[Doc ()]] -> [Doc ()]) -> [[Doc ()]] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc ()] -> [[Doc ()]] -> [Doc ()]
forall a. [a] -> [[a]] -> [a]
intercalate [Doc ()
forall ann. Doc ann
comma Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space]) ((Doc () -> [Doc ()]) -> [Doc ()] -> [[Doc ()]]
forall a b. (a -> b) -> [a] -> [b]
map (Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
: []) (String -> Doc ()
symbol (String -> Doc ()) -> [String] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
linecomments)) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
dot
  , if Result -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Result
blockcomments
    then Doc ()
"There are no multiple-line comments in the grammar."
    else Doc ()
"Multiple-line comments are enclosed with" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
      ([Doc ()] -> Doc ()
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([Doc ()] -> Doc ())
-> ([[Doc ()]] -> [Doc ()]) -> [[Doc ()]] -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Doc ()] -> [[Doc ()]] -> [Doc ()]
forall a. [a] -> [[a]] -> [a]
intercalate [Doc ()
forall ann. Doc ann
comma Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space])
      ((Doc () -> [Doc ()]) -> [Doc ()] -> [[Doc ()]]
forall a b. (a -> b) -> [a] -> [b]
map (Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
: []) ((\(String
s1,String
s2) -> String -> Doc ()
symbol String
s1 Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"and" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
symbol String
s2) ((String, String) -> Doc ()) -> Result -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Result
blockcomments)) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<>
      Doc ()
forall ann. Doc ann
dot
  ]

printGrammar :: LBNF -> String -> Doc ()
printGrammar :: LBNF -> String -> Doc ()
printGrammar LBNF
lbnf String
cfName = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
  [ Doc ()
"\\section*{The syntactic structure of" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
cfName Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}"
  , Doc ()
forall ann. Doc ann
emptyDoc
  , Doc ()
"Non-terminals are enclosed between $\\langle$ and $\\rangle$."
  , Doc ()
"The symbols {\\arrow} (production), {\\delimit} (union)"
  , Doc ()
"and {\\emptyP} (empty rule) belong to the BNF notation."
  , Doc ()
"All other symbols are terminals.\\\\"
  , Doc ()
forall ann. Doc ann
emptyDoc
  , if [(Cat, [ARHS])] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Cat, [ARHS])]
rules
    then Doc ()
"There are no rules in this grammar."
    else [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
forall ann. Doc ann
emptyDoc ([Doc ()] -> [Doc ()]) -> [Doc ()] -> [Doc ()]
forall a b. (a -> b) -> a -> b
$ Doc () -> Doc ()
tabular (Doc () -> Doc ())
-> ((Cat, [ARHS]) -> Doc ()) -> (Cat, [ARHS]) -> Doc ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cat, [ARHS]) -> Doc ()
printRule ((Cat, [ARHS]) -> Doc ()) -> [(Cat, [ARHS])] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Cat, [ARHS])]
rules
  ]

  where

    rules :: [(Cat, [ARHS])]
    rules :: [(Cat, [ARHS])]
rules =
      ((Cat, Map Label (WithPosition ARuleRHS)) -> (Cat, [ARHS]))
-> [(Cat, Map Label (WithPosition ARuleRHS))] -> [(Cat, [ARHS])]
forall a b. (a -> b) -> [a] -> [b]
map
        (\(Cat
c,Map Label (WithPosition ARuleRHS)
m) -> (Cat
c,(Label, WithPosition ARuleRHS) -> ARHS
getARHS ((Label, WithPosition ARuleRHS) -> ARHS)
-> [(Label, WithPosition ARuleRHS)] -> [ARHS]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map Label (WithPosition ARuleRHS)
-> [(Label, WithPosition ARuleRHS)]
forall k a. Map k a -> [(k, a)]
Map.toList Map Label (WithPosition ARuleRHS)
m))
        (Map Cat (Map Label (WithPosition ARuleRHS))
-> [(Cat, Map Label (WithPosition ARuleRHS))]
forall k a. Map k a -> [(k, a)]
Map.toList (LBNF -> Map Cat (Map Label (WithPosition ARuleRHS))
_lbnfASTRules LBNF
lbnf))

    getARHS :: (Label, WithPosition ARuleRHS) -> ARHS
    getARHS :: (Label, WithPosition ARuleRHS) -> ARHS
getARHS (Label
_, WithPosition Position
_ (ARuleRHS RuleOrigin
_ Parseable
_ ARHS
arhs)) = ARHS
arhs

printRule :: (Cat, [ARHS]) -> Doc ()
printRule :: (Cat, [ARHS]) -> Doc ()
printRule = \case
  (Cat
c, []) -> Cat -> Doc ()
nonterminal Cat
c Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\arrow}" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\emptyP}" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"  \\\\"
  (Cat
c, [ARHS
a]) -> Cat -> Doc ()
nonterminal Cat
c Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\arrow}" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> ARHS -> Doc ()
printARHS ARHS
a Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"  \\\\"
  (Cat
c, ARHS
a:[ARHS]
as) -> [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep
    [ Cat -> Doc ()
nonterminal Cat
c Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\arrow}" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> ARHS -> Doc ()
printARHS ARHS
a Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"  \\\\"
    , Int -> Doc () -> Doc ()
forall ann. Int -> Doc ann -> Doc ann
indent Int
1 (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$ [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
vsep ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$
      (\ARHS
arhs -> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\delimit}" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
space Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"&" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<>
        ARHS -> Doc ()
printARHS ARHS
arhs Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"  \\\\")
      (ARHS -> Doc ()) -> [ARHS] -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
      [ARHS]
as
    ]

terminal :: String1 -> Doc ()
terminal :: CatName -> Doc ()
terminal CatName
s = Doc ()
"{\\terminal{" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString (String -> String
printEscape (CatName -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList CatName
s)) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}}"

nonterminal :: Cat -> Doc ()
nonterminal :: Cat -> Doc ()
nonterminal Cat
c =
  Doc ()
"{\\nonterminal{" Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString ((Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
escape (Cat -> String
printCatNamePrec' Cat
c)) Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
"}}"
  where
    escape :: Char -> Char
    escape :: Char -> Char
escape Char
char = case Char
char of
      Char
'_' -> Char
'-'
      Char
_   -> Char
char

printItem :: Item' String1 -> Doc ()
printItem :: Item' CatName -> Doc ()
printItem = \case
  (Terminal CatName
s)  -> CatName -> Doc ()
terminal CatName
s
  (NTerminal Cat
c) -> Cat -> Doc ()
nonterminal Cat
c

printARHS :: ARHS -> Doc ()
printARHS :: ARHS -> Doc ()
printARHS []   = String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\emptyP}"
printARHS ARHS
arhs = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ Item' CatName -> Doc ()
printItem (Item' CatName -> Doc ()) -> ARHS -> [Doc ()]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ARHS
arhs

printRegLatex :: Regex -> Doc ()
printRegLatex :: Regex -> Doc ()
printRegLatex = Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
0

class Print a where
  prt :: Int -> a -> Doc ()

instance {-# OVERLAPPABLE #-} Print a => Print [a] where
  prt :: Int -> [a] -> Doc ()
prt Int
i [a]
as = [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ (a -> Doc ()) -> [a] -> [Doc ()]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> a -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
i) [a]
as

instance Print Char where
  prt :: Int -> Char -> Doc ()
prt Int
_ Char
c = String -> Doc ()
forall a. IsString a => String -> a
fromString (String -> Doc ()) -> String -> Doc ()
forall a b. (a -> b) -> a -> b
$ String
"\\mbox{`" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
printEscape [Char
c] String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'}"

instance Print Regex where
  prt :: Int -> Regex -> Doc ()
prt Int
i Regex
e = case Regex
e of

    RChar (CMinus CharClassUnion
yes CharClassUnion
no) -> Int -> Int -> Doc () -> Doc ()
prPrec Int
i Int
1 (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$
      if CharClassUnion -> Bool
isEmpty CharClassUnion
no
      then Int -> CharClassUnion -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
2 CharClassUnion
yes
      else
        Int -> CharClassUnion -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
2 CharClassUnion
yes Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
        String -> Doc ()
forall a. IsString a => String -> a
fromString String
"-" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
        Int -> CharClassUnion -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
2 CharClassUnion
no

    RAlts  List2 Regex
regs -> Int -> Int -> Doc () -> Doc ()
prPrec Int
i Int
1 (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$ [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
"\\mid" ([Doc ()] -> [Doc ()]) -> [Doc ()] -> [Doc ()]
forall a b. (a -> b) -> a -> b
$
      (Regex -> Doc ()) -> [Regex] -> [Doc ()]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
1) ([Regex] -> [Doc ()]) -> [Regex] -> [Doc ()]
forall a b. (a -> b) -> a -> b
$ List2 Regex -> [Item (List2 Regex)]
forall l. IsList l => l -> [Item l]
List2.toList List2 Regex
regs

    RMinus Regex
reg1 Regex
reg2 -> Int -> Int -> Doc () -> Doc ()
prPrec Int
i Int
1 (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$
      Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
2 Regex
reg1 Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
      String -> Doc ()
forall a. IsString a => String -> a
fromString String
"-" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+>
      Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
2 Regex
reg2

    Regex
REps -> Doc ()
"\\epsilon"

    RSeqs  List2 Regex
regs -> Int -> Int -> Doc () -> Doc ()
prPrec Int
i Int
2 (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$ Int -> [Regex] -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
2 ([Regex] -> Doc ()) -> [Regex] -> Doc ()
forall a b. (a -> b) -> a -> b
$ List2 Regex -> [Item (List2 Regex)]
forall l. IsList l => l -> [Item l]
List2.toList List2 Regex
regs

    RStar  Regex
reg  -> Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
3 Regex
reg Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"*"

    RPlus  Regex
reg  -> Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
3 Regex
reg Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"+"

    ROpt   Regex
reg  -> Int -> Regex -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
3 Regex
reg Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"?"

instance Print CharClassUnion where
  prt :: Int -> CharClassUnion -> Doc ()
prt Int
i CharClassUnion
e = case CharClassUnion
e of
    CharClassUnion
CAny      -> Doc ()
"{\\nonterminal{anychar}}"
    CAlt []   -> String -> Doc ()
forall a. HasCallStack => String -> a
panic String
"CharClass shouldn't be empty"
    CAlt [CharClassAtom
a]  -> Int -> CharClassAtom -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
0 CharClassAtom
a
    CAlt [CharClassAtom]
alts -> [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
hsep ([Doc ()] -> Doc ()) -> [Doc ()] -> Doc ()
forall a b. (a -> b) -> a -> b
$ Doc () -> [Doc ()] -> [Doc ()]
forall a. a -> [a] -> [a]
intersperse Doc ()
"\\mid" ([Doc ()] -> [Doc ()]) -> [Doc ()] -> [Doc ()]
forall a b. (a -> b) -> a -> b
$ (CharClassAtom -> Doc ()) -> [CharClassAtom] -> [Doc ()]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> CharClassAtom -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
i) [CharClassAtom]
alts

instance Print CharClassAtom where
  prt :: Int -> CharClassAtom -> Doc ()
prt Int
_ CharClassAtom
e = case CharClassAtom
e of
    CChar Char
c -> Int -> Char -> Doc ()
forall a. Print a => Int -> a -> Doc ()
prt Int
0 Char
c
    CharClassAtom
CDigit  -> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\nonterminal{digit}}"
    CharClassAtom
CLower  -> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\nonterminal{lower}}"
    CharClassAtom
CUpper  -> String -> Doc ()
forall a. IsString a => String -> a
fromString String
"{\\nonterminal{upper}}"