{-# LANGUAGE FlexibleInstances #-}
{- |
   Module      : Text.Pandoc.TeX
   Copyright   : Copyright (C) 2017-2023 John MacFarlane
   License     : GNU GPL, version 2 or above

   Maintainer  : John MacFarlane <jgm@berkeley.edu>
   Stability   : alpha
   Portability : portable

Types for TeX tokens and macros.
-}
module Text.Pandoc.TeX ( Tok(..)
                       , TokType(..)
                       , Macro(..)
                       , ArgSpec(..)
                       , ExpansionPoint(..)
                       , MacroScope(..)
                       , SourcePos
                       )
where
import Data.Text (Text)
import Text.Parsec (SourcePos, sourceName)
import Text.Pandoc.Sources
import Data.List (groupBy)

data TokType = CtrlSeq Text | Spaces | Newline | Symbol | Word | Comment |
               Esc1    | Esc2   | Arg Int  | DeferredArg Int
     deriving (TokType -> TokType -> Bool
(TokType -> TokType -> Bool)
-> (TokType -> TokType -> Bool) -> Eq TokType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TokType -> TokType -> Bool
== :: TokType -> TokType -> Bool
$c/= :: TokType -> TokType -> Bool
/= :: TokType -> TokType -> Bool
Eq, Eq TokType
Eq TokType =>
(TokType -> TokType -> Ordering)
-> (TokType -> TokType -> Bool)
-> (TokType -> TokType -> Bool)
-> (TokType -> TokType -> Bool)
-> (TokType -> TokType -> Bool)
-> (TokType -> TokType -> TokType)
-> (TokType -> TokType -> TokType)
-> Ord TokType
TokType -> TokType -> Bool
TokType -> TokType -> Ordering
TokType -> TokType -> TokType
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: TokType -> TokType -> Ordering
compare :: TokType -> TokType -> Ordering
$c< :: TokType -> TokType -> Bool
< :: TokType -> TokType -> Bool
$c<= :: TokType -> TokType -> Bool
<= :: TokType -> TokType -> Bool
$c> :: TokType -> TokType -> Bool
> :: TokType -> TokType -> Bool
$c>= :: TokType -> TokType -> Bool
>= :: TokType -> TokType -> Bool
$cmax :: TokType -> TokType -> TokType
max :: TokType -> TokType -> TokType
$cmin :: TokType -> TokType -> TokType
min :: TokType -> TokType -> TokType
Ord, Int -> TokType -> ShowS
[TokType] -> ShowS
TokType -> String
(Int -> TokType -> ShowS)
-> (TokType -> String) -> ([TokType] -> ShowS) -> Show TokType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TokType -> ShowS
showsPrec :: Int -> TokType -> ShowS
$cshow :: TokType -> String
show :: TokType -> String
$cshowList :: [TokType] -> ShowS
showList :: [TokType] -> ShowS
Show)

data Tok = Tok SourcePos TokType Text
     deriving (Tok -> Tok -> Bool
(Tok -> Tok -> Bool) -> (Tok -> Tok -> Bool) -> Eq Tok
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Tok -> Tok -> Bool
== :: Tok -> Tok -> Bool
$c/= :: Tok -> Tok -> Bool
/= :: Tok -> Tok -> Bool
Eq, Eq Tok
Eq Tok =>
(Tok -> Tok -> Ordering)
-> (Tok -> Tok -> Bool)
-> (Tok -> Tok -> Bool)
-> (Tok -> Tok -> Bool)
-> (Tok -> Tok -> Bool)
-> (Tok -> Tok -> Tok)
-> (Tok -> Tok -> Tok)
-> Ord Tok
Tok -> Tok -> Bool
Tok -> Tok -> Ordering
Tok -> Tok -> Tok
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Tok -> Tok -> Ordering
compare :: Tok -> Tok -> Ordering
$c< :: Tok -> Tok -> Bool
< :: Tok -> Tok -> Bool
$c<= :: Tok -> Tok -> Bool
<= :: Tok -> Tok -> Bool
$c> :: Tok -> Tok -> Bool
> :: Tok -> Tok -> Bool
$c>= :: Tok -> Tok -> Bool
>= :: Tok -> Tok -> Bool
$cmax :: Tok -> Tok -> Tok
max :: Tok -> Tok -> Tok
$cmin :: Tok -> Tok -> Tok
min :: Tok -> Tok -> Tok
Ord, Int -> Tok -> ShowS
[Tok] -> ShowS
Tok -> String
(Int -> Tok -> ShowS)
-> (Tok -> String) -> ([Tok] -> ShowS) -> Show Tok
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Tok -> ShowS
showsPrec :: Int -> Tok -> ShowS
$cshow :: Tok -> String
show :: Tok -> String
$cshowList :: [Tok] -> ShowS
showList :: [Tok] -> ShowS
Show)

instance ToSources [Tok] where
  toSources :: [Tok] -> Sources
toSources = [(SourcePos, Text)] -> Sources
Sources
    ([(SourcePos, Text)] -> Sources)
-> ([Tok] -> [(SourcePos, Text)]) -> [Tok] -> Sources
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Tok] -> (SourcePos, Text)) -> [[Tok]] -> [(SourcePos, Text)]
forall a b. (a -> b) -> [a] -> [b]
map (\[Tok]
ts -> case [Tok]
ts of
                    Tok SourcePos
p TokType
_ Text
_ : [Tok]
_ -> (SourcePos
p, [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (Tok -> Text) -> [Tok] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Tok -> Text
tokToText [Tok]
ts)
                    [Tok]
_ -> String -> (SourcePos, Text)
forall a. HasCallStack => String -> a
error String
"toSources [Tok] encountered empty group")
    ([[Tok]] -> [(SourcePos, Text)])
-> ([Tok] -> [[Tok]]) -> [Tok] -> [(SourcePos, Text)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tok -> Tok -> Bool) -> [Tok] -> [[Tok]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (\(Tok SourcePos
p1 TokType
_ Text
_) (Tok SourcePos
p2 TokType
_ Text
_) -> SourcePos -> String
sourceName SourcePos
p1 String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== SourcePos -> String
sourceName SourcePos
p2)

tokToText :: Tok -> Text
tokToText :: Tok -> Text
tokToText (Tok SourcePos
_ TokType
_ Text
t) = Text
t

data ExpansionPoint = ExpandWhenDefined | ExpandWhenUsed
     deriving (ExpansionPoint -> ExpansionPoint -> Bool
(ExpansionPoint -> ExpansionPoint -> Bool)
-> (ExpansionPoint -> ExpansionPoint -> Bool) -> Eq ExpansionPoint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExpansionPoint -> ExpansionPoint -> Bool
== :: ExpansionPoint -> ExpansionPoint -> Bool
$c/= :: ExpansionPoint -> ExpansionPoint -> Bool
/= :: ExpansionPoint -> ExpansionPoint -> Bool
Eq, Eq ExpansionPoint
Eq ExpansionPoint =>
(ExpansionPoint -> ExpansionPoint -> Ordering)
-> (ExpansionPoint -> ExpansionPoint -> Bool)
-> (ExpansionPoint -> ExpansionPoint -> Bool)
-> (ExpansionPoint -> ExpansionPoint -> Bool)
-> (ExpansionPoint -> ExpansionPoint -> Bool)
-> (ExpansionPoint -> ExpansionPoint -> ExpansionPoint)
-> (ExpansionPoint -> ExpansionPoint -> ExpansionPoint)
-> Ord ExpansionPoint
ExpansionPoint -> ExpansionPoint -> Bool
ExpansionPoint -> ExpansionPoint -> Ordering
ExpansionPoint -> ExpansionPoint -> ExpansionPoint
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ExpansionPoint -> ExpansionPoint -> Ordering
compare :: ExpansionPoint -> ExpansionPoint -> Ordering
$c< :: ExpansionPoint -> ExpansionPoint -> Bool
< :: ExpansionPoint -> ExpansionPoint -> Bool
$c<= :: ExpansionPoint -> ExpansionPoint -> Bool
<= :: ExpansionPoint -> ExpansionPoint -> Bool
$c> :: ExpansionPoint -> ExpansionPoint -> Bool
> :: ExpansionPoint -> ExpansionPoint -> Bool
$c>= :: ExpansionPoint -> ExpansionPoint -> Bool
>= :: ExpansionPoint -> ExpansionPoint -> Bool
$cmax :: ExpansionPoint -> ExpansionPoint -> ExpansionPoint
max :: ExpansionPoint -> ExpansionPoint -> ExpansionPoint
$cmin :: ExpansionPoint -> ExpansionPoint -> ExpansionPoint
min :: ExpansionPoint -> ExpansionPoint -> ExpansionPoint
Ord, Int -> ExpansionPoint -> ShowS
[ExpansionPoint] -> ShowS
ExpansionPoint -> String
(Int -> ExpansionPoint -> ShowS)
-> (ExpansionPoint -> String)
-> ([ExpansionPoint] -> ShowS)
-> Show ExpansionPoint
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExpansionPoint -> ShowS
showsPrec :: Int -> ExpansionPoint -> ShowS
$cshow :: ExpansionPoint -> String
show :: ExpansionPoint -> String
$cshowList :: [ExpansionPoint] -> ShowS
showList :: [ExpansionPoint] -> ShowS
Show)

data MacroScope = GlobalScope | GroupScope
  deriving (MacroScope -> MacroScope -> Bool
(MacroScope -> MacroScope -> Bool)
-> (MacroScope -> MacroScope -> Bool) -> Eq MacroScope
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MacroScope -> MacroScope -> Bool
== :: MacroScope -> MacroScope -> Bool
$c/= :: MacroScope -> MacroScope -> Bool
/= :: MacroScope -> MacroScope -> Bool
Eq, Eq MacroScope
Eq MacroScope =>
(MacroScope -> MacroScope -> Ordering)
-> (MacroScope -> MacroScope -> Bool)
-> (MacroScope -> MacroScope -> Bool)
-> (MacroScope -> MacroScope -> Bool)
-> (MacroScope -> MacroScope -> Bool)
-> (MacroScope -> MacroScope -> MacroScope)
-> (MacroScope -> MacroScope -> MacroScope)
-> Ord MacroScope
MacroScope -> MacroScope -> Bool
MacroScope -> MacroScope -> Ordering
MacroScope -> MacroScope -> MacroScope
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: MacroScope -> MacroScope -> Ordering
compare :: MacroScope -> MacroScope -> Ordering
$c< :: MacroScope -> MacroScope -> Bool
< :: MacroScope -> MacroScope -> Bool
$c<= :: MacroScope -> MacroScope -> Bool
<= :: MacroScope -> MacroScope -> Bool
$c> :: MacroScope -> MacroScope -> Bool
> :: MacroScope -> MacroScope -> Bool
$c>= :: MacroScope -> MacroScope -> Bool
>= :: MacroScope -> MacroScope -> Bool
$cmax :: MacroScope -> MacroScope -> MacroScope
max :: MacroScope -> MacroScope -> MacroScope
$cmin :: MacroScope -> MacroScope -> MacroScope
min :: MacroScope -> MacroScope -> MacroScope
Ord, Int -> MacroScope -> ShowS
[MacroScope] -> ShowS
MacroScope -> String
(Int -> MacroScope -> ShowS)
-> (MacroScope -> String)
-> ([MacroScope] -> ShowS)
-> Show MacroScope
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MacroScope -> ShowS
showsPrec :: Int -> MacroScope -> ShowS
$cshow :: MacroScope -> String
show :: MacroScope -> String
$cshowList :: [MacroScope] -> ShowS
showList :: [MacroScope] -> ShowS
Show)

data Macro = Macro MacroScope ExpansionPoint [ArgSpec] (Maybe [Tok]) [Tok]
     deriving Int -> Macro -> ShowS
[Macro] -> ShowS
Macro -> String
(Int -> Macro -> ShowS)
-> (Macro -> String) -> ([Macro] -> ShowS) -> Show Macro
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Macro -> ShowS
showsPrec :: Int -> Macro -> ShowS
$cshow :: Macro -> String
show :: Macro -> String
$cshowList :: [Macro] -> ShowS
showList :: [Macro] -> ShowS
Show

data ArgSpec = ArgNum Int | Pattern [Tok]
     deriving Int -> ArgSpec -> ShowS
[ArgSpec] -> ShowS
ArgSpec -> String
(Int -> ArgSpec -> ShowS)
-> (ArgSpec -> String) -> ([ArgSpec] -> ShowS) -> Show ArgSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ArgSpec -> ShowS
showsPrec :: Int -> ArgSpec -> ShowS
$cshow :: ArgSpec -> String
show :: ArgSpec -> String
$cshowList :: [ArgSpec] -> ShowS
showList :: [ArgSpec] -> ShowS
Show