1 {-# LANGUAGE DuplicateRecordFields #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# OPTIONS_GHC -fno-warn-orphans #-}
6 module Hdoc.DTC.Check where
8 import Control.Applicative (Applicative(..))
9 import Control.Category
10 import Control.Monad (Monad(..))
12 import Data.Char (Char)
13 import Data.Default.Class (Default(..))
15 import Data.Foldable (Foldable(..), concat)
16 import Data.Function (($), const)
17 import Data.Functor ((<$>))
18 import Data.Map.Strict (Map)
19 import Data.IntMap.Strict (IntMap)
20 import Data.Maybe (Maybe(..), maybe)
21 import Data.Monoid (Monoid(..))
22 import Data.Semigroup (Semigroup(..))
23 import Data.Sequence ((|>))
24 import Data.Traversable (Traversable(..))
25 import Data.TreeMap.Strict (TreeMap(..))
26 import Data.TreeSeq.Strict (Tree(..), tree0)
27 import Text.Show (Show)
28 import qualified Control.Monad.Trans.State as S
29 import qualified Data.Char as Char
30 import qualified Data.List as List
31 import qualified Data.Map.Strict as Map
32 import qualified Data.IntMap.Strict as IntMap
33 import qualified Data.Sequence as Seq
34 import qualified Data.Strict.Maybe as Strict
35 import qualified Data.Text.Lazy as TL
36 import qualified Data.TreeMap.Strict as TreeMap
37 -- import qualified Data.TreeSeq.Strict as TreeSeq
38 import qualified Hjugement as MJ
40 import Hdoc.DTC.Document
44 type Rrefs = Map Ident [Anchor]
46 -- * Type 'NotesBySection'
47 type NotesBySection = Map PosPath Notes
50 type Notes = IntMap [Para]
54 { state_section :: Pos -- RO
55 , state_irefs :: Irefs
56 , state_rrefs :: Rrefs
57 , state_notes :: NotesBySection
59 , state_errors :: [Error]
61 instance Default State where
64 , state_irefs = TreeMap.empty
73 = Error_Judgment (MJ.ErrorSection Choice Judge Grade)
79 check :: a -> S.State State a
80 instance Check a => Check (Maybe a) where
81 check = traverse check
82 instance Check Body where
83 check = traverse check
84 instance Check (Tree BodyNode) where
89 before@State{state_section} <- S.get
90 S.put before{state_section = pos}
91 t <- Tree <$> check n <*> check ts
92 S.modify' $ \s -> s{state_section}
94 BodyBlock{} -> tree0 <$> check n
95 instance Check BodyNode where
101 <*> traverse check judgments
102 BodyBlock b -> BodyBlock <$> check b
103 instance Check Block where
105 BlockPara p -> BlockPara <$> check p
106 b@BlockBreak{} -> return b
107 b@BlockToC{} -> return b
108 b@BlockToF{} -> return b
109 b@BlockIndex{} -> return b
112 <$> traverse check blocks
114 BlockFigure pos type_ attrs
116 <*> traverse check paras
117 BlockReferences{..} ->
118 BlockReferences pos attrs
119 <$> traverse check refs
121 BlockJudges pos attrs
122 <$> traverse check jury
124 BlockGrades pos attrs
125 <$> traverse check scale
126 instance Check Para where
128 ParaItem{..} -> ParaItem <$> check item
129 ParaItems{..} -> ParaItems pos attrs <$> traverse check items
130 instance Check ParaItem where
132 ParaPlain plain -> ParaPlain <$> check plain
133 ParaOL items -> ParaOL <$> traverse check items
134 ParaUL items -> ParaUL <$> traverse (traverse check) items
135 ParaQuote{..} -> ParaQuote type_ <$> traverse check paras
136 p@ParaArtwork{} -> return p
137 p@ParaComment{} -> return p
138 ParaJudgment j -> ParaJudgment <$> check j
139 instance Check ListItem where
140 check ListItem{..} = ListItem name <$> traverse check paras
141 instance Check Plain where
142 check = traverse check
143 instance Check (Tree PlainNode) where
144 check (Tree n ts) = do
148 | not $ null state_irefs
149 , Just words <- pathFromWords term
150 , Strict.Just anchs <- TreeMap.lookup words state_irefs -> do
151 -- NOTE: Insert new anchor for this index ref.
152 let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c
153 let anch = Anchor{count, section=state_section}
155 { state_irefs = TreeMap.insert const words (anch:anchs) state_irefs }
156 Tree PlainIref{term, anchor=Just anch}
157 <$> traverse check ts
159 | not $ null state_irefs -> do
160 -- NOTE: Find indexed words in this text.
161 let (irefs,para) = indexifyWords state_section state_irefs (wordify txt)
163 { state_irefs = irefs }
164 return $ Tree PlainGroup para
166 -- NOTE: Insert new note for this section.
167 let section = pos_Ancestors state_section
169 { state_note = succNat1 state_note }
170 note' <- traverse check note
171 let noteByNumber = IntMap.singleton (unNat1 state_note) note'
172 State{state_notes=notes} <- S.get
174 { state_notes = Map.insertWith (<>) section noteByNumber notes }
175 Tree PlainNote{number=Just state_note, note=note'}
176 <$> traverse check ts -- NOTE: normally ts is empty anyway
178 -- NOTE: Insert new anchor for this reference ref.
179 let anchs = Map.findWithDefault [] to state_rrefs
180 let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c
181 let anch = Anchor{count, section=state_section}
183 { state_rrefs = Map.insert to (anch:anchs) state_rrefs }
184 Tree PlainRref{anchor=Just anch, to}
185 <$> traverse check ts
186 _ -> Tree n <$> traverse check ts
187 instance Check Title where
188 check (Title p) = Title <$> check p
189 instance Check Reference where
191 instance Check Judgment where
193 Judgment opinionsByChoice judges grades importance
195 <*> traverse check choices
196 instance Check Choice where
200 <*> traverse check opinions
201 instance Check Opinion where
203 Opinion judge grade importance
205 instance Check Grade where
207 Grade pos name color isDefault
209 instance Check Judge where
213 <*> pure defaultGrades