1 {-# LANGUAGE BangPatterns #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# LANGUAGE RecordWildCards #-}
6 {-# LANGUAGE ScopedTypeVariables #-}
7 {-# LANGUAGE TypeFamilies #-}
8 {-# LANGUAGE ViewPatterns #-}
9 {-# OPTIONS_GHC -fno-warn-orphans #-}
10 -- | Read DTC from TCT.
11 module Language.DTC.Read.TCT where
13 -- import Control.Monad.Trans.Class (MonadTrans(..))
14 -- import qualified Control.Monad.Trans.Reader as R
15 import Control.Applicative (Applicative(..))
16 import Control.Monad (Monad(..))
18 import Data.Either (Either(..))
19 import Data.Eq (Eq(..))
20 import Data.Foldable (null, foldl')
21 import Data.Function (($), (.), const, id)
22 import Data.Functor ((<$>), (<$))
24 import Data.List.NonEmpty (NonEmpty(..))
25 import Data.Maybe (Maybe(..), fromMaybe, maybe)
26 import Data.Monoid (Monoid(..))
27 import Data.Ord (Ord(..))
28 import Data.Proxy (Proxy(..))
29 import Data.Semigroup (Semigroup(..))
30 import Data.Sequence (ViewL(..))
31 import Data.String (String)
32 import Data.Text (Text)
33 import Data.Tuple (snd)
34 import GHC.Exts (toList)
35 import Prelude (Num(..))
36 import Text.Read (readMaybe)
37 import Text.Show (Show(..))
38 import qualified Control.Monad.Trans.State as S
39 import qualified Data.List as List
40 import qualified Data.Map.Strict as Map
41 import qualified Data.Sequence as Seq
42 import qualified Data.Set as Set
43 import qualified Data.Text as Text
44 import qualified Text.Megaparsec as P
45 import qualified Text.Megaparsec.Perm as P
47 import Language.DTC.Document (Nat(..), Nat1(..))
48 import Language.TCT hiding (Parser)
49 import Language.TCT.Write.XML (XML,XMLs,XmlLeaf(..),XmlPos(..))
50 import qualified Language.DTC.Document as DTC
51 import qualified Language.DTC.Sym as DTC
52 import qualified Language.RNC.Sym as RNC
53 import qualified Language.TCT.Write.XML as XML
56 -- type Parser = P.Parsec Error XMLs
57 type Parser = S.StateT XmlPos (P.Parsec Error XMLs)
59 instance RNC.Sym_Rule Parser where
60 -- rule n p = P.dbg s p {-(p P.<?> s)-} where s = Text.unpack n
62 instance RNC.Sym_RNC Parser where
63 none = P.label "none" $ P.eof
64 any = P.label "any" $ p_satisfyMaybe $ const $ Just ()
65 anyElem p = P.label "anyElem" $ do
66 (n,ts) <- P.token check $ Just expected
69 expected = TreeN (cell0 "") mempty
70 check (TreeN (unCell -> n) ts) = Right (n,ts)
72 ( Just $ P.Tokens $ pure t
73 , Set.singleton $ P.Tokens $ pure expected )
78 ts <- P.token check $ Just expected
81 { xmlPosAncestors = (n,maybe 1 (+1) $ Map.lookup n $ xmlPosPrecedingsSiblings xp):xmlPosAncestors xp
82 , xmlPosPrecedingsSiblings = mempty
84 parserXMLs p ts <* S.put xp
85 { xmlPosPrecedingsSiblings =
86 Map.insertWith (\_new old -> old + 1) n 1 $
87 xmlPosPrecedingsSiblings xp
90 expected = TreeN (cell0 n) mempty
91 check (TreeN (unCell -> e) ts) | e == n = Right ts
93 ( Just $ P.Tokens $ pure t
94 , Set.singleton $ P.Tokens $ pure expected )
96 v <- P.token check $ Just expected
99 expected = Tree0 (cell0 $ XML.XmlAttr n "")
100 check (TreeN (unCell -> e) ts) | e == n = Right ts
101 check (Tree0 (Cell bp ep (XML.XmlAttr k v))) | k == n =
102 Right $ Seq.singleton $ Tree0 $ Cell bp ep $ XML.XmlText v
104 ( Just $ P.Tokens $ pure t
105 , Set.singleton $ P.Tokens $ pure expected )
109 Tree0 (unCell -> XmlComment c) :< ts -> do
112 t :< _ts -> P.failure (Just $ P.Tokens $ pure t) ex
113 EmptyL -> P.failure Nothing ex
115 ex = Set.singleton $ P.Tokens $ pure expected
116 expected = Tree0 (cell0 $ XML.XmlComment "")
118 P.token check (Just expected)
121 expected = Tree0 (cell0 $ XML.XmlText "")
122 check (Tree0 (unCell -> XML.XmlText t)) = Right t
124 ( Just $ P.Tokens $ pure t
125 , Set.singleton $ P.Tokens $ pure expected )
126 int = RNC.rule "int" $ RNC.text >>= \t ->
127 case readMaybe (Text.unpack t) of
129 Nothing -> P.fancyFailure $
130 Set.singleton $ P.ErrorCustom $ Error_Not_Int t
131 nat = RNC.rule "nat" $ RNC.int >>= \i ->
134 else P.fancyFailure $ Set.singleton $
135 P.ErrorCustom $ Error_Not_Nat i
136 nat1 = RNC.rule "nat1" $ RNC.int >>= \i ->
139 else P.fancyFailure $ Set.singleton $
140 P.ErrorCustom $ Error_Not_Nat1 i
144 optional = P.optional
148 type instance RNC.Perm Parser = P.PermParser XMLs Parser
149 instance RNC.Sym_Interleaved Parser where
150 interleaved = P.makePermParser
155 f <$*> a = f P.<$?> ([],P.some a)
156 f <|*> a = f P.<|?> ([],P.some a)
157 instance DTC.Sym_DTC Parser
160 DTC.Sym_DTC Parser =>
162 Either (P.ParseError (P.Token XMLs) Error) DTC.Document
165 XmlPos { xmlPosAncestors = []
166 , xmlPosPrecedingsSiblings = mempty
172 DTC.Sym_DTC Parser =>
174 P.SourcePos -> Parser a -> XMLs ->
175 Either (P.ParseError (P.Token XMLs) Error) a
176 parseXMLs xp pos p i =
178 P.runParser' ((`S.evalStateT` xp) $ p <* RNC.none)
181 , P.statePos = pure $
183 Tree0 c :< _ -> sourcePosCell c
184 TreeN c _ :< _ -> sourcePosCell c
186 , P.stateTabWidth = P.pos1
187 , P.stateTokensProcessed = 0
190 -- | @parserXMLs xp pos p xs@ returns a 'Parser' parsing @xs@ with @p@ from position @xp@.
192 DTC.Sym_DTC Parser =>
193 Parser a -> XMLs -> Parser a
197 case parseXMLs xp pos p xs of
198 Left (P.TrivialError (posErr:|_) un ex) -> do
201 Left (P.FancyError (posErr:|_) errs) -> do
204 Right a -> a <$ fixPos
206 -- | Adjust the current 'P.SourcePos'
207 -- to be the begining of the following-sibling 'XML' node
208 -- so that on error 'P.toHints' keeps expected 'P.Token's in the list,
209 -- and thus makes useful error messages.
211 -- This is needed because the end of a 'Cell'
212 -- is not necessarily the begin of the next 'Cell'.
217 , P.statePos = pos :| _
218 } <- P.getParserState
219 case Seq.viewl inp of
221 t :< _ -> P.setPosition $
222 P.positionAt1 (Proxy::Proxy XMLs) pos t
224 sourcePosCell :: Cell a -> P.SourcePos
227 (P.mkPos $ lineCell c)
228 (P.mkPos $ columnCell c)
230 sourcePos :: Pos -> Maybe P.SourcePos
231 sourcePos (Pos l c) | l>0 && c>0 = Just $ P.SourcePos "" (P.mkPos l) (P.mkPos c)
232 sourcePos _ = Nothing
234 instance P.Stream XMLs where
235 type Token XMLs = XML
236 type Tokens XMLs = XMLs
239 Tree0 (unCell -> XmlComment{}) :< ts -> P.take1_ ts
242 positionAt1 _s pos t =
243 fromMaybe pos $ sourcePos $
245 TreeN c _ -> posCell c
247 positionAtN s pos ts =
249 t :< _ -> P.positionAt1 s pos t
251 advance1 _s _indent pos t =
252 -- WARNING: the end of a 'Cell' is not necessarily
253 -- the beginning of the next 'Cell'.
254 fromMaybe pos $ sourcePos $
256 TreeN c _ -> posEndCell c
257 Tree0 c -> posEndCell c
258 advanceN s = foldl' . P.advance1 s
260 | n <= 0 = Just (mempty, s)
262 | otherwise = Just (Seq.splitAt n s) -- FIXME: handle XmlComment
263 tokensToChunk _s = Seq.fromList
264 chunkToTokens _s = toList
265 chunkLength _s = Seq.length
266 takeWhile_ = Seq.spanl
267 instance P.ShowToken XML where
268 showTokens toks = List.intercalate ", " $ toList $ showTree <$> toks
270 showTree :: XML -> String
272 Tree0 c -> showCell c showXmlLeaf
273 TreeN c _ts -> showCell c showXmlName
275 showCell (Cell (Pos 0 0) (Pos 0 0) a) f = f a
276 showCell (Cell bp ep a) f = f a<>" at "<>show bp<>"-"<>show ep
279 XmlAttr n _v -> show n<>"="
281 XmlComment _c -> "comment"
282 showXmlName n = "<"<>show n<>">"
290 -- | Error_Unexpected P.sourcePos XML
291 deriving (Eq,Ord,Show)
292 instance P.ShowErrorComponent Error where
293 showErrorComponent = show