{-# 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 ()
[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}}"