1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 {-# LANGUAGE Rank2Types #-}
4 {-# LANGUAGE TupleSections #-}
5 {-# LANGUAGE TypeFamilies #-}
6 module Language.TCT.Read.Tree where
8 import Control.Applicative (Applicative(..), Alternative(..))
9 import Control.Monad (Monad(..), void)
11 import Data.Eq (Eq(..))
12 import Data.Function (($), (.))
13 import Data.Functor ((<$>), ($>), (<$))
14 import Data.Monoid (Monoid(..))
15 import Data.Semigroup (Semigroup(..))
16 import Data.String (String)
17 import Data.Text (Text)
18 import Prelude (undefined, Int, Num(..), toInteger)
19 import qualified Data.Char as Char
20 import qualified Data.List as List
21 import qualified Data.Sequence as Seq
22 import qualified Data.Text as Text
23 import qualified Text.Megaparsec as P
25 import Language.TCT.Tree
26 import Language.TCT.Token
27 import Language.TCT.Read.Elem
29 p_Position :: Parser e s (Line,Column)
30 p_Position = (<$> P.getPosition) $ \p ->
31 ( intOfPos $ P.sourceLine p
32 , intOfPos $ P.sourceColumn p)
33 intOfPos :: P.Pos -> Int
34 intOfPos = fromInteger . toInteger . P.unPos
36 p_Line :: Parser e s Line
37 p_Line = intOfPos . P.sourceLine <$> P.getPosition
39 p_Column :: Parser e s Column
40 p_Column = intOfPos . P.sourceColumn <$> P.getPosition
42 p_CellKey :: Row -> Parser e s Row
43 p_CellKey row = pdbg "CellKey" $ do
44 P.skipMany $ P.char ' '
48 [ P.try $ P.string "- " $> KeyDash
51 , P.try $ P.some (P.char '#') <* P.lookAhead (P.try $ P.char ' ') >>= \hs ->
52 return $ KeySection $ List.length hs
56 <$> many (P.satisfy $ \c ->
57 Char.isAlphaNum c || c=='-' || c=='_')
58 wh <- Text.pack <$> P.many (P.char ' ')
60 [ P.try $ KeyColon name wh
62 <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy $ \c -> c=='\n'||c==' '))
63 , P.char '>' $> KeyGreat name wh
64 , P.char '=' $> KeyEqual name wh
65 , 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 KeyColon{} -> p_Row row'
75 KeyGreat{} -> p_Row row'
76 KeyEqual{} -> p_CellEnd row'
77 KeyBar{} -> p_CellEnd row'
78 KeyLower{} -> undefined -- NOTE: handled in 'p_CellLower'
80 p_CellLower :: Row -> Parser e s Row
81 p_CellLower row = pdbg "CellLower" $ do
82 P.skipMany $ P.char ' '
87 posClose <- p_Position
89 TreeN (Cell pos posClose $ KeyLower name attrs) .
91 let treeElem toks (Cell _ p c) =
92 let (o,_) = pairBorders (PairElem name attrs) toks in
93 Tree0 $ Cell pos p (o<>c)
94 let indent = List.replicate (columnPos pos - 1) ' '
96 P.try (P.char '>' >> treeElem (tokens [TokenPlain ""]) <$> p_CellLinesUntilElemEnd indent name) <|>
97 P.try (P.char '\n' >> P.string indent >> treeHere <$> p_CellLines indent) <|>
98 P.try (P.string "/>" >> treeElem mempty <$> p_CellLine) <|>
99 (P.eof $> treeHere (Cell posClose posClose ""))
102 p_name :: Parser e s Name
105 <$> many (P.satisfy $ \c ->
106 Char.isAlphaNum c || c=='-' || c=='_')
107 p_attrs = P.many $ P.try $
109 <$> (Text.pack <$> P.some (P.char ' '))
111 p_line :: Parser e s Text
112 p_line = Text.pack <$> P.many (P.satisfy (/='\n'))
113 p_CellLine :: Parser e s (Cell Text)
118 return $ Cell pos posEnd content
119 p_CellLines :: String -> Parser e s (Cell Text)
120 p_CellLines indent = do
123 Text.intercalate "\n"
124 <$> P.sepBy (P.try p_line) (P.try $ P.char '\n' >> P.string indent)
126 return $ Cell pos posEnd content
127 p_CellLinesUntilElemEnd :: String -> Text -> Parser e s (Cell Text)
128 p_CellLinesUntilElemEnd indent name = P.dbg "CellLinesUntilElemEnd" $ do
130 content <- Text.intercalate "\n" . List.reverse <$> go []
132 return $ Cell pos posEnd content
134 go :: [Text] -> Parser e s [Text]
136 P.try ((\w p l -> Text.pack w <> Text.pack p <> l : ls)
137 <$> P.many (P.char ' ')
138 <*> P.string ("</"<>Text.unpack name)
140 (p_line >>= \l -> P.try $
145 p_CellText :: Row -> Parser e s Row
146 p_CellText row = pdbg "CellText" $ do
147 P.skipMany $ P.char ' '
149 line <- Text.pack <$> P.some (P.satisfy (/='\n'))
151 return $ Tree0 (Cell pos posEnd line) : row
153 p_CellSpaces :: Row -> Parser e s Row
154 p_CellSpaces row = pdbg "CellSpaces" $ do
155 P.skipSome $ P.char ' '
157 return $ Tree0 (Cell pos pos "") : row
159 p_CellEnd :: Row -> Parser e s Row
160 p_CellEnd row = pdbg "Row" $
161 P.try (p_CellLower row) <|>
162 P.try (p_CellText row) <|>
166 p_Row :: Row -> Parser e s Row
167 p_Row row = pdbg "Row" $
168 P.try (p_CellKey row) <|>
171 p_Rows :: Rows -> Parser e s Rows
174 let rows' = appendRow rows (List.reverse row) in
176 (P.newline >> p_Rows rows')
178 p_Trees :: Parser e s (Trees (Cell Key) (Cell Text))
179 p_Trees = unRoot . collapseRows <$> p_Rows [root]
181 root = TreeN (Cell (0,0) (0,0) KeyDash) mempty
182 unRoot (TreeN (unCell -> KeyDash) roots) = roots