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.Either (Either(..))
16 import Data.Eq (Eq(..))
17 import Data.Foldable (null, foldl')
18 import Data.Function (($), (.), const, id)
19 import Data.Functor ((<$>), (<$))
21 import Data.List.NonEmpty (NonEmpty(..))
22 import Data.Maybe (Maybe(..), fromMaybe, maybe)
23 import Data.Monoid (Monoid(..))
24 import Data.Ord (Ord(..))
25 import Data.Proxy (Proxy(..))
26 import Data.Semigroup (Semigroup(..))
27 import Data.Sequence (ViewL(..))
28 import Data.String (String)
29 import Data.Text (Text)
30 import Data.Tuple (snd)
31 import GHC.Exts (toList)
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
51 -- type Parser = P.Parsec Error XMLs
52 type Parser = S.StateT XmlPos (P.Parsec Error XMLs)
54 instance RNC.Sym_Rule Parser where
55 -- rule n p = P.dbg s p {-(p P.<?> s)-} where s = Text.unpack n
57 instance RNC.Sym_RNC Parser where
58 none = P.label "none" $ P.eof
59 any = P.label "any" $ p_satisfyMaybe $ const $ Just ()
60 anyElem p = P.label "anyElem" $ do
61 (n,ts) <- P.token check $ Just expected
64 expected = TreeN (cell0 "") mempty
65 check (TreeN (unCell -> n) ts) = Right (n,ts)
67 ( Just $ P.Tokens $ pure t
68 , Set.singleton $ P.Tokens $ pure expected )
71 ts <- P.token check $ Just expected
74 { xmlPosAncestors = (n,maybe 1 (+1) $ Map.lookup n $ xmlPosPrecedingsSiblings xp):xmlPosAncestors xp
75 , xmlPosPrecedingsSiblings = mempty
77 parserXMLs p ts <* S.put xp
78 { xmlPosPrecedingsSiblings =
79 Map.insertWith (\_new old -> old + 1) n 1 $
80 xmlPosPrecedingsSiblings xp
83 expected = TreeN (cell0 n) mempty
84 check (TreeN (unCell -> e) ts) | e == n = Right ts
86 ( Just $ P.Tokens $ pure t
87 , Set.singleton $ P.Tokens $ pure expected )
89 v <- P.token check $ Just expected
92 expected = Tree0 (cell0 $ XmlAttr n "")
93 check (TreeN (unCell -> e) ts) | e == n = Right ts
94 check (Tree0 (Cell bp ep (XmlAttr k v))) | k == n =
95 Right $ Seq.singleton $ Tree0 $ Cell bp ep $ XmlText v
97 ( Just $ P.Tokens $ pure t
98 , Set.singleton $ P.Tokens $ pure expected )
102 Tree0 (unCell -> XmlComment c) :< ts -> do
105 t :< _ts -> P.failure (Just $ P.Tokens $ pure t) ex
106 EmptyL -> P.failure Nothing ex
108 ex = Set.singleton $ P.Tokens $ pure expected
109 expected = Tree0 (cell0 $ XmlComment "")
111 P.token check (Just expected)
114 expected = Tree0 (cell0 $ XmlText "")
115 check (Tree0 (unCell -> XmlText t)) = Right t
117 ( Just $ P.Tokens $ pure t
118 , Set.singleton $ P.Tokens $ pure expected )
119 int = RNC.rule "int" $ RNC.text >>= \t ->
120 case readMaybe (Text.unpack t) of
122 Nothing -> P.fancyFailure $
123 Set.singleton $ P.ErrorCustom $ Error_Not_Int t
124 nat = RNC.rule "nat" $ RNC.int >>= \i ->
127 else P.fancyFailure $ Set.singleton $
128 P.ErrorCustom $ Error_Not_Nat i
129 nat1 = RNC.rule "nat1" $ RNC.int >>= \i ->
132 else P.fancyFailure $ Set.singleton $
133 P.ErrorCustom $ Error_Not_Nat1 i
137 optional = P.optional
141 type instance RNC.Perm Parser = P.PermParser XMLs Parser
142 instance RNC.Sym_Interleaved Parser where
143 interleaved = P.makePermParser
148 f <$*> a = f P.<$?> ([],P.some a)
149 f <|*> a = f P.<|?> ([],P.some a)
150 instance DTC.Sym_DTC Parser
153 DTC.Sym_DTC Parser =>
155 Either (P.ParseError (P.Token XMLs) Error) DTC.Document
158 XmlPos { xmlPosAncestors = []
159 , xmlPosPrecedingsSiblings = mempty
165 DTC.Sym_DTC Parser =>
167 P.SourcePos -> Parser a -> XMLs ->
168 Either (P.ParseError (P.Token XMLs) Error) a
169 parseXMLs xp pos p i =
171 P.runParser' ((`S.evalStateT` xp) $ p <* RNC.none)
174 , P.statePos = pure $
176 Tree0 c :< _ -> sourcePosCell c
177 TreeN c _ :< _ -> sourcePosCell c
179 , P.stateTabWidth = P.pos1
180 , P.stateTokensProcessed = 0
183 -- | @parserXMLs xp pos p xs@ returns a 'Parser' parsing @xs@ with @p@ from position @xp@.
185 DTC.Sym_DTC Parser =>
186 Parser a -> XMLs -> Parser a
190 case parseXMLs xp pos p xs of
191 Left (P.TrivialError (posErr:|_) un ex) -> do
194 Left (P.FancyError (posErr:|_) errs) -> do
197 Right a -> a <$ fixPos
199 -- | Adjust the current 'P.SourcePos'
200 -- to be the begining of the following-sibling 'XML' node
201 -- so that on error 'P.toHints' keeps expected 'P.Token's in the list,
202 -- and thus makes useful error messages.
204 -- This is needed because the end of a 'Cell'
205 -- is not necessarily the begin of the next 'Cell'.
210 , P.statePos = pos :| _
211 } <- P.getParserState
212 case Seq.viewl inp of
214 t :< _ -> P.setPosition $
215 P.positionAt1 (Proxy::Proxy XMLs) pos t
217 sourcePosCell :: Cell a -> P.SourcePos
220 (P.mkPos $ lineCell c)
221 (P.mkPos $ columnCell c)
223 sourcePos :: Pos -> Maybe P.SourcePos
224 sourcePos (Pos l c) | l>0 && c>0 = Just $ P.SourcePos "" (P.mkPos l) (P.mkPos c)
225 sourcePos _ = Nothing
227 instance P.Stream XMLs where
228 type Token XMLs = XML
229 type Tokens XMLs = XMLs
232 Tree0 (unCell -> XmlComment{}) :< ts -> P.take1_ ts
235 positionAt1 _s pos t =
236 fromMaybe pos $ sourcePos $
238 TreeN c _ -> posCell c
240 positionAtN s pos ts =
242 t :< _ -> P.positionAt1 s pos t
244 advance1 _s _indent pos t =
245 -- WARNING: the end of a 'Cell' is not necessarily
246 -- the beginning of the next 'Cell'.
247 fromMaybe pos $ sourcePos $
249 TreeN c _ -> posEndCell c
250 Tree0 c -> posEndCell c
251 advanceN s = foldl' . P.advance1 s
253 | n <= 0 = Just (mempty, s)
255 | otherwise = Just (Seq.splitAt n s) -- FIXME: handle XmlComment
256 tokensToChunk _s = Seq.fromList
257 chunkToTokens _s = toList
258 chunkLength _s = Seq.length
259 takeWhile_ = Seq.spanl
260 instance P.ShowToken XML where
261 showTokens toks = List.intercalate ", " $ toList $ showTree <$> toks
263 showTree :: XML -> String
265 Tree0 c -> showCell c showXmlLeaf
266 TreeN c _ts -> showCell c showXmlName
268 showCell (Cell (Pos 0 0) (Pos 0 0) a) f = f a
269 showCell (Cell bp ep a) f = f a<>" at "<>show bp<>"-"<>show ep
272 XmlAttr n _v -> show n<>"="
274 XmlComment _c -> "comment"
275 showXmlName n = "<"<>show n<>">"
283 -- | Error_Unexpected P.sourcePos XML
284 deriving (Eq,Ord,Show)
285 instance P.ShowErrorComponent Error where
286 showErrorComponent = show