1 {-# LANGUAGE BangPatterns #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# LANGUAGE ScopedTypeVariables #-}
6 {-# LANGUAGE TypeFamilies #-}
7 {-# LANGUAGE ViewPatterns #-}
8 {-# OPTIONS_GHC -fno-warn-orphans #-}
9 -- | Read DTC from TCT.
10 module Language.DTC.Read.TCT where
12 import Control.Applicative (Applicative(..))
13 import Control.Monad (Monad(..))
15 import Data.Default.Class (Default(..))
16 import Data.Either (Either(..))
17 import Data.Eq (Eq(..))
18 import Data.Foldable (Foldable(..))
19 import Data.Function (($), (.), const, id)
20 import Data.Functor ((<$>), (<$))
22 import Data.List.NonEmpty (NonEmpty(..))
23 import Data.Maybe (Maybe(..), fromMaybe, maybe)
24 import Data.Monoid (Monoid(..), First(..))
25 import Data.Ord (Ord(..))
26 import Data.Proxy (Proxy(..))
27 import Data.Semigroup (Semigroup(..))
28 import Data.Sequence (ViewL(..), (|>))
29 import Data.String (String)
30 import Data.Text (Text)
31 import Data.Tuple (snd)
32 import Prelude (Num(..))
33 import Text.Read (readMaybe)
34 import Text.Show (Show(..))
35 import qualified Control.Monad.Trans.State as S
36 import qualified Data.List as List
37 import qualified Data.Map.Strict as Map
38 import qualified Data.Sequence as Seq
39 import qualified Data.Set as Set
40 import qualified Data.Text as Text
41 import qualified Text.Megaparsec as P
42 import qualified Text.Megaparsec.Perm as P
44 import Language.TCT hiding (Parser)
46 import qualified Language.DTC.Document as DTC
47 import qualified Language.DTC.Sym as DTC
48 import qualified Language.RNC.Sym as RNC
54 -- type Parser = P.Parsec Error XMLs
55 type Parser = S.StateT State (P.Parsec Error XMLs)
57 instance RNC.Sym_Rule Parser where
58 -- rule n p = P.dbg s p {-(p P.<?> s)-} where s = Text.unpack n
60 instance RNC.Sym_RNC Parser where
61 none = P.label "none" $ P.eof
62 any = P.label "any" $ p_satisfyMaybe $ const $ Just ()
63 anyElem p = P.label "anyElem" $ do
64 (n,ts) <- P.token check $ Just expected
67 expected = TreeN (cell0 "") mempty
68 check (TreeN (unCell -> n) ts) = Right (n,ts)
70 ( Just $ P.Tokens $ pure t
71 , Set.singleton $ P.Tokens $ pure expected )
73 ts <- P.token check $ Just expected
77 -- NOTE: special case renaming the current DTC.Pos
78 -- using the @type attribute to have positions like this:
86 , Just ty <- getFirst $ (`foldMap` ts) $ \case
87 Tree0 (unCell -> XmlAttr "type" ty) -> First $ Just ty
91 let anc name = maybe 1 (+1) $ Map.lookup name $ DTC.posPrecedingsSiblings xp
93 { DTC.posAncestors = DTC.posAncestors xp |> (n,anc n)
94 , DTC.posAncestorsWithFigureNames =
95 DTC.posAncestorsWithFigureNames xp |>
96 (nameOrFigureName,anc nameOrFigureName)
97 , DTC.posPrecedingsSiblings = mempty
99 parserXMLs p ts <* S.put xp
100 { DTC.posPrecedingsSiblings=
101 (if n /= nameOrFigureName
102 then Map.insertWith (\_new old -> old + 1) nameOrFigureName 1
104 Map.insertWith (\_new old -> old + 1) n 1 $
105 DTC.posPrecedingsSiblings xp
108 expected = TreeN (cell0 n) mempty
109 check (TreeN (unCell -> e) ts) | e == n = Right ts
111 ( Just $ P.Tokens $ pure t
112 , Set.singleton $ P.Tokens $ pure expected )
114 v <- P.token check $ Just expected
117 expected = Tree0 (cell0 $ XmlAttr n "")
118 check (TreeN (unCell -> e) ts) | e == n = Right ts
119 check (Tree0 (Cell bp ep (XmlAttr k v))) | k == n =
120 Right $ Seq.singleton $ Tree0 $ Cell bp ep $ XmlText v
122 ( Just $ P.Tokens $ pure t
123 , Set.singleton $ P.Tokens $ pure expected )
127 Tree0 (unCell -> XmlComment c) :< ts -> do
130 t :< _ts -> P.failure (Just $ P.Tokens $ pure t) ex
131 EmptyL -> P.failure Nothing ex
133 ex = Set.singleton $ P.Tokens $ pure expected
134 expected = Tree0 (cell0 $ XmlComment "")
136 P.token check (Just expected)
139 expected = Tree0 (cell0 $ XmlText "")
140 check (Tree0 (unCell -> XmlText t)) = Right t
142 ( Just $ P.Tokens $ pure t
143 , Set.singleton $ P.Tokens $ pure expected )
144 int = RNC.rule "int" $ RNC.text >>= \t ->
145 case readMaybe (Text.unpack t) of
147 Nothing -> P.fancyFailure $
148 Set.singleton $ P.ErrorCustom $ Error_Not_Int t
149 nat = RNC.rule "nat" $ RNC.int >>= \i ->
152 else P.fancyFailure $ Set.singleton $
153 P.ErrorCustom $ Error_Not_Nat i
154 nat1 = RNC.rule "nat1" $ RNC.int >>= \i ->
157 else P.fancyFailure $ Set.singleton $
158 P.ErrorCustom $ Error_Not_Nat1 i
162 optional = P.optional
166 type instance RNC.Perm Parser = P.PermParser XMLs Parser
167 instance RNC.Sym_Interleaved Parser where
168 interleaved = P.makePermParser
173 f <$*> a = f P.<$?> ([],P.some a)
174 f <|*> a = f P.<|?> ([],P.some a)
175 instance DTC.Sym_DTC Parser where
179 DTC.Sym_DTC Parser =>
181 Either (P.ParseError (P.Token XMLs) Error) DTC.Document
182 readDTC = parseXMLs def (P.initialPos "") DTC.document
185 DTC.Sym_DTC Parser =>
187 P.SourcePos -> Parser a -> XMLs ->
188 Either (P.ParseError (P.Token XMLs) Error) a
189 parseXMLs st pos p i =
191 P.runParser' ((`S.evalStateT` st) $ p <* RNC.none)
194 , P.statePos = pure $
196 Tree0 c :< _ -> sourcePosCell c
197 TreeN c _ :< _ -> sourcePosCell c
199 , P.stateTabWidth = P.pos1
200 , P.stateTokensProcessed = 0
203 -- | @parserXMLs st pos p xs@ returns a 'Parser' parsing @xs@ with @p@ from state @st@.
205 DTC.Sym_DTC Parser =>
206 Parser a -> XMLs -> Parser a
210 case parseXMLs st pos p xs of
211 Left (P.TrivialError (posErr:|_) un ex) -> do
214 Left (P.FancyError (posErr:|_) errs) -> do
217 Right a -> a <$ fixPos
219 -- | Adjust the current 'P.SourcePos'
220 -- to be the begining of the following-sibling 'XML' node
221 -- so that on error 'P.toHints' keeps expected 'P.Token's in the list,
222 -- and thus makes useful error messages.
224 -- This is needed because the end of a 'Cell'
225 -- is not necessarily the begin of the next 'Cell'.
230 , P.statePos = pos :| _
231 } <- P.getParserState
232 case Seq.viewl inp of
234 t :< _ -> P.setPosition $
235 P.positionAt1 (Proxy::Proxy XMLs) pos t
237 sourcePosCell :: Cell a -> P.SourcePos
240 (P.mkPos $ lineCell c)
241 (P.mkPos $ columnCell c)
243 sourcePos :: Pos -> Maybe P.SourcePos
244 sourcePos (Pos l c) | l>0 && c>0 = Just $ P.SourcePos "" (P.mkPos l) (P.mkPos c)
245 sourcePos _ = Nothing
247 instance P.Stream XMLs where
248 type Token XMLs = XML
249 type Tokens XMLs = XMLs
252 Tree0 (unCell -> XmlComment{}) :< ts -> P.take1_ ts
255 positionAt1 _s pos t =
256 fromMaybe pos $ sourcePos $
258 TreeN c _ -> posCell c
260 positionAtN s pos ts =
262 t :< _ -> P.positionAt1 s pos t
264 advance1 _s _indent pos t =
265 -- WARNING: the end of a 'Cell' is not necessarily
266 -- the beginning of the next 'Cell'.
267 fromMaybe pos $ sourcePos $
269 TreeN c _ -> posEndCell c
270 Tree0 c -> posEndCell c
271 advanceN s = foldl' . P.advance1 s
273 | n <= 0 = Just (mempty, s)
275 | otherwise = Just (Seq.splitAt n s) -- FIXME: handle XmlComment
276 tokensToChunk _s = Seq.fromList
277 chunkToTokens _s = toList
278 chunkLength _s = Seq.length
279 takeWhile_ = Seq.spanl
280 instance P.ShowToken XML where
281 showTokens toks = List.intercalate ", " $ toList $ showTree <$> toks
283 showTree :: XML -> String
285 Tree0 c -> showCell c showXmlLeaf
286 TreeN c _ts -> showCell c showXmlName
288 showCell (Cell (Pos 0 0) (Pos 0 0) a) f = f a
289 showCell (Cell bp ep a) f = f a<>" at "<>show bp<>"-"<>show ep
292 XmlAttr n _v -> show n<>"="
294 XmlComment _c -> "comment"
295 showXmlName n = "<"<>show n<>">"
303 -- | Error_Unexpected P.sourcePos XML
304 deriving (Eq,Ord,Show)
305 instance P.ShowErrorComponent Error where
306 showErrorComponent = show