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 Pos
30 p_Position = (<$> P.getPosition) $ \p ->
32 (intOfPos $ P.sourceLine p)
33 (intOfPos $ P.sourceColumn p)
34 intOfPos :: P.Pos -> Int
35 intOfPos = fromInteger . toInteger . P.unPos
37 p_Line :: Parser e s Line
38 p_Line = intOfPos . P.sourceLine <$> P.getPosition
40 p_Column :: Parser e s Column
41 p_Column = intOfPos . P.sourceColumn <$> P.getPosition
43 p_CellKey :: Row -> Parser e s Row
44 p_CellKey row = pdbg "CellKey" $ do
45 P.skipMany $ P.char ' '
49 [ P.try $ P.string "- " $> KeyDash
52 , P.try $ P.some (P.char '#') <* P.lookAhead (P.try $ P.char ' ') >>= \hs ->
53 return $ KeySection $ List.length hs
57 <$> many (P.satisfy $ \c ->
58 Char.isAlphaNum c || c=='-' || c=='_')
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
71 let row' = TreeN (Cell pos posEnd key) mempty : row
73 KeySection{} -> p_CellEnd row'
74 KeyDash{} -> p_Row row'
75 KeyColon{} -> p_Row row'
76 KeyGreat{} -> p_Row row'
77 KeyEqual{} -> p_CellEnd row'
78 KeyBar{} -> p_CellEnd row'
79 KeyLower{} -> undefined -- NOTE: handled in 'p_CellLower'
81 p_CellLower :: Row -> Parser e s Row
82 p_CellLower row = pdbg "CellLower" $ do
83 P.skipMany $ P.char ' '
88 posClose <- p_Position
90 TreeN (Cell pos posClose $ KeyLower name attrs) .
92 let treeElem toks (Cell _ p c) =
93 let (o,_) = pairBorders (PairElem name attrs) toks in
94 Tree0 $ Cell pos p (o<>c)
95 let indent = List.replicate (columnPos pos - 1) ' '
97 P.try (P.char '>' >> treeElem (tokens [TokenPlain ""]) <$> p_CellLinesUntilElemEnd indent name) <|>
98 P.try (P.char '\n' >> P.string indent >> treeHere <$> p_CellLines indent) <|>
99 P.try (P.string "/>" >> treeElem mempty <$> p_CellLine) <|>
100 (P.eof $> treeHere (Cell posClose posClose ""))
103 p_name :: Parser e s Name
106 <$> many (P.satisfy $ \c ->
107 Char.isAlphaNum c || c=='-' || c=='_')
108 p_attrs = P.many $ P.try $
110 <$> (Text.pack <$> P.some (P.char ' '))
112 p_line :: Parser e s Text
113 p_line = Text.pack <$> P.many (P.satisfy (/='\n'))
114 p_CellLine :: Parser e s (Cell Text)
119 return $ Cell pos posEnd content
120 p_CellLines :: String -> Parser e s (Cell Text)
121 p_CellLines indent = do
124 Text.intercalate "\n"
125 <$> P.sepBy (P.try p_line) (P.try $ P.char '\n' >> P.string indent)
127 return $ Cell pos posEnd content
128 p_CellLinesUntilElemEnd :: String -> Text -> Parser e s (Cell Text)
129 p_CellLinesUntilElemEnd indent name = P.dbg "CellLinesUntilElemEnd" $ do
131 content <- Text.intercalate "\n" . List.reverse <$> go []
133 return $ Cell pos posEnd content
135 go :: [Text] -> Parser e s [Text]
137 P.try ((\w p l -> Text.pack w <> Text.pack p <> l : ls)
138 <$> P.many (P.char ' ')
139 <*> P.string ("</"<>Text.unpack name)
141 (p_line >>= \l -> P.try $
146 p_CellText :: Row -> Parser e s Row
147 p_CellText row = pdbg "CellText" $ do
148 P.skipMany $ P.char ' '
150 line <- Text.pack <$> P.some (P.satisfy (/='\n'))
152 return $ Tree0 (Cell pos posEnd line) : row
154 p_CellSpaces :: Row -> Parser e s Row
155 p_CellSpaces row = pdbg "CellSpaces" $ do
156 P.skipSome $ P.char ' '
158 return $ Tree0 (Cell pos pos "") : row
160 p_CellEnd :: Row -> Parser e s Row
161 p_CellEnd row = pdbg "Row" $
162 P.try (p_CellLower row) <|>
163 P.try (p_CellText row) <|>
167 p_Row :: Row -> Parser e s Row
168 p_Row row = pdbg "Row" $
169 P.try (p_CellKey row) <|>
172 p_Rows :: Rows -> Parser e s Rows
175 let rows' = appendRow rows (List.reverse row) in
177 (P.newline >> p_Rows rows')
179 p_Trees :: Parser e s (Trees (Cell Key) (Cell Text))
180 p_Trees = unRoot . collapseRows <$> p_Rows [root]
182 root = TreeN (Cell pos0 pos0 KeyDash) mempty
183 unRoot (TreeN (unCell -> KeyDash) roots) = roots