Fix XML rendition of PairFrenchquote.
[doclang.git] / Language / TCT / Read / Tree.hs
index 9763e2b1d8b019b833b0ba8a6f9c1a8885d80fc7..f6ba041ac87741ead8624e299e762ad0cb88ca2c 100644 (file)
@@ -2,88 +2,80 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TupleSections #-}
 {-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE ViewPatterns #-}
 module Language.TCT.Read.Tree where
 
--- import Data.String (IsString(..))
--- import qualified Data.TreeSeq.Strict as TreeSeq
 import Control.Applicative (Applicative(..), Alternative(..))
 import Control.Monad (Monad(..), void)
 import Data.Bool
 import Data.Eq (Eq(..))
 import Data.Function (($), (.))
 import Data.Functor ((<$>), ($>), (<$))
-import Data.Foldable (toList)
+import Data.List.NonEmpty (NonEmpty(..))
 import Data.Maybe (Maybe(..))
 import Data.Monoid (Monoid(..))
 import Data.Semigroup (Semigroup(..))
-import Data.TreeSeq.Strict (Tree(..), Trees)
+import Data.TreeSeq.Strict (Tree(..), Trees, tree0)
 import qualified Data.List as List
 import qualified Data.Sequence as Seq
 import qualified Data.Text.Lazy as TL
 import qualified Text.Megaparsec as P
 import qualified Text.Megaparsec.Char as P
 
+import Language.TCT.Debug
 import Language.TCT.Cell
--- import Language.TCT.Token
 import Language.TCT.Tree
 import Language.TCT.Read.Cell
 import Language.TCT.Read.Elem
 import Language.TCT.Read.Token
 
 p_CellHeader :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
-p_CellHeader row = pdbg "CellHeader" $ do
+p_CellHeader row = debugParser "CellHeader" $ do
        P.skipMany $ P.char ' '
-       pos <- p_Position
-       header <- pdbg "Header" $
-               P.choice $
-                [ P.try $ P.char '-' >>
-                       P.char ' ' $> HeaderDash <|>
-                       P.string "- " $> HeaderDashDash
-                , P.try $ HeaderDot
-                        <$> p_Digits
-                        <* P.char '.'
-                        <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy $ \c -> c=='\n'||c==' '))
-                , P.try $ P.some (P.char '#') <* P.lookAhead (P.try $ P.char ' ') >>= \hs ->
-                       return $ HeaderSection $ List.length hs
-                , P.try $
-                       HeaderBrackets
-                        <$> P.between (P.string "[") (P.string "]") p_Name
-                        <*  P.lookAhead (P.try $ P.eof <|> void (P.satisfy (=='\n')))
-                , P.try $
-                       (\f -> HeaderDotSlash $ "./"<>f)
-                        <$  P.string "./"
-                        <*> P.many (P.satisfy (/='\n'))
-                , do
-                       name <- p_Name
-                       wh <- p_HSpaces
+       Cell sp h <- p_Cell $ do
+               debugParser "Header" $
                        P.choice
-                        [ P.try $ HeaderColon name wh
-                                <$ P.char ':'
+                        [ P.try $ P.char '-' >>
+                               P.char ' ' $> HeaderDash <|>
+                               P.string "- " $> HeaderDashDash
+                        , P.try $ HeaderDot
+                                <$> p_Digits
+                                <* P.char '.'
                                 <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy $ \c -> c=='\n'||c==' '))
-                        , P.char '>' $> HeaderGreat name wh
-                        , P.char '=' $> HeaderEqual name wh
-                        , P.char '|' $> HeaderBar   name wh
+                        , P.try $ P.some (P.char '#') <* P.lookAhead (P.try $ P.char ' ') >>= \hs ->
+                               return $ HeaderSection $ List.length hs
+                        , P.try $
+                               HeaderBrackets
+                                <$> P.between (P.string "[") (P.string "]") p_Name
+                                <*  P.lookAhead (P.try $ P.eof <|> void (P.satisfy (=='\n')))
+                        , P.try $
+                               (\f -> HeaderDotSlash $ "./"<>f)
+                                <$  P.string "./"
+                                <*> P.many (P.satisfy (/='\n'))
+                        , do
+                               name <- p_Name
+                               wh <- p_HSpaces
+                               P.choice
+                                [ P.try $ HeaderColon name wh
+                                        <$ P.char ':'
+                                        <* P.lookAhead (P.try $ P.eof <|> void (P.satisfy $ \c -> c=='\n'||c==' '))
+                                , P.char '>' $> HeaderGreat name wh
+                                , P.char '=' $> HeaderEqual name wh
+                                , P.char '|' $> HeaderBar   name wh
+                                ]
                         ]
-                ]
-       posEnd <- p_Position
-       let row' = Tree (Cell pos posEnd $ NodeHeader header) mempty : row
-       case header of
+       let row' = Tree (Cell sp $ NodeHeader h) mempty : row
+       case h of
         HeaderSection{}  -> p_CellEnd  row'
         HeaderDash{}     -> p_Row      row'
-        HeaderDashDash{} -> p_CellText row'
+        HeaderDashDash{} -> p_CellRaw  row'
         HeaderDot{}      -> p_Row      row'
         HeaderColon{}    -> p_Row      row'
         HeaderBrackets{} -> p_Row      row'
         HeaderGreat{}    -> p_Row      row'
-        HeaderEqual{}    -> p_CellEnd  row'
-        HeaderBar{}      -> p_CellEnd  row'
+        HeaderEqual{}    -> p_CellRaw  row'
+        HeaderBar{}      -> p_CellRaw  row'
         HeaderDotSlash{} -> p_CellEnd  row'
-        -- HeaderLower{}    -> undefined -- NOTE: handled in 'p_CellLower'
-        -- TODO: move to a NodeLower
-        -- HeaderPara       -> undefined -- NOTE: only introduced later in 'appendRow'
 
 p_Name :: P.Tokens s ~ TL.Text => Parser e s Name
 p_Name = p_AlphaNums
@@ -100,28 +92,27 @@ p_Line1 :: P.Tokens s ~ TL.Text => Parser e s TL.Text
 p_Line1 = P.takeWhile1P (Just "Line") (/='\n')
 
 p_CellLower :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
-p_CellLower row = pdbg "CellLower" $ do
-       indent   <- p_HSpaces
-       pos      <- p_Position
-       void     $  P.char '<'
-       name     <- p_Name
-       attrs    <- p_ElemAttrs
-       posClose <- p_Position
+p_CellLower row = debugParser "CellLower" $ do
+       indent <- p_HSpaces
+       Cell ssp@(Span fp bp ep:|sp) (name,attrs) <-
+               p_Cell $ do
+                       void $ P.char '<'
+                       (,) <$> p_Name <*> p_ElemAttrs
        let treeHere =
-               Tree (Cell pos posClose $ NodeLower name attrs) .
-               Seq.singleton . Tree0 . (NodeText <$>)
-       let treeElem hasContent nod (Cell _ p t) =
+               Tree (Cell ssp $ NodeLower name attrs) .
+               Seq.singleton . tree0 . (NodeText <$>)
+       let treeElem hasContent nod (Cell (Span _fp _bp ep':|_sp) t) =
                let (o,_) = bs $ PairElem name attrs in
-               Tree0 $ Cell pos p $ nod $ o<>t
+               tree0 $ Cell (Span fp bp ep':|sp) $ nod $ o<>t
                where
-               bs | hasContent = pairBorders
-                  | otherwise  = pairBordersWithoutContent
-       tree <-
+               bs | hasContent = pairBordersDouble
+                  | otherwise  = pairBordersSingle
+       cel <-
                P.try (P.char '>' >> treeElem True NodeText <$> p_CellLinesUntilElemEnd indent name) <|>
                P.try (P.char '\n' >> P.tokens (==) indent >> treeHere <$> p_CellLines indent) <|>
                P.try (P.tokens (==) "/>" >> treeElem False NodeText <$> p_CellLine) <|>
-               (P.eof $> treeHere (Cell posClose posClose ""))
-       return $ tree : row
+               (P.eof $> treeHere (Cell (Span fp ep ep:|sp) ""))
+       return $ cel : row
        where
        p_CellLine :: P.Tokens s ~ TL.Text => Parser e s (Cell TL.Text)
        p_CellLine = p_Cell p_Line
@@ -149,41 +140,42 @@ p_CellLower row = pdbg "CellLower" $ do
                                 >> P.tokens (==) indent
                                 >> go (l:ls))
 
-p_CellText :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
-p_CellText row = pdbg "CellText" $ do
+p_CellText1 :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
+p_CellText1 row = debugParser "CellText" $ do
        P.skipMany $ P.char ' '
        n <- p_Cell $ NodeText <$> p_Line1
-       return $ Tree0 n : row
+       return $ tree0 n : row
 
-p_CellSpaces :: Row -> Parser e s Row
-p_CellSpaces row = pdbg "CellSpaces" $ do
+p_CellRaw :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
+p_CellRaw row = debugParser "CellRaw" $ do
+       P.skipMany $ P.char ' '
+       n <- p_Cell $ NodeText <$> p_Line
+       return $ tree0 n : row
+
+p_CellSpaces1 :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
+p_CellSpaces1 row = debugParser "CellSpaces" $ do
        P.skipSome $ P.char ' '
-       pos <- p_Position
-       return $ Tree0 (Cell pos pos $ NodeText "") : row
+       cell <- p_Cell $ NodeText <$> P.string ""
+       return $ tree0 cell : row
 
 p_CellEnd :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
-p_CellEnd row = pdbg "CellEnd" $
+p_CellEnd row = debugParser "CellEnd" $
        P.try (p_CellLower row) <|>
-       P.try (p_CellText row) <|>
-       p_CellSpaces row <|>
+       P.try (p_CellText1 row) <|>
+       p_CellSpaces1 row <|>
        return row
 
 p_Row :: P.Tokens s ~ TL.Text => Row -> Parser e s Row
-p_Row row = pdbg "Row" $
+p_Row row = debugParser "Row" $
        P.try (p_CellHeader row) <|>
        p_CellEnd row
 
 p_Rows :: P.Tokens s ~ TL.Text => Rows -> Parser e s Rows
 p_Rows rows =
        p_Row [] >>= \row ->
-               let rows' = appendRow rows (List.reverse row) in
+               let rows' = rows `mergeRow` row in
                (P.eof $> rows') <|>
-               (P.newline >> P.eof $> rows' <|> p_Rows rows')
+               (P.newline >> {- USELESS: P.eof $> rows' <|>-} p_Rows rows')
 
 p_Trees :: P.Tokens s ~ TL.Text => Parser e s (Trees (Cell Node))
-p_Trees = unNodePara . subTrees . collapseRows <$> p_Rows [root]
-       where
-       root = Tree (cell0 $ NodeHeader HeaderDashDash) mempty
-       unNodePara :: Trees (Cell Node) -> Trees (Cell Node)
-       unNodePara (toList -> [(Tree (unCell -> NodePara) ts)]) = ts
-       unNodePara ts = ts
+p_Trees = collapseRows <$> p_Rows initRows