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.TCT hiding (Parser)
49 import qualified Language.DTC.Document as DTC
50 import qualified Language.DTC.Sym as DTC
51 import qualified Language.RNC.Sym as RNC
54 -- type Parser = P.Parsec Error XMLs
55 type Parser = S.StateT XmlPos (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 )
76 ts <- P.token check $ Just expected
79 { xmlPosAncestors = (n,maybe 1 (+1) $ Map.lookup n $ xmlPosPrecedingsSiblings xp):xmlPosAncestors xp
80 , xmlPosPrecedingsSiblings = mempty
82 parserXMLs p ts <* S.put xp
83 { xmlPosPrecedingsSiblings =
84 Map.insertWith (\_new old -> old + 1) n 1 $
85 xmlPosPrecedingsSiblings xp
88 expected = TreeN (cell0 n) mempty
89 check (TreeN (unCell -> e) ts) | e == n = Right ts
91 ( Just $ P.Tokens $ pure t
92 , Set.singleton $ P.Tokens $ pure expected )
94 v <- P.token check $ Just expected
97 expected = Tree0 (cell0 $ XmlAttr n "")
98 check (TreeN (unCell -> e) ts) | e == n = Right ts
99 check (Tree0 (Cell bp ep (XmlAttr k v))) | k == n =
100 Right $ Seq.singleton $ Tree0 $ Cell bp ep $ XmlText v
102 ( Just $ P.Tokens $ pure t
103 , Set.singleton $ P.Tokens $ pure expected )
107 Tree0 (unCell -> XmlComment c) :< ts -> do
110 t :< _ts -> P.failure (Just $ P.Tokens $ pure t) ex
111 EmptyL -> P.failure Nothing ex
113 ex = Set.singleton $ P.Tokens $ pure expected
114 expected = Tree0 (cell0 $ XmlComment "")
116 P.token check (Just expected)
119 expected = Tree0 (cell0 $ XmlText "")
120 check (Tree0 (unCell -> XmlText t)) = Right t
122 ( Just $ P.Tokens $ pure t
123 , Set.singleton $ P.Tokens $ pure expected )
124 int = RNC.rule "int" $ RNC.text >>= \t ->
125 case readMaybe (Text.unpack t) of
127 Nothing -> P.fancyFailure $
128 Set.singleton $ P.ErrorCustom $ Error_Not_Int t
129 nat = RNC.rule "nat" $ RNC.int >>= \i ->
132 else P.fancyFailure $ Set.singleton $
133 P.ErrorCustom $ Error_Not_Nat i
134 nat1 = RNC.rule "nat1" $ RNC.int >>= \i ->
137 else P.fancyFailure $ Set.singleton $
138 P.ErrorCustom $ Error_Not_Nat1 i
142 optional = P.optional
146 type instance RNC.Perm Parser = P.PermParser XMLs Parser
147 instance RNC.Sym_Interleaved Parser where
148 interleaved = P.makePermParser
153 f <$*> a = f P.<$?> ([],P.some a)
154 f <|*> a = f P.<|?> ([],P.some a)
155 instance DTC.Sym_DTC Parser
158 DTC.Sym_DTC Parser =>
160 Either (P.ParseError (P.Token XMLs) Error) DTC.Document
163 XmlPos { xmlPosAncestors = []
164 , xmlPosPrecedingsSiblings = mempty
170 DTC.Sym_DTC Parser =>
172 P.SourcePos -> Parser a -> XMLs ->
173 Either (P.ParseError (P.Token XMLs) Error) a
174 parseXMLs xp pos p i =
176 P.runParser' ((`S.evalStateT` xp) $ p <* RNC.none)
179 , P.statePos = pure $
181 Tree0 c :< _ -> sourcePosCell c
182 TreeN c _ :< _ -> sourcePosCell c
184 , P.stateTabWidth = P.pos1
185 , P.stateTokensProcessed = 0
188 -- | @parserXMLs xp pos p xs@ returns a 'Parser' parsing @xs@ with @p@ from position @xp@.
190 DTC.Sym_DTC Parser =>
191 Parser a -> XMLs -> Parser a
195 case parseXMLs xp pos p xs of
196 Left (P.TrivialError (posErr:|_) un ex) -> do
199 Left (P.FancyError (posErr:|_) errs) -> do
202 Right a -> a <$ fixPos
204 -- | Adjust the current 'P.SourcePos'
205 -- to be the begining of the following-sibling 'XML' node
206 -- so that on error 'P.toHints' keeps expected 'P.Token's in the list,
207 -- and thus makes useful error messages.
209 -- This is needed because the end of a 'Cell'
210 -- is not necessarily the begin of the next 'Cell'.
215 , P.statePos = pos :| _
216 } <- P.getParserState
217 case Seq.viewl inp of
219 t :< _ -> P.setPosition $
220 P.positionAt1 (Proxy::Proxy XMLs) pos t
222 sourcePosCell :: Cell a -> P.SourcePos
225 (P.mkPos $ lineCell c)
226 (P.mkPos $ columnCell c)
228 sourcePos :: Pos -> Maybe P.SourcePos
229 sourcePos (Pos l c) | l>0 && c>0 = Just $ P.SourcePos "" (P.mkPos l) (P.mkPos c)
230 sourcePos _ = Nothing
232 instance P.Stream XMLs where
233 type Token XMLs = XML
234 type Tokens XMLs = XMLs
237 Tree0 (unCell -> XmlComment{}) :< ts -> P.take1_ ts
240 positionAt1 _s pos t =
241 fromMaybe pos $ sourcePos $
243 TreeN c _ -> posCell c
245 positionAtN s pos ts =
247 t :< _ -> P.positionAt1 s pos t
249 advance1 _s _indent pos t =
250 -- WARNING: the end of a 'Cell' is not necessarily
251 -- the beginning of the next 'Cell'.
252 fromMaybe pos $ sourcePos $
254 TreeN c _ -> posEndCell c
255 Tree0 c -> posEndCell c
256 advanceN s = foldl' . P.advance1 s
258 | n <= 0 = Just (mempty, s)
260 | otherwise = Just (Seq.splitAt n s) -- FIXME: handle XmlComment
261 tokensToChunk _s = Seq.fromList
262 chunkToTokens _s = toList
263 chunkLength _s = Seq.length
264 takeWhile_ = Seq.spanl
265 instance P.ShowToken XML where
266 showTokens toks = List.intercalate ", " $ toList $ showTree <$> toks
268 showTree :: XML -> String
270 Tree0 c -> showCell c showXmlLeaf
271 TreeN c _ts -> showCell c showXmlName
273 showCell (Cell (Pos 0 0) (Pos 0 0) a) f = f a
274 showCell (Cell bp ep a) f = f a<>" at "<>show bp<>"-"<>show ep
277 XmlAttr n _v -> show n<>"="
279 XmlComment _c -> "comment"
280 showXmlName n = "<"<>show n<>">"
288 -- | Error_Unexpected P.sourcePos XML
289 deriving (Eq,Ord,Show)
290 instance P.ShowErrorComponent Error where
291 showErrorComponent = show