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 <$> many (P.satisfy $ \c ->
88 Char.isAlphaNum c || c=='-' || c=='_')
89 attrs <- P.many $ P.try $ (,) <$> (Text.pack <$> P.some (P.char ' ')) <*> p_Attr
90 posClose <- p_Position
92 TreeN (Cell pos posClose $ KeyLower name attrs) .
94 let treeElem m (Cell _ p c) =
95 let (o,_) = groupBorders (GroupElem name attrs) m in
96 Tree0 $ Cell pos p (o<>c)
97 let indent = List.replicate (columnPos pos - 1) ' '
99 P.try (P.char '>' >> treeElem mempty <$> p_lines indent) <|>
100 P.try (P.char '\n' >> P.string indent >> treeHere <$> p_lines indent) <|>
101 P.try (P.string "/>" >> treeElem (Tokens mempty) <$> p_lines indent) <|>
102 (P.eof $> treeHere (Cell posClose posClose ""))
105 p_lines :: String -> Parser e s (Cell Text)
109 Text.intercalate "\n"
111 (P.try $ Text.pack <$> P.many (P.satisfy (/='\n')))
112 (P.try $ P.char '\n' >> P.string indent)
114 return $ Cell pos posEnd content
116 p_CellText :: Row -> Parser e s Row
117 p_CellText row = pdbg "CellText" $ do
118 P.skipMany $ P.char ' '
120 line <- Text.pack <$> P.some (P.satisfy (/='\n'))
122 return $ Tree0 (Cell pos posEnd line) : row
124 p_CellSpaces :: Row -> Parser e s Row
125 p_CellSpaces row = pdbg "CellSpaces" $ do
126 P.skipSome $ P.char ' '
128 return $ Tree0 (Cell pos pos "") : row
130 p_CellEnd :: Row -> Parser e s Row
131 p_CellEnd row = pdbg "Row" $
132 P.try (p_CellLower row) <|>
133 P.try (p_CellText row) <|>
137 p_Row :: Row -> Parser e s Row
138 p_Row row = pdbg "Row" $
139 P.try (p_CellKey row) <|>
142 p_Rows :: Rows -> Parser e s Rows
145 let rows' = appendRow rows (List.reverse row) in
147 (P.newline >> p_Rows rows')
149 p_Trees :: Parser e s (Trees (Cell Key) (Cell Text))
150 p_Trees = unRoot . collapseRows <$> p_Rows [root]
152 root = TreeN (Cell (0,0) (0,0) KeyDash) mempty
153 unRoot (TreeN (unCell -> KeyDash) roots) = roots