1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 {-# LANGUAGE Rank2Types #-}
4 {-# LANGUAGE ScopedTypeVariables #-}
5 {-# LANGUAGE TupleSections #-}
6 {-# LANGUAGE TypeFamilies #-}
7 module Language.TCT.Read.Tree where
9 import Control.Applicative (Applicative(..), Alternative(..))
10 import Control.Monad (Monad(..), void)
12 import Data.Eq (Eq(..))
13 import Data.Function (($), (.))
14 import Data.Functor ((<$>), ($>), (<$))
15 import Data.Monoid (Monoid(..))
16 import Data.Semigroup (Semigroup(..))
17 import Data.String (IsString(..))
18 import Data.Text (Text)
19 import Data.TreeSeq.Strict (Tree(..), Trees)
20 import Prelude (undefined, Num(..))
21 import qualified Data.Char as Char
22 import qualified Data.List as List
23 import qualified Data.Sequence as Seq
24 import qualified Data.Text as Text
25 import qualified Text.Megaparsec as P
26 import qualified Text.Megaparsec.Char as P
28 import Language.TCT.Cell
29 import Language.TCT.Token
30 import Language.TCT.Tree
31 import Language.TCT.Read.Cell
32 import Language.TCT.Read.Elem
34 p_CellKey :: Row -> Parser e s Row
35 p_CellKey row = pdbg "CellKey" $ do
36 P.skipMany $ P.char ' '
40 [ P.try $ P.char '-' >>
41 P.char ' ' $> KeyDash <|>
42 P.string "- " $> KeyDashDash
43 , P.try $ KeyDot . Text.pack
44 <$> P.some (P.satisfy Char.isDigit)
46 <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy $ \c -> c=='\n'||c==' '))
47 , P.try $ P.some (P.char '#') <* P.lookAhead (P.try $ P.char ' ') >>= \hs ->
48 return $ KeySection $ List.length hs
51 <$> P.between (P.string "[") (P.string "]") p_Name
52 <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy (=='\n')))
54 (\f -> KeyDotSlash $ "./"<>f)
56 <*> P.many (P.satisfy (/='\n'))
59 wh <- Text.pack <$> P.many (P.char ' ')
61 [ P.try $ KeyColon name wh
63 <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy $ \c -> c=='\n'||c==' '))
64 , P.char '>' $> KeyGreat name wh
65 , P.char '=' $> KeyEqual name wh
66 , P.char '|' $> KeyBar name wh
70 let row' = TreeN (Cell pos posEnd key) mempty : row
72 KeySection{} -> p_CellEnd row'
73 KeyDash{} -> p_Row row'
74 KeyDashDash{} -> p_CellText row'
75 KeyDot{} -> p_Row row'
76 KeyColon{} -> p_Row row'
77 KeyBrackets{} -> p_Row row'
78 KeyGreat{} -> p_Row row'
79 KeyEqual{} -> p_CellEnd row'
80 KeyBar{} -> p_CellEnd row'
81 KeyDotSlash{} -> p_CellEnd row'
82 KeyLower{} -> undefined -- NOTE: handled in 'p_CellLower'
84 p_Name :: Parser e s Name
86 (\h t -> Text.pack (h:t))
87 <$> (P.satisfy $ \c ->
88 Char.isAlphaNum c || c=='_')
89 <*> many (P.satisfy $ \c ->
90 Char.isAlphaNum c || c=='-' || c=='_')
92 p_Line :: Parser e s Text
93 p_Line = Text.pack <$> P.many (P.satisfy (/='\n'))
95 p_CellLower :: forall e s. Row -> Parser e s Row
96 p_CellLower row = pdbg "CellLower" $ do
97 P.skipMany $ P.char ' '
102 posClose <- p_Position
104 TreeN (Cell pos posClose $ KeyLower name attrs) .
105 Seq.singleton . Tree0
106 let treeElem toks (Cell _ p c) =
107 let (o,_) = pairBorders (PairElem name attrs) toks in
108 Tree0 $ Cell pos p (o<>c)
109 let indent = fromString $ List.replicate (columnPos pos - 1) ' '
111 P.try (P.char '>' >> treeElem (tokens [cell0 $ TokenPlain ""]) <$> p_CellLinesUntilElemEnd indent name) <|>
112 P.try (P.char '\n' >> P.string indent >> treeHere <$> p_CellLines indent) <|>
113 P.try (P.string "/>" >> treeElem mempty <$> p_CellLine) <|>
114 (P.eof $> treeHere (Cell posClose posClose ""))
117 p_attrs = P.many $ P.try $
119 <$> (Text.pack <$> P.some (P.char ' '))
121 p_CellLine :: Parser e s (Cell Text)
126 return $ Cell pos posEnd content
127 p_CellLines :: P.Tokens s -> Parser e s (Cell Text)
128 p_CellLines indent = do
131 Text.intercalate "\n"
132 <$> P.sepBy (P.try p_Line) (P.try $ P.char '\n' >> P.string indent)
134 return $ Cell pos posEnd content
135 p_CellLinesUntilElemEnd :: P.Tokens s -> Text -> Parser e s (Cell Text)
136 p_CellLinesUntilElemEnd indent name = do
138 content <- Text.intercalate "\n" . List.reverse <$> go []
140 return $ Cell pos posEnd content
142 go :: [Text] -> Parser e s [Text]
144 P.try ((\w l -> Text.pack w <> "</" <> name <> l : ls)
145 <$> P.many (P.char ' ')
146 <* P.string (fromString $ "</"<>Text.unpack name)
148 (p_Line >>= \l -> P.try $
153 p_CellText :: Row -> Parser e s Row
154 p_CellText row = pdbg "CellText" $ do
155 P.skipMany $ P.char ' '
157 line <- Text.pack <$> P.some (P.satisfy (/='\n'))
159 return $ Tree0 (Cell pos posEnd line) : row
161 p_CellSpaces :: Row -> Parser e s Row
162 p_CellSpaces row = pdbg "CellSpaces" $ do
163 P.skipSome $ P.char ' '
165 return $ Tree0 (Cell pos pos "") : row
167 p_CellEnd :: Row -> Parser e s Row
168 p_CellEnd row = pdbg "Row" $
169 P.try (p_CellLower row) <|>
170 P.try (p_CellText row) <|>
174 p_Row :: Row -> Parser e s Row
175 p_Row row = pdbg "Row" $
176 P.try (p_CellKey row) <|>
179 p_Rows :: Rows -> Parser e s Rows
182 let rows' = appendRow rows (List.reverse row) in
184 (P.newline >> p_Rows rows')
186 p_Trees :: Parser e s (Trees (Cell Key) (Cell Text))
187 p_Trees = unRoot . collapseRows <$> p_Rows [root]
189 root = TreeN (cell0 KeyDashDash) mempty
190 unRoot (TreeN (unCell -> KeyDashDash) roots) = roots