module Language.Ltml.Parser.Paragraph
    ( paragraphP
    )
where

import Control.Applicative (optional, (<|>))
import Control.Monad.State (evalStateT)
import Data.Maybe (isJust)
import Language.Lsd.AST.Type.Paragraph (ParagraphType (ParagraphType))
import Language.Ltml.AST.Node (Node (Node))
import Language.Ltml.AST.Paragraph (Paragraph (Paragraph))
import Language.Ltml.Parser (Parser)
import Language.Ltml.Parser.Common.Lexeme (nLexeme1)
import Language.Ltml.Parser.Label (labelingP)
import Language.Ltml.Parser.Text (textForestP)
import Text.Megaparsec (try)

paragraphP :: ParagraphType -> Parser (Node Paragraph)
paragraphP :: ParagraphType -> Parser (Node Paragraph)
paragraphP (ParagraphType ParagraphFormat
fmt TextType EnumType
tt) = do
    -- Note:
    --  * Backtracking due to `try` is limited to
    --    `labelingP <* sp <* char '\n'`, and this is typically cheap.
    --    - CONSIDER: Avoid `try`.
    Maybe Label
mLabel <- ParsecT Void Text Identity Label
-> ParsecT Void Text Identity (Maybe Label)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ParsecT Void Text Identity Label
-> ParsecT Void Text Identity Label
forall a.
ParsecT Void Text Identity a -> ParsecT Void Text Identity a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try (ParsecT Void Text Identity Label
 -> ParsecT Void Text Identity Label)
-> ParsecT Void Text Identity Label
-> ParsecT Void Text Identity Label
forall a b. (a -> b) -> a -> b
$ ParsecT Void Text Identity Label
-> ParsecT Void Text Identity Label
forall (m :: * -> *) a. MonadParser m => m a -> m a
nLexeme1 ParsecT Void Text Identity Label
forall (m :: * -> *). MonadParser m => m Label
labelingP)
    [TextTree
   HardLineBreak
   FootnoteReference
   FontStyle
   Enumeration
   SentenceStart]
body <-
        if Maybe Label -> Bool
forall a. Maybe a -> Bool
isJust Maybe Label
mLabel
            then ParsecT
  Void
  Text
  Identity
  [TextTree
     HardLineBreak
     FootnoteReference
     FontStyle
     Enumeration
     SentenceStart]
bodyP ParsecT
  Void
  Text
  Identity
  [TextTree
     HardLineBreak
     FootnoteReference
     FontStyle
     Enumeration
     SentenceStart]
-> ParsecT
     Void
     Text
     Identity
     [TextTree
        HardLineBreak
        FootnoteReference
        FontStyle
        Enumeration
        SentenceStart]
-> ParsecT
     Void
     Text
     Identity
     [TextTree
        HardLineBreak
        FootnoteReference
        FontStyle
        Enumeration
        SentenceStart]
forall a.
ParsecT Void Text Identity a
-> ParsecT Void Text Identity a -> ParsecT Void Text Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> [TextTree
   HardLineBreak
   FootnoteReference
   FontStyle
   Enumeration
   SentenceStart]
-> ParsecT
     Void
     Text
     Identity
     [TextTree
        HardLineBreak
        FootnoteReference
        FontStyle
        Enumeration
        SentenceStart]
forall a. a -> ParsecT Void Text Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
            else ParsecT
  Void
  Text
  Identity
  [TextTree
     HardLineBreak
     FootnoteReference
     FontStyle
     Enumeration
     SentenceStart]
bodyP
    Node Paragraph -> Parser (Node Paragraph)
forall a. a -> ParsecT Void Text Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Node Paragraph -> Parser (Node Paragraph))
-> Node Paragraph -> Parser (Node Paragraph)
forall a b. (a -> b) -> a -> b
$ Maybe Label -> Paragraph -> Node Paragraph
forall a. Maybe Label -> a -> Node a
Node Maybe Label
mLabel (ParagraphFormat
-> [TextTree
      HardLineBreak
      FootnoteReference
      FontStyle
      Enumeration
      SentenceStart]
-> Paragraph
Paragraph ParagraphFormat
fmt [TextTree
   HardLineBreak
   FootnoteReference
   FontStyle
   Enumeration
   SentenceStart]
body)
  where
    bodyP :: ParsecT
  Void
  Text
  Identity
  [TextTree
     HardLineBreak
     FootnoteReference
     FontStyle
     Enumeration
     SentenceStart]
bodyP = StateT
  Bool
  (ParsecT Void Text Identity)
  [TextTree
     HardLineBreak
     FootnoteReference
     FontStyle
     Enumeration
     SentenceStart]
-> Bool
-> ParsecT
     Void
     Text
     Identity
     [TextTree
        HardLineBreak
        FootnoteReference
        FontStyle
        Enumeration
        SentenceStart]
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (TextType EnumType
-> StateT
     Bool
     (ParsecT Void Text Identity)
     [TextTree
        HardLineBreak
        FootnoteReference
        FontStyle
        Enumeration
        SentenceStart]
forall (m :: * -> *) lbrk fnref style enumType enum special.
(ParserWrapper m, LineBreakP lbrk, FootnoteRefP fnref,
 StyleP style, EnumP enumType enum, SpecialP m special) =>
TextType enumType -> m [TextTree lbrk fnref style enum special]
textForestP TextType EnumType
tt) Bool
True