{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Hdoc.DTC.Anchor where import Control.Applicative (Applicative(..)) import Control.Category import Control.Monad (Monad(..)) import Data.Bool import Data.Char (Char) import Data.Default.Class (Default(..)) import Data.Foldable (Foldable(..), concat) import Data.Function (($), const) import Data.Functor ((<$>)) import Data.Map.Strict (Map) import Data.Maybe (Maybe(..), maybe) import Data.Monoid (Monoid(..)) import Data.Semigroup (Semigroup(..)) import Data.Sequence ((|>)) import Data.Traversable (Traversable(..)) import Data.TreeMap.Strict (TreeMap(..)) import Data.TreeSeq.Strict (Tree(..), tree0) import qualified Control.Monad.Trans.State as S import qualified Data.Char as Char import qualified Data.List as List import qualified Data.Map.Strict as Map import qualified Data.Sequence as Seq import qualified Data.Strict.Maybe as Strict import qualified Data.Text.Lazy as TL import qualified Data.TreeMap.Strict as TreeMap -- import qualified Data.TreeSeq.Strict as TreeSeq import Hdoc.DTC.Document import Hdoc.DTC.Index -- * Type 'Rrefs' type Rrefs = Map Ident [Anchor] -- * Type 'Notes' -- | 'Note' by 'BodySection'. type Notes = Map PosPath [Note] -- ** Type 'Note' data Note = Note { note_number :: Nat1 , note_content :: [Para] } -- deriving (Eq,Show) -- * Type 'State' data State = State { state_section :: Pos , state_irefs :: Irefs , state_rrefs :: Rrefs , state_notes :: Notes , state_note :: Nat1 } instance Default State where def = State { state_section = def , state_irefs = mempty , state_rrefs = def , state_notes = def , state_note = def } -- * Class 'Anchorify' class Anchorify a where anchorify :: a -> S.State State a instance Anchorify a => Anchorify (Maybe a) where anchorify = traverse anchorify instance Anchorify Body where anchorify = traverse anchorify instance Anchorify (Tree BodyNode) where anchorify = \case Tree n ts -> case n of BodySection{..} -> do before@State{state_section} <- S.get S.put before{state_section = pos} t <- Tree <$> anchorify n <*> anchorify ts after <- S.get S.put after{state_section} return t BodyBlock{} -> tree0 <$> anchorify n instance Anchorify BodyNode where anchorify = \case BodySection{..} -> BodySection pos attrs <$> anchorify title <*> pure aliases <*> traverse anchorify judgments BodyBlock b -> BodyBlock <$> anchorify b instance Anchorify Block where anchorify = \case BlockPara p -> BlockPara <$> anchorify p b@BlockBreak{} -> return b b@BlockToC{} -> return b b@BlockToF{} -> return b b@BlockIndex{} -> return b BlockAside{..} -> BlockAside pos attrs <$> traverse anchorify blocks BlockFigure{..} -> BlockFigure pos type_ attrs <$> anchorify mayTitle <*> traverse anchorify paras BlockReferences{..} -> BlockReferences pos attrs <$> traverse anchorify refs BlockJudges{..} -> BlockJudges pos attrs <$> traverse anchorify jury BlockGrades{..} -> BlockGrades pos attrs <$> traverse anchorify scale instance Anchorify Para where anchorify = \case ParaItem{..} -> ParaItem <$> anchorify item ParaItems{..} -> ParaItems pos attrs <$> traverse anchorify items instance Anchorify ParaItem where anchorify = \case ParaPlain plain -> ParaPlain <$> anchorify plain ParaOL items -> ParaOL <$> traverse anchorify items ParaUL items -> ParaUL <$> traverse (traverse anchorify) items ParaQuote{..} -> ParaQuote type_ <$> traverse anchorify paras p@ParaArtwork{} -> return p p@ParaComment{} -> return p ParaJudgment j -> ParaJudgment <$> anchorify j instance Anchorify ListItem where anchorify ListItem{..} = ListItem name <$> traverse anchorify paras instance Anchorify Judgment where anchorify Judgment{..} = Judgment judges grades importance <$> anchorify question <*> traverse anchorify choices instance Anchorify Plain where anchorify = traverse anchorify instance Anchorify (Tree PlainNode) where anchorify (Tree n ts) = do State{..} <- S.get case n of PlainIref{term} | not $ null state_irefs , Just words <- pathFromWords term , Strict.Just anchs <- TreeMap.lookup words state_irefs -> do let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c let anch = Anchor{count, section=state_section} S.modify' $ \s -> s { state_irefs = TreeMap.insert const words (anch:anchs) state_irefs } Tree PlainIref{term, anchor=Just anch} <$> traverse anchorify ts PlainText txt | not $ null state_irefs -> do let (irefs,para) = indexifyWords state_section state_irefs (wordify txt) S.modify' $ \s -> s { state_irefs = irefs } return $ Tree PlainGroup para PlainNote{..} -> do let notes = Map.findWithDefault [] (pos_Ancestors state_section) state_notes S.modify' $ \s -> s { state_notes = Map.insert (pos_Ancestors state_section) (Note state_note note:notes) state_notes , state_note = succNat1 state_note } Tree PlainNote{number=Just state_note, note} <$> traverse anchorify ts -- NOTE: normally ts is empty anyway PlainRref{..} -> do let anchs = Map.findWithDefault [] to state_rrefs let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c let anch = Anchor{count, section=state_section} S.modify' $ \s -> s { state_rrefs = Map.insert to (anch:anchs) state_rrefs } Tree PlainRref{anchor=Just anch, to} <$> traverse anchorify ts _ -> Tree n <$> traverse anchorify ts instance Anchorify Title where anchorify (Title p) = Title <$> anchorify p instance Anchorify Reference where anchorify = return instance Anchorify Choice where anchorify Choice{..} = Choice <$> anchorify title <*> traverse anchorify opinions instance Anchorify Opinion where anchorify Opinion{..} = Opinion judge grade importance <$> anchorify comment instance Anchorify Grade where anchorify Grade{..} = Grade pos name color isDefault <$> anchorify title instance Anchorify Judge where anchorify Judge{..} = Judge name <$> anchorify title <*> pure defaultGrades