1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 module Language.TCT.Tree where
5 import Control.Applicative (Applicative(..))
7 import Data.Eq (Eq(..))
8 import Data.Foldable (Foldable(..))
9 import Data.Foldable (foldr)
10 import Data.Function (($), (.))
11 import Data.Functor (Functor, (<$>))
12 import Data.Maybe (Maybe(..))
13 import Data.Ord (Ordering(..), Ord(..))
14 import Data.Semigroup (Semigroup(..))
15 import Data.Sequence (Seq, ViewL(..), (|>))
16 import Data.Text (Text)
17 import Data.Traversable (Traversable(..))
18 import Data.Tuple (fst,snd)
19 import Prelude (undefined, Int, Num(..))
20 import Text.Show (Show(..))
21 import qualified Data.List as List
22 import qualified Data.Sequence as Seq
23 import qualified Data.Text as Text
25 import Language.TCT.Elem
31 deriving (Eq, Show, Functor)
33 instance Traversable (Tree k) where
34 traverse f (TreeN k ts) = TreeN k <$> traverse (traverse f) ts
35 traverse f (Tree0 a) = Tree0 <$> f a
36 instance Foldable (Tree k) where
37 foldMap f (TreeN _k ts) = foldMap (foldMap f) ts
38 foldMap f (Tree0 k) = f k
40 mapTreeWithKey :: (Maybe k -> a -> b) -> Tree k a -> Tree k b
41 mapTreeWithKey = go Nothing
43 go _k f (TreeN k ts) = TreeN k (go (Just k) f <$> ts)
44 go k f (Tree0 a) = Tree0 (f k a)
46 traverseTreeWithKey :: Applicative f => (Maybe k -> a -> f b) -> Tree k a -> f (Tree k b)
47 traverseTreeWithKey = go Nothing
49 go _p f (TreeN k ts) = TreeN k <$> traverse (go (Just k) f) ts
50 go p f (Tree0 a) = Tree0 <$> f p a
53 type Trees k a = Seq (Tree k a)
55 newtype PrettyTree k a = PrettyTree (Trees k a)
56 instance (Show k, Show a) => Show (PrettyTree k a) where
57 show (PrettyTree t) = Text.unpack $ prettyTrees t
59 prettyTree :: (Show k, Show a) => Tree k a -> Text
60 prettyTree = Text.unlines . pretty
62 prettyTrees :: (Show k, Show a) => Trees k a -> Text
63 prettyTrees = foldr (\t acc -> prettyTree t <> "\n" <> acc) ""
65 pretty :: (Show k, Show a) => Tree k a -> [Text]
66 pretty (Tree0 a) = [Text.pack (show a)]
67 pretty (TreeN k ts0) = Text.pack (show k) : prettySubTrees ts0
72 t:<ts | Seq.null ts -> "|" : shift "`- " " " (pretty t)
73 | otherwise -> "|" : shift "+- " "| " (pretty t) <> prettySubTrees ts
74 shift first other = List.zipWith (<>) (first : List.repeat other)
77 type Pos = (Line,Column)
79 posTree :: Tree (Cell k) (Cell a) -> Pos
80 posTree (TreeN c _) = posCell c
81 posTree (Tree0 c) = posCell c
83 posEndTree :: Tree (Cell k) (Cell a) -> Pos
84 posEndTree (TreeN c _) = posEndCell c
85 posEndTree (Tree0 c) = posEndCell c
91 -- | Line in the source file, counting from 1.
93 linePos :: Pos -> Line
97 -- | Column in the source file, counting from 1.
99 columnPos :: Pos -> Column
103 -- | A list of 'Key's, maybe ended by 'Value', all read on the same 'Line'.
104 type Row = [Tree (Cell Key) (Cell Text)]
107 -- | NOTE: every 'Cell' as a 'Pos',
108 -- which is useful to indicate matches/errors/warnings/whatever,
109 -- or outputing in a format somehow preserving
110 -- the original input style.
111 data Cell a = Cell Pos Pos a
114 unCell :: Cell a -> a
115 unCell (Cell _ _ a) = a
117 posCell :: Cell a -> Pos
118 posCell (Cell pos _ _) = pos
120 posEndCell :: Cell a -> Pos
121 posEndCell (Cell _ pos _) = pos
123 lineCell :: Cell a -> Line
124 lineCell = fst . posCell
125 columnCell :: Cell a -> Column
126 columnCell = snd . posCell
129 cell0 = Cell pos0 pos0
132 data Key = KeyColon Name White -- ^ @name:@ begin 'Cell'
133 | KeyEqual Name White -- ^ @name=@ begin 'Value'
134 | KeyBar Name White -- ^ @name|@ continue 'Value'
135 | KeyGreat Name White -- ^ @name>@ continue 'Cell'
136 | KeyLower Name Attrs -- ^ @<name a=b@ begin HereDoc
137 | KeyDash -- ^ @- @ begin item
138 | KeySection LevelSection -- ^ @### @ begin section
144 -- ** Type 'LevelSection'
145 type LevelSection = Int
148 type Rows = [Tree (Cell Key) (Cell Text)]
150 -- | @appendRow rows row@ appends @row@ to @rows@.
152 -- [@rows@] parent 'Rows', from closest to farest (non-strictly descending)
153 -- [@row@] next 'Row', from leftest column to rightest (non-stricly ascending)
154 appendRow :: Rows -> Row -> Rows
155 appendRow [] row = List.reverse row
156 appendRow parents [] = parents
157 appendRow rows@(parent:parents) row@(cell:cells) =
158 trac ("appendRow: rows=" <> show rows) $
159 trac ("appendRow: row=" <> show row) $
161 let colParent = columnPos $ posTree parent in
162 let colRow = columnPos $ posTree cell in
163 case dbg "colParent" colParent`compare`dbg "colRow" colRow of
165 case (dbg "parent" parent,dbg "cell" cell) of
166 (Tree0{}, TreeN{}) -> eq
167 (Tree0 p, Tree0{}) | Text.null (unCell p) -> eq -- FIXME: useful?
168 (Tree0 p, Tree0 r) -> appendTree0 p r
171 case (dbg "parent" parent,dbg "cell" cell) of
172 (Tree0 p, Tree0 r) -> appendTree0 p r
173 (_, TreeN (unCell -> KeySection sectionRow) _)
174 | Just (sectionParent, secPar:secPars) <- collapseSection colRow rows ->
175 case dbg "sectionParent" sectionParent`compare`dbg "sectionRow" sectionRow of
176 LT -> appendRow (cell:secPar:secPars) cells
177 EQ -> appendRow (cell:insertChild secPar secPars) cells
179 (TreeN (unCell -> KeySection{}) _, Tree0{}) -> lt
180 (TreeN (unCell -> KeySection{}) _, TreeN{}) -> lt
181 (Tree0{}, TreeN{}) -> eq
182 (TreeN{}, TreeN{}) -> eq
183 (TreeN{}, Tree0{}) -> eq
187 case appendCellText p r of
188 Nothing -> appendRow (Tree0 r : insertChild (Tree0 p) parents) cells
189 Just c -> appendRow (Tree0 c : parents) cells
190 lt = appendRow [] row <> rows
191 eq = appendRow (cell : insertChild parent parents) cells
192 gt = appendRow (insertChild parent parents) row
193 -- | Find the first section (if any), returning its level, and the path collapsed upto it.
194 collapseSection :: Column -> Rows -> Maybe (Int,Rows)
195 collapseSection col xxs@(x:xs) | columnPos (posTree x) == col =
197 TreeN (unCell -> KeySection lvl) _ -> Just (lvl,xxs)
198 _ -> (\(lvl,cs) -> (lvl,insertChild x cs)) <$> collapseSection col xs
199 collapseSection _ _ = Nothing
201 appendCellText :: Cell Text -> Cell Text -> Maybe (Cell Text)
202 appendCellText (Cell posPar posEndPar p)
203 (Cell posRow posEndRow r) =
204 trac ("appendCellText: p="<>show p) $
205 trac ("appendCellText: r="<>show r) $
206 dbg "appendCellText" $
207 case linePos posRow - linePos posEndPar of
208 0 -> Just $ Cell posPar posEndRow $ p <> pad <> r
209 where pad = padding (columnPos posEndPar) (columnPos posRow)
210 1 -> Just $ Cell posPar posEndRow $ p <> pad <> r
211 where pad = "\n" <> padding (columnPos posPar) (columnPos posRow)
214 padding x y = Text.replicate (y - x) " "
216 insertChild :: Tree (Cell Key) (Cell Text) -> Rows -> Rows
217 insertChild child ps@[] =
218 trac ("insertChild: child="<>show child) $
219 trac ("insertChild: ps="<>show ps) $
222 insertChild _child (Tree0{}:_) = undefined
223 insertChild child ps@(TreeN parent treesParent:parents) =
224 trac ("insertChild: child="<>show child) $
225 trac ("insertChild: ps="<>show ps) $
227 case dbg "colParent" (columnCell parent)`compare`dbg "colChild" (columnPos $ posTree child) of
228 LT -> TreeN parent (treesParent |> child) : parents
229 EQ -> TreeN parent (treesParent |> child) : parents
232 collapseRows :: Rows -> Tree (Cell Key) (Cell Text)
233 collapseRows [] = undefined
234 collapseRows [child] = dbg "collapseRows" $ child
235 collapseRows (child:parents) = dbg "collapseRows" $ collapseRows $ insertChild child parents