trifecta 0.52 → 0.53
raw patch · 127 files changed
+6050/−6081 lines, 127 filesdep −data-lensdep −data-lens-fddep ~bifunctorsdep ~bytestringdep ~charset
Dependencies removed: data-lens, data-lens-fd
Dependency ranges changed: bifunctors, bytestring, charset, comonad, keys, pointed, profunctors, reducers, semigroupoids, wl-pprint-extras, wl-pprint-terminfo
Files
- Text/Trifecta.hs +0/−30
- Text/Trifecta/Diagnostic.hs +0/−40
- Text/Trifecta/Diagnostic/Class.hs +0/−64
- Text/Trifecta/Diagnostic/Combinators.hs +0/−57
- Text/Trifecta/Diagnostic/Err.hs +0/−87
- Text/Trifecta/Diagnostic/Err/Log.hs +0/−43
- Text/Trifecta/Diagnostic/Err/State.hs +0/−42
- Text/Trifecta/Diagnostic/Level.hs +0/−66
- Text/Trifecta/Diagnostic/Prim.hs +0/−104
- Text/Trifecta/Diagnostic/Rendering.hs +0/−23
- Text/Trifecta/Diagnostic/Rendering/Caret.hs +0/−128
- Text/Trifecta/Diagnostic/Rendering/Fixit.hs +0/−63
- Text/Trifecta/Diagnostic/Rendering/Prim.hs +0/−240
- Text/Trifecta/Diagnostic/Rendering/Span.hs +0/−125
- Text/Trifecta/Highlight.hs +0/−22
- Text/Trifecta/Highlight/Class.hs +0/−19
- Text/Trifecta/Highlight/Effects.hs +0/−44
- Text/Trifecta/Highlight/Prim.hs +0/−47
- Text/Trifecta/Highlight/Rendering/HTML.hs +0/−48
- Text/Trifecta/IntervalMap.hs +0/−275
- Text/Trifecta/Language.hs +0/−34
- Text/Trifecta/Language/Class.hs +0/−59
- Text/Trifecta/Language/Combinators.hs +0/−42
- Text/Trifecta/Language/Monad.hs +0/−79
- Text/Trifecta/Language/Prim.hs +0/−28
- Text/Trifecta/Language/Style.hs +0/−26
- Text/Trifecta/Layout.hs +0/−23
- Text/Trifecta/Layout/Class.hs +0/−64
- Text/Trifecta/Layout/Combinators.hs +0/−67
- Text/Trifecta/Layout/Monad.hs +0/−112
- Text/Trifecta/Layout/Prim.hs +0/−86
- Text/Trifecta/Literate.hs +0/−23
- Text/Trifecta/Literate/Class.hs +0/−54
- Text/Trifecta/Literate/Combinators.hs +0/−85
- Text/Trifecta/Literate/Monad.hs +0/−94
- Text/Trifecta/Literate/Prim.hs +0/−60
- Text/Trifecta/Parser.hs +0/−47
- Text/Trifecta/Parser/ByteString.hs +0/−93
- Text/Trifecta/Parser/Char.hs +0/−204
- Text/Trifecta/Parser/Char8.hs +0/−213
- Text/Trifecta/Parser/Class.hs +0/−271
- Text/Trifecta/Parser/Combinators.hs +0/−207
- Text/Trifecta/Parser/Expr.hs +0/−167
- Text/Trifecta/Parser/Identifier.hs +0/−67
- Text/Trifecta/Parser/Identifier/Style.hs +0/−70
- Text/Trifecta/Parser/It.hs +0/−147
- Text/Trifecta/Parser/Mark.hs +0/−67
- Text/Trifecta/Parser/Perm.hs +0/−141
- Text/Trifecta/Parser/Prim.hs +0/−322
- Text/Trifecta/Parser/Result.hs +0/−82
- Text/Trifecta/Parser/Rich.hs +0/−26
- Text/Trifecta/Parser/Step.hs +0/−63
- Text/Trifecta/Parser/Token.hs +0/−24
- Text/Trifecta/Parser/Token/Combinators.hs +0/−197
- Text/Trifecta/Parser/Token/Prim.hs +0/−217
- Text/Trifecta/Parser/Token/Style.hs +0/−74
- Text/Trifecta/Rope.hs +0/−26
- Text/Trifecta/Rope/Bytes.hs +0/−27
- Text/Trifecta/Rope/Delta.hs +0/−169
- Text/Trifecta/Rope/Highlighted.hs +0/−98
- Text/Trifecta/Rope/Prim.hs +0/−114
- Text/Trifecta/Util/Array.hs +0/−378
- Text/Trifecta/Util/Combinators.hs +0/−52
- src/Text/Trifecta.hs +30/−0
- src/Text/Trifecta/Diagnostic.hs +40/−0
- src/Text/Trifecta/Diagnostic/Class.hs +64/−0
- src/Text/Trifecta/Diagnostic/Combinators.hs +57/−0
- src/Text/Trifecta/Diagnostic/Err.hs +87/−0
- src/Text/Trifecta/Diagnostic/Err/Log.hs +43/−0
- src/Text/Trifecta/Diagnostic/Err/State.hs +42/−0
- src/Text/Trifecta/Diagnostic/Level.hs +66/−0
- src/Text/Trifecta/Diagnostic/Prim.hs +102/−0
- src/Text/Trifecta/Diagnostic/Rendering.hs +23/−0
- src/Text/Trifecta/Diagnostic/Rendering/Caret.hs +117/−0
- src/Text/Trifecta/Diagnostic/Rendering/Fixit.hs +63/−0
- src/Text/Trifecta/Diagnostic/Rendering/Prim.hs +241/−0
- src/Text/Trifecta/Diagnostic/Rendering/Span.hs +107/−0
- src/Text/Trifecta/Highlight.hs +22/−0
- src/Text/Trifecta/Highlight/Class.hs +19/−0
- src/Text/Trifecta/Highlight/Effects.hs +44/−0
- src/Text/Trifecta/Highlight/Prim.hs +47/−0
- src/Text/Trifecta/Highlight/Rendering/HTML.hs +48/−0
- src/Text/Trifecta/IntervalMap.hs +275/−0
- src/Text/Trifecta/Language.hs +34/−0
- src/Text/Trifecta/Language/Class.hs +59/−0
- src/Text/Trifecta/Language/Combinators.hs +42/−0
- src/Text/Trifecta/Language/Monad.hs +79/−0
- src/Text/Trifecta/Language/Prim.hs +28/−0
- src/Text/Trifecta/Language/Style.hs +26/−0
- src/Text/Trifecta/Layout.hs +23/−0
- src/Text/Trifecta/Layout/Class.hs +64/−0
- src/Text/Trifecta/Layout/Combinators.hs +68/−0
- src/Text/Trifecta/Layout/Monad.hs +112/−0
- src/Text/Trifecta/Layout/Prim.hs +87/−0
- src/Text/Trifecta/Literate.hs +23/−0
- src/Text/Trifecta/Literate/Class.hs +54/−0
- src/Text/Trifecta/Literate/Combinators.hs +85/−0
- src/Text/Trifecta/Literate/Monad.hs +94/−0
- src/Text/Trifecta/Literate/Prim.hs +60/−0
- src/Text/Trifecta/Parser.hs +47/−0
- src/Text/Trifecta/Parser/ByteString.hs +93/−0
- src/Text/Trifecta/Parser/Char.hs +204/−0
- src/Text/Trifecta/Parser/Char8.hs +213/−0
- src/Text/Trifecta/Parser/Class.hs +271/−0
- src/Text/Trifecta/Parser/Combinators.hs +207/−0
- src/Text/Trifecta/Parser/Expr.hs +167/−0
- src/Text/Trifecta/Parser/Identifier.hs +67/−0
- src/Text/Trifecta/Parser/Identifier/Style.hs +70/−0
- src/Text/Trifecta/Parser/It.hs +144/−0
- src/Text/Trifecta/Parser/Mark.hs +67/−0
- src/Text/Trifecta/Parser/Perm.hs +141/−0
- src/Text/Trifecta/Parser/Prim.hs +322/−0
- src/Text/Trifecta/Parser/Result.hs +82/−0
- src/Text/Trifecta/Parser/Rich.hs +26/−0
- src/Text/Trifecta/Parser/Step.hs +63/−0
- src/Text/Trifecta/Parser/Token.hs +24/−0
- src/Text/Trifecta/Parser/Token/Combinators.hs +197/−0
- src/Text/Trifecta/Parser/Token/Prim.hs +217/−0
- src/Text/Trifecta/Parser/Token/Style.hs +74/−0
- src/Text/Trifecta/Rope.hs +26/−0
- src/Text/Trifecta/Rope/Bytes.hs +27/−0
- src/Text/Trifecta/Rope/Delta.hs +169/−0
- src/Text/Trifecta/Rope/Highlighted.hs +98/−0
- src/Text/Trifecta/Rope/Prim.hs +114/−0
- src/Text/Trifecta/Util/Array.hs +378/−0
- src/Text/Trifecta/Util/Combinators.hs +52/−0
- trifecta.cabal +15/−15
− Text/Trifecta.hs
@@ -1,30 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta- ( module Text.Trifecta.Diagnostic- , module Text.Trifecta.Highlight- , module Text.Trifecta.Language- , module Text.Trifecta.Layout- , module Text.Trifecta.Literate- , module Text.Trifecta.Parser- , module Text.Trifecta.Rope- , module System.Console.Terminfo.PrettyPrint- ) where--import Text.Trifecta.Diagnostic-import Text.Trifecta.Highlight-import Text.Trifecta.Language-import Text.Trifecta.Layout-import Text.Trifecta.Literate-import Text.Trifecta.Parser-import Text.Trifecta.Rope-import System.Console.Terminfo.PrettyPrint
− Text/Trifecta/Diagnostic.hs
@@ -1,40 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic - ( - -- * Diagnostics- Diagnostic(..)- -- * Rendering- , Renderable(..)- , Source- , rendering- , renderingCaret- , Caret(..), Careted(..)- , Span(..), Spanned(..)- , Fixit(..), Rendered(..)- -- * Emitting diagnostics- , MonadDiagnostic(..)- , panic, panicAt- , fatal, fatalAt- , err, errAt- , warn, warnAt- , note, noteAt- , verbose, verboseAt- -- * Diagnostic Levels- , DiagnosticLevel(..)- ) where--import Text.Trifecta.Diagnostic.Prim-import Text.Trifecta.Diagnostic.Class-import Text.Trifecta.Diagnostic.Combinators-import Text.Trifecta.Diagnostic.Level-import Text.Trifecta.Diagnostic.Rendering
− Text/Trifecta/Diagnostic/Class.hs
@@ -1,64 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies, FlexibleContexts, UndecidableInstances #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Class--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ Provides a class for logging and throwing expressive diagnostics.------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Class- ( MonadDiagnostic(..)- ) where--import Control.Monad.Trans.Class-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import Control.Monad.Trans.RWS.Lazy as Lazy-import Control.Monad.Trans.RWS.Strict as Strict-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Identity-import Data.Monoid-import Text.Trifecta.Diagnostic.Prim--class Monad m => MonadDiagnostic e m | m -> e where- throwDiagnostic :: Diagnostic e -> m a- logDiagnostic :: Diagnostic e -> m ()--instance MonadDiagnostic e m => MonadDiagnostic e (Lazy.StateT s m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance MonadDiagnostic e m => MonadDiagnostic e (Strict.StateT s m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance MonadDiagnostic e m => MonadDiagnostic e (ReaderT r m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.WriterT w m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.WriterT w m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.RWST r w s m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.RWST r w s m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance MonadDiagnostic e m => MonadDiagnostic e (IdentityT m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic
− Text/Trifecta/Diagnostic/Combinators.hs
@@ -1,57 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Combinators--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ Combinators for throwing and logging expressive diagnostics------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Combinators- ( panic, panicAt- , fatal, fatalAt- , err, errAt- , warn, warnAt- , note, noteAt- , verbose, verboseAt- ) where--import Control.Applicative-import Control.Monad.Instances ()-import Text.Trifecta.Parser.Class-import Text.Trifecta.Diagnostic.Class-import Text.Trifecta.Diagnostic.Prim-import Text.Trifecta.Diagnostic.Level-import Text.Trifecta.Diagnostic.Rendering.Prim-import Text.Trifecta.Diagnostic.Rendering.Caret-import Text.Trifecta.Rope.Delta--rendCaret :: MonadParser m => m Rendering-rendCaret = (delta >>= addCaret) <$> rend--panicAt, fatalAt, errAt :: MonadDiagnostic e m => [Diagnostic e] -> e -> Rendering -> m a-panicAt es e r = throwDiagnostic $ Diagnostic (Right r) Panic e es-fatalAt es e r = throwDiagnostic $ Diagnostic (Right r) Fatal e es-errAt es e r = throwDiagnostic $ Diagnostic (Right r) Error e es--panic, fatal, err :: (MonadParser m, MonadDiagnostic e m) => [Diagnostic e] -> e -> m a-panic es e = rendCaret >>= panicAt es e-fatal es e = rendCaret >>= fatalAt es e-err es e = rendCaret >>= errAt es e--warnAt, noteAt :: MonadDiagnostic e m => [Diagnostic e] -> e -> Rendering -> m ()-warnAt es e r = logDiagnostic $ Diagnostic (Right r) Warning e es-noteAt es e r = logDiagnostic $ Diagnostic (Right r) Note e es--verboseAt :: MonadDiagnostic e m => Int -> [Diagnostic e] -> e -> Rendering -> m ()-verboseAt l es e r = logDiagnostic $ Diagnostic (Right r) (Verbose l) e es--warn, note :: (MonadParser m, MonadDiagnostic e m) => [Diagnostic e] -> e -> m ()-warn es e = rendCaret >>= warnAt es e-note es e = rendCaret >>= noteAt es e--verbose :: (MonadParser m, MonadDiagnostic e m) => Int -> [Diagnostic e] -> e -> m ()-verbose l es e = rendCaret >>= verboseAt l es e
− Text/Trifecta/Diagnostic/Err.hs
@@ -1,87 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Err--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ The unlocated error type used internally within the parser.------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Err- ( Err(..)- , knownErr- , fatalErr- ) where--import Control.Applicative-import Data.Foldable-import Data.Traversable-import Data.Semigroup-import Data.Functor.Plus-import Text.Trifecta.Diagnostic.Prim-import Text.Trifecta.Diagnostic.Level-import Text.Trifecta.Diagnostic.Rendering.Prim--data Err e- = EmptyErr -- no error specified, unlocated- | FailErr Rendering String -- a recoverable error caused by fail from a known location- | PanicErr Rendering String -- something is bad with the grammar, fail fast- | Err !(Diagnostic e) -- a user defined error message- deriving Show--knownErr :: Err e -> Bool-knownErr EmptyErr = False-knownErr _ = True--fatalErr :: Err e -> Bool-fatalErr (Err (Diagnostic _ Panic _ _)) = True-fatalErr (Err (Diagnostic _ Fatal _ _)) = True-fatalErr (PanicErr _ _) = True-fatalErr _ = False--instance Functor Err where- fmap _ EmptyErr = EmptyErr- fmap _ (FailErr r s) = FailErr r s- fmap _ (PanicErr r s) = PanicErr r s- fmap f (Err e) = Err (fmap f e)--instance Foldable Err where- foldMap _ EmptyErr = mempty- foldMap _ FailErr{} = mempty- foldMap _ PanicErr{} = mempty- foldMap f (Err e) = foldMap f e--instance Traversable Err where- traverse _ EmptyErr = pure EmptyErr- traverse _ (FailErr r s) = pure $ FailErr r s- traverse _ (PanicErr r s) = pure $ PanicErr r s- traverse f (Err e) = Err <$> traverse f e---- | Merge two errors, selecting the most severe.-instance Alt Err where- a <!> EmptyErr = a- _ <!> a@(Err (Diagnostic _ Panic _ _)) = a- a@(Err (Diagnostic _ Panic _ _)) <!> _ = a- _ <!> a@PanicErr{} = a- a@PanicErr{} <!> _ = a- _ <!> a@(Err (Diagnostic _ Fatal _ _)) = a- a@(Err (Diagnostic _ Fatal _ _)) <!> _ = a- _ <!> b = b- {-# INLINE (<!>) #-}---- | Merge two errors, selecting the most severe.-instance Plus Err where- zero = EmptyErr---- | Merge two errors, selecting the most severe.-instance Semigroup (Err t) where- (<>) = (<!>)- times1p _ = id---- | Merge two errors, selecting the most severe.-instance Monoid (Err t) where- mempty = EmptyErr- mappend = (<!>)
− Text/Trifecta/Diagnostic/Err/Log.hs
@@ -1,43 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Err.Log--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Err.Log- ( ErrLog(..)- ) where--import Data.Functor.Plus-import Data.Semigroup-import Text.Trifecta.Diagnostic.Prim-import Text.Trifecta.Highlight.Prim-import Data.Semigroup.Union (union, empty)-import Data.Sequence (Seq)--data ErrLog e = ErrLog- { errLog :: !(Seq (Diagnostic e))- , errHighlights :: !Highlights- }--instance Functor ErrLog where- fmap f (ErrLog a b) = ErrLog (fmap (fmap f) a) b--instance Alt ErrLog where- ErrLog a b <!> ErrLog a' b' = ErrLog (a <> a') (union b b')- {-# INLINE (<!>) #-}--instance Plus ErrLog where- zero = ErrLog mempty empty- -instance Semigroup (ErrLog e) where- (<>) = (<!>) --instance Monoid (ErrLog e) where- mempty = zero- mappend = (<!>)
− Text/Trifecta/Diagnostic/Err/State.hs
@@ -1,42 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Err.State--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Err.State- ( ErrState(..)- ) where--import Data.Functor.Plus-import Data.Set as Set-import Data.Semigroup-import Text.Trifecta.Diagnostic.Err-import Text.Trifecta.Diagnostic.Rendering.Caret--data ErrState e = ErrState- { errExpected :: !(Set (Careted String))- , errMessage :: !(Err e)- }--instance Functor ErrState where- fmap f (ErrState a b) = ErrState a (fmap f b)--instance Alt ErrState where- ErrState a b <!> ErrState a' b' = ErrState (a <> a') (b <> b')- {-# INLINE (<!>) #-}--instance Plus ErrState where- zero = ErrState mempty mempty--instance Semigroup (ErrState e) where- (<>) = (<!>)--instance Monoid (ErrState e) where- mempty = zero- mappend = (<!>)
− Text/Trifecta/Diagnostic/Level.hs
@@ -1,66 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Level--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ A fairly straightforward set of common error levels.------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Level- ( DiagnosticLevel(..)- ) where--import Control.Applicative-import Data.Semigroup-import Text.PrettyPrint.Free-import System.Console.Terminfo.PrettyPrint---- | The severity of an error (or message)-data DiagnosticLevel- = Verbose !Int -- ^ a comment we should only show to the excessively curious- | Note -- ^ a comment- | Warning -- ^ a warning, computation continues- | Error -- ^ a user specified error- | Fatal -- ^ a user specified fatal error- | Panic -- ^ a non-maskable death sentence thrown by the parser itself- deriving (Eq,Show,Read)--instance Ord DiagnosticLevel where- compare (Verbose n) (Verbose m) = compare m n- compare (Verbose _) _ = LT- compare Note (Verbose _) = GT- compare Note Note = EQ- compare Note _ = LT- compare Warning (Verbose _) = GT- compare Warning Note = GT- compare Warning Warning = EQ- compare Warning _ = LT- compare Error Error = EQ- compare Error Fatal = LT- compare Error Panic = LT- compare Error _ = GT- compare Fatal Panic = LT- compare Fatal Fatal = EQ- compare Fatal _ = GT- compare Panic Panic = EQ- compare Panic _ = GT---- | Compute the maximum of two diagnostic levels-instance Semigroup DiagnosticLevel where- (<>) = max--instance Pretty DiagnosticLevel where- pretty p = prettyTerm p *> empty---- | pretty print as a color coded description-instance PrettyTerm DiagnosticLevel where- prettyTerm (Verbose n) = blue $ text "verbose (" <> prettyTerm n <> char ')'- prettyTerm Note = black $ text "note"- prettyTerm Warning = magenta $ text "warning"- prettyTerm Error = red $ text "error"- prettyTerm Fatal = standout $ red $ text "fatal"- prettyTerm Panic = standout $ red $ text "panic"
− Text/Trifecta/Diagnostic/Prim.hs
@@ -1,104 +0,0 @@-{-# LANGUAGE FlexibleContexts, DeriveDataTypeable #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Prim--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ Rich diagnostics------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Prim- ( Diagnostic(..)- ) where--import Control.Applicative-import Control.Comonad-import Control.Monad (guard)-import Control.Exception-import Data.Functor.Apply-import Data.Foldable-import Data.Traversable-import Data.List.NonEmpty hiding (map)-import Data.Semigroup-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Diagnostic.Rendering.Prim-import Text.Trifecta.Diagnostic.Level-import Text.PrettyPrint.Free-import Text.Trifecta.Highlight.Class-import System.Console.Terminfo.PrettyPrint-import Prelude hiding (log)-import Data.Typeable--data Diagnostic m = Diagnostic !(Either String Rendering) !DiagnosticLevel m [Diagnostic m]- deriving (Show, Typeable)--instance Highlightable (Diagnostic e) where- addHighlights h (Diagnostic rs l m xs) = Diagnostic (addHighlights h <$> rs) l m (addHighlights h <$> xs)--instance (Typeable m, Show m) => Exception (Diagnostic m)--instance Renderable (Diagnostic m) where- render (Diagnostic r _ _ _) = either (const emptyRendering) id r--instance HasDelta (Diagnostic m) where- delta (Diagnostic r _ _ _) = either (const mempty) delta r--instance HasBytes (Diagnostic m) where- bytes (Diagnostic r _ _ _) = either (const 0) (bytes . delta) r--instance Extend Diagnostic where- extend f d@(Diagnostic r l _ xs) = Diagnostic r l (f d) (map (extend f) xs)--instance Comonad Diagnostic where- extract (Diagnostic _ _ m _) = m--instance Pretty m => Pretty (Diagnostic m) where- pretty (Diagnostic src l m xs) = case src of - Left p -> vsep $ [pretty p <> msg]- <|> children- Right r -> vsep $ [pretty (delta r) <> msg]- <|> pretty r <$ guard (not (nullRendering r))- <|> children- where - msg = char ':' <+> pretty l <> char ':' <+> nest 4 (pretty m) - children = indent 2 (prettyList xs) <$ guard (not (null xs))-- prettyList = vsep . Prelude.map pretty--instance PrettyTerm m => PrettyTerm (Diagnostic m) where- prettyTerm (Diagnostic src l m xs) = case src of - Left p -> vsep $ [prettyTerm p <> msg]- <|> children- Right r -> vsep $ [prettyTerm (delta r) <> msg]- <|> prettyTerm r <$ guard (not (nullRendering r))- <|> children- where - msg = char ':' <+> prettyTerm l <> char ':' <+> nest 4 (prettyTerm m) - children = indent 2 (prettyTermList xs) <$ guard (not (null xs))- prettyTermList = vsep . Prelude.map prettyTerm--instance Functor Diagnostic where- fmap f (Diagnostic r l m xs) = Diagnostic r l (f m) $ map (fmap f) xs--instance Foldable Diagnostic where- foldMap f (Diagnostic _ _ m xs) = f m `mappend` foldMap (foldMap f) xs--instance Traversable Diagnostic where- traverse f (Diagnostic r l m xs) = Diagnostic r l <$> f m <*> traverse (traverse f) xs--instance Foldable1 Diagnostic where- foldMap1 f (Diagnostic _ _ m []) = f m- foldMap1 f (Diagnostic _ _ m (x:xs)) = f m <> foldMap1 (foldMap1 f) (x:|xs)--instance Traversable1 Diagnostic where- traverse1 f (Diagnostic r l m []) = fmap (\fm -> Diagnostic r l fm []) (f m)- traverse1 f (Diagnostic r l m (x:xs)) = (\fm (y:|ys) -> Diagnostic r l fm (y:ys)) - <$> f m - <.> traverse1 (traverse1 f) (x:|xs)
− Text/Trifecta/Diagnostic/Rendering.hs
@@ -1,23 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Rendering--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Rendering- ( Renderable(..)- , Source, rendering, renderingCaret- , Caret(..), Careted(..)- , Span(..), Spanned(..)- , Fixit(..), Rendered(..)- ) where--import Text.Trifecta.Diagnostic.Rendering.Prim-import Text.Trifecta.Diagnostic.Rendering.Caret-import Text.Trifecta.Diagnostic.Rendering.Span-import Text.Trifecta.Diagnostic.Rendering.Fixit
− Text/Trifecta/Diagnostic/Rendering/Caret.hs
@@ -1,128 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Rendering.Caret--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Rendering.Caret- ( Caret(..)- , caret- , Careted(..)- , careted- -- * Internals- , drawCaret- , addCaret- , caretEffects- , renderingCaret- ) where--import Control.Applicative-import Control.Comonad-import Data.ByteString (ByteString)-import Data.Foldable-import Data.Functor.Bind-import Data.Hashable-import Data.Semigroup-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Data.Semigroup.Reducer-import Data.Traversable-import Prelude hiding (span)-import System.Console.Terminfo.Color-import System.Console.Terminfo.PrettyPrint-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Parser.Class-import Text.Trifecta.Diagnostic.Rendering.Prim---- |--- > In file included from baz.c:9--- > In file included from bar.c:4--- > foo.c:8:36: note--- > int main(int argc, char ** argv) { int; }--- > ^-data Caret = Caret !Delta {-# UNPACK #-} !ByteString deriving (Eq,Ord,Show)--instance Hashable Caret where- hash (Caret d bs) = hash d `hashWithSalt` bs--caretEffects :: [ScopedEffect]-caretEffects = [soft (Foreground Green), soft Bold]--drawCaret :: Delta -> Delta -> Lines -> Lines-drawCaret p = ifNear p $ draw caretEffects 1 (fromIntegral (column p)) "^"--addCaret :: Delta -> Rendering -> Rendering-addCaret p r = drawCaret p .# r--caret :: MonadParser m => m Caret-caret = Caret <$> position <*> line- -careted :: MonadParser m => m a -> m (Careted a)-careted p = do- m <- position- l <- line- a <- p- return $ a :^ Caret m l--instance HasBytes Caret where- bytes = bytes . delta--instance HasDelta Caret where- delta (Caret d _) = d--instance Renderable Caret where- render (Caret d bs) = addCaret d $ rendering d bs--instance Reducer Caret Rendering where- unit = render--instance Semigroup Caret where- a <> _ = a--renderingCaret :: Delta -> ByteString -> Rendering-renderingCaret d bs = addCaret d $ rendering d bs--data Careted a = a :^ Caret deriving (Eq,Ord,Show)--instance Functor Careted where- fmap f (a :^ s) = f a :^ s--instance Extend Careted where- extend f as@(_ :^ s) = f as :^ s--instance HasDelta (Careted a) where- delta (_ :^ c) = delta c--instance HasBytes (Careted a) where- bytes (_ :^ c) = bytes c--instance Comonad Careted where- extract (a :^ _) = a--instance Foldable Careted where- foldMap f (a :^ _) = f a--instance Traversable Careted where- traverse f (a :^ s) = (:^ s) <$> f a--instance Foldable1 Careted where- foldMap1 f (a :^ _) = f a--instance Traversable1 Careted where- traverse1 f (a :^ s) = (:^ s) <$> f a--instance Renderable (Careted a) where- render (_ :^ a) = render a--instance Reducer (Careted a) Rendering where- unit = render--instance Hashable a => Hashable (Careted a) where-
− Text/Trifecta/Diagnostic/Rendering/Fixit.hs
@@ -1,63 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Rendering.Fixit--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Rendering.Fixit- ( Fixit(..)- , drawFixit- , addFixit- , fixit- ) where--import Data.Functor-import Data.Hashable-import Data.ByteString (ByteString)-import qualified Data.ByteString as Strict-import qualified Data.ByteString.UTF8 as UTF8-import Data.Semigroup.Reducer-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Diagnostic.Rendering.Prim-import Text.Trifecta.Diagnostic.Rendering.Span-import Text.Trifecta.Parser.Class-import Text.Trifecta.Util.Combinators-import System.Console.Terminfo.Color-import System.Console.Terminfo.PrettyPrint-import Prelude hiding (span)---- |--- > int main(int argc char ** argv) { int; }--- > ^--- > ,-drawFixit :: Delta -> Delta -> String -> Delta -> Lines -> Lines-drawFixit s e rpl d a = ifNear l (draw [soft (Foreground Blue)] 2 (fromIntegral (column l)) rpl) d - $ drawSpan s e d a- where l = argmin bytes s e--addFixit :: Delta -> Delta -> String -> Rendering -> Rendering-addFixit s e rpl r = drawFixit s e rpl .# r--data Fixit = Fixit - { fixitSpan :: {-# UNPACK #-} !Span- , fixitReplacement :: {-# UNPACK #-} !ByteString - } deriving (Eq,Ord,Show)--instance Hashable Fixit where- hash (Fixit s b) = hash s `hashWithSalt` b--instance Reducer Fixit Rendering where- unit = render--instance Renderable Fixit where- render (Fixit (Span s e bs) r) = addFixit s e (UTF8.toString r) $ rendering s bs--fixit :: MonadParser m => m Strict.ByteString -> m Fixit-fixit p = (\(r :~ s) -> Fixit s r) <$> spanned p
− Text/Trifecta/Diagnostic/Rendering/Prim.hs
@@ -1,240 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}---------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Rendering.Prim--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ The type for Lines will very likely change over time, to enable drawing --- lit up multi-character versions of control characters for @^Z@, @^[@, --- @<0xff>@, etc. This will make for much nicer diagnostics when --- working with protocols.-----------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Rendering.Prim - ( Rendering(..)- , nullRendering- , emptyRendering- , Source(..)- , rendering- , Renderable(..)- , Rendered(..)- -- * Lower level drawing primitives- , Lines- , draw- , ifNear- , (.#)- ) where--import Control.Applicative-import Control.Comonad-import Control.Monad.State-import Data.Array-import Data.ByteString as B hiding (groupBy, empty, any)-import Data.Foldable-import Data.Function (on)-import Data.Int (Int64)-import Data.Functor.Bind-import Data.List (groupBy)-import Data.Semigroup-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Data.Traversable-import Text.Trifecta.IntervalMap-import Prelude as P-import Prelude hiding (span)-import System.Console.Terminfo.Color-import System.Console.Terminfo.PrettyPrint-import Text.PrettyPrint.Free hiding (column)-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Highlight.Class-import Text.Trifecta.Highlight.Effects-import qualified Data.ByteString.UTF8 as UTF8 --outOfRangeEffects :: [ScopedEffect] -> [ScopedEffect]-outOfRangeEffects xs = soft Bold : xs--type Lines = Array (Int,Int64) ([ScopedEffect], Char)--(///) :: Ix i => Array i e -> [(i, e)] -> Array i e-a /// xs = a // P.filter (inRange (bounds a) . fst) xs--grow :: Int -> Lines -> Lines-grow y a - | inRange (t,b) y = a- | otherwise = array new [ (i, if inRange old i then a ! i else ([],' ')) | i <- range new ]- where old@((t,lo),(b,hi)) = bounds a- new = ((min t y,lo),(max b y,hi))--draw :: [ScopedEffect] -> Int -> Int64 -> String -> Lines -> Lines-draw e y n xs a0 - | Prelude.null xs = a0- | otherwise = gt $ lt (a /// out) - where - a = grow y a0- ((_,lo),(_,hi)) = bounds a- out = P.zipWith (\i c -> ((y,i),(e,c))) [n..] xs- lt | Prelude.any (\el -> snd (fst el) < lo) out = (// [((y,lo),(outOfRangeEffects e,'<'))])- | otherwise = id- gt | Prelude.any (\el -> snd (fst el) > hi) out = (// [((y,hi),(outOfRangeEffects e,'>'))])- | otherwise = id---- | fill the interval from [n .. m) with a given effect-recolor :: ([ScopedEffect] -> [ScopedEffect]) -> Maybe Int64 -> Maybe Int64 -> Lines -> Lines-recolor f n0 m0 a0 - | m <= n = a0- | otherwise = a /// P.map rc [n .. m - 1]- where - ((_,lo),(_,hi)) = bounds a- n = maybe lo id n0- m = maybe (hi + 1) id m0- a = grow 0 a0- rc i = (yi, (f e, c)) -- only if not isSpace?- where - yi = (0, i)- (e,c) = a ! yi--data Rendering = Rendering- { renderingDelta :: !Delta -- focus, the render will keep this visible- , renderingLineLen :: {-# UNPACK #-} !Int64 -- actual line length- , renderingLineBytes :: {-# UNPACK #-} !Int64 -- line length in bytes- , renderingLine :: Lines -> Lines- , renderingOverlays :: Delta -> Lines -> Lines- }--instance Highlightable Rendering where- addHighlights intervals (Rendering d ll lb l o) = Rendering d ll lb l' o where- d' = rewind d- l' = Prelude.foldr (.) l [ recolor (eff tok) (column lo <$ guard (near d lo)) (column hi <$ guard (near d hi)) - | (Interval lo hi, tok) <- intersections d' (d' <> Columns ll lb) intervals ]- eff t _ = highlightEffects t--instance Show Rendering where- showsPrec d (Rendering p ll lb _ _) = showParen (d > 10) $ - showString "Rendering " . showsPrec 11 p . showChar ' ' . showsPrec 11 ll . showChar ' ' . showsPrec 11 lb . showString " ... ..."--nullRendering :: Rendering -> Bool-nullRendering (Rendering (Columns 0 0) 0 0 _ _) = True-nullRendering _ = False--emptyRendering :: Rendering-emptyRendering = rendering (Columns 0 0) ""--instance Semigroup Rendering where- -- an unprincipled hack- Rendering (Columns 0 0) 0 0 _ f <> Rendering del len lb doc g = Rendering del len lb doc $ \d l -> f d (g d l)- Rendering del len lb doc f <> Rendering _ _ _ _ g = Rendering del len lb doc $ \d l -> f d (g d l)--instance Monoid Rendering where- mappend = (<>) - mempty = emptyRendering- -ifNear :: Delta -> (Lines -> Lines) -> Delta -> Lines -> Lines-ifNear d f d' l | near d d' = f l - | otherwise = l--instance HasDelta Rendering where- delta = renderingDelta--class Renderable t where- render :: t -> Rendering--instance Renderable Rendering where- render = id--class Source t where- source :: t -> (Int64, Int64, Lines -> Lines) {- the number of (padded) columns, number of bytes, and the the line -}--instance Source String where- source s - | Prelude.elem '\n' s = ( ls, bs, draw [] 0 0 s') - | otherwise = ( ls + fromIntegral (Prelude.length end), bs, draw [soft (Foreground Blue), soft Bold] 0 ls end . draw [] 0 0 s') - where- end = "<EOF>" - s' = go 0 s- bs = fromIntegral $ B.length $ UTF8.fromString $ Prelude.takeWhile (/='\n') s- ls = fromIntegral $ Prelude.length s' - go n ('\t':xs) = let t = 8 - mod n 8 in P.replicate t ' ' ++ go (n + t) xs- go _ ('\n':_) = []- go n (x:xs) = x : go (n + 1) xs- go _ [] = []- --instance Source ByteString where- source = source . UTF8.toString---- | create a drawing surface-rendering :: Source s => Delta -> s -> Rendering-rendering del s = case source s of - (len, lb, doc) -> Rendering del len lb doc (\_ l -> l)--(.#) :: (Delta -> Lines -> Lines) -> Rendering -> Rendering-f .# Rendering d ll lb s g = Rendering d ll lb s $ \e l -> f e $ g e l --instance Pretty Rendering where- pretty r = prettyTerm r >>= const empty--instance PrettyTerm Rendering where- prettyTerm (Rendering d ll _ l f) = nesting $ \k -> columns $ \n -> go (fromIntegral (n - k)) where- go cols = align (vsep (P.map ln [t..b])) where - (lo, hi) = window (column d) ll (min (max (cols - 2) 30) 200)- a = f d $ l $ array ((0,lo),(-1,hi)) []- ((t,_),(b,_)) = bounds a- ln y = hcat - $ P.map (\g -> P.foldr with (pretty (P.map snd g)) (fst (P.head g)))- $ groupBy ((==) `on` fst) - [ a ! (y,i) | i <- [lo..hi] ] --window :: Int64 -> Int64 -> Int64 -> (Int64, Int64)-window c l w - | c <= w2 = (0, min w l)- | c + w2 >= l = if l > w then (l-w, l) else (0, w)- | otherwise = (c-w2,c + w2)- where w2 = div w 2--data Rendered a = a :@ Rendering- deriving Show--instance Functor Rendered where- fmap f (a :@ s) = f a :@ s--instance HasDelta (Rendered a) where- delta = delta . render--instance HasBytes (Rendered a) where- bytes = bytes . delta--instance Extend Rendered where- extend f as@(_ :@ s) = f as :@ s--instance Comonad Rendered where- extract (a :@ _) = a--instance Apply Rendered where- (f :@ s) <.> (a :@ t) = f a :@ (s <> t)--instance Bind Rendered where- (a :@ s) >>- f = case f a of- b :@ t -> b :@ (s <> t)--instance Foldable Rendered where- foldMap f (a :@ _) = f a --instance Traversable Rendered where- traverse f (a :@ s) = (:@ s) <$> f a--instance Foldable1 Rendered where- foldMap1 f (a :@ _) = f a --instance Traversable1 Rendered where- traverse1 f (a :@ s) = (:@ s) <$> f a--instance Renderable (Rendered a) where- render (_ :@ s) = s
− Text/Trifecta/Diagnostic/Rendering/Span.hs
@@ -1,125 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Diagnostic.Rendering.Span--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Diagnostic.Rendering.Span- ( Span(..)- , span- , Spanned(..)- , spanned- -- * Internals- , spanEffects- , drawSpan- , addSpan- ) where--import Control.Applicative-import Data.Hashable-import Data.Semigroup-import Data.Semigroup.Reducer-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Data.Foldable-import Data.Traversable-import Control.Comonad-import Data.Functor.Bind-import Data.ByteString (ByteString)-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Diagnostic.Rendering.Prim-import Text.Trifecta.Util.Combinators-import Text.Trifecta.Parser.Class-import Data.Array-import System.Console.Terminfo.Color-import System.Console.Terminfo.PrettyPrint-import Prelude as P hiding (span)--spanEffects :: [ScopedEffect]-spanEffects = [soft (Foreground Green)]--drawSpan :: Delta -> Delta -> Delta -> Lines -> Lines-drawSpan s e d a- | nl && nh = go (column l) (rep (max (column h - column l) 0) '~') a- | nl = go (column l) (rep (max (snd (snd (bounds a)) - column l + 1) 0) '~') a- | nh = go (-1) (rep (max (column h + 1) 0) '~') a- | otherwise = a- where- go = draw spanEffects 1 . fromIntegral- l = argmin bytes s e- h = argmax bytes s e- nl = near l d- nh = near h d- rep = P.replicate . fromIntegral---- |--- > int main(int argc, char ** argv) { int; }--- > ^~~-addSpan :: Delta -> Delta -> Rendering -> Rendering-addSpan s e r = drawSpan s e .# r--data Span = Span !Delta !Delta {-# UNPACK #-} !ByteString deriving (Eq,Ord,Show)--instance Renderable Span where- render (Span s e bs) = addSpan s e $ rendering s bs--instance Semigroup Span where- Span s _ b <> Span _ e _ = Span s e b--instance Reducer Span Rendering where- unit = render--data Spanned a = a :~ Span deriving (Eq,Ord,Show)--instance Functor Spanned where- fmap f (a :~ s) = f a :~ s--instance Extend Spanned where- extend f as@(_ :~ s) = f as :~ s--instance Comonad Spanned where- extract (a :~ _) = a--instance Apply Spanned where- (f :~ s) <.> (a :~ t) = f a :~ (s <> t)--instance Bind Spanned where- (a :~ s) >>- f = case f a of- b :~ t -> b :~ (s <> t)--instance Foldable Spanned where- foldMap f (a :~ _) = f a--instance Traversable Spanned where- traverse f (a :~ s) = (:~ s) <$> f a--instance Foldable1 Spanned where- foldMap1 f (a :~ _) = f a--instance Traversable1 Spanned where- traverse1 f (a :~ s) = (:~ s) <$> f a--instance Reducer (Spanned a) Rendering where- unit = render--instance Renderable (Spanned a) where- render (_ :~ s) = render s--instance Hashable Span where- hash (Span s e bs) = hash s `hashWithSalt` e `hashWithSalt` bs--instance Hashable a => Hashable (Spanned a) where- hash (a :~ s) = hash a `hashWithSalt` s--span :: MonadParser m => m a -> m Span-span p = (\s l e -> Span s e l) <$> position <*> line <*> (p *> position)--spanned :: MonadParser m => m a -> m (Spanned a)-spanned p = (\s l a e -> a :~ Span s e l) <$> position <*> line <*> p <*> position
− Text/Trifecta/Highlight.hs
@@ -1,22 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Highlight--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Highlight - ( - -- * Text.Trifecta.Highlight.Class- Highlightable(..)- -- * Text.Trifecta.Highlight.Prim- , Highlight- , Highlights- ) where--import Text.Trifecta.Highlight.Class-import Text.Trifecta.Highlight.Prim
− Text/Trifecta/Highlight/Class.hs
@@ -1,19 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Highlight.Class--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Highlight.Class - ( Highlightable(..)- ) where--import Text.Trifecta.Highlight.Prim--class Highlightable a where- addHighlights :: Highlights -> a -> a
− Text/Trifecta/Highlight/Effects.hs
@@ -1,44 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Highlight.Effects--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Highlight.Effects - ( highlightEffects- , pushToken- , popToken- , withHighlight- ) where--import Control.Applicative-import System.Console.Terminfo.PrettyPrint-import System.Console.Terminfo.Color-import Data.Semigroup-import Text.Trifecta.Highlight.Prim--highlightEffects :: Highlight -> [ScopedEffect]-highlightEffects Comment = [soft $ Foreground Blue]-highlightEffects ReservedIdentifier = [soft $ Foreground Magenta, soft Bold]-highlightEffects ReservedConstructor = [soft $ Foreground Magenta, soft Bold]-highlightEffects EscapeCode = [soft $ Foreground Magenta, soft Bold]-highlightEffects Operator = [soft $ Foreground Yellow]-highlightEffects CharLiteral = [soft $ Foreground Cyan]-highlightEffects StringLiteral = [soft $ Foreground Cyan]-highlightEffects Constructor = [soft Bold]-highlightEffects ReservedOperator = [soft $ Foreground Yellow]-highlightEffects ConstructorOperator = [soft $ Foreground Yellow, soft Bold]-highlightEffects ReservedConstructorOperator = [soft $ Foreground Yellow, soft Bold]-highlightEffects _ = []--pushToken, popToken :: Highlight -> TermDoc-pushToken h = foldr (\a b -> pure (Push a) <> b) mempty (highlightEffects h)-popToken h = foldr (\_ b -> pure Pop <> b) mempty (highlightEffects h)--withHighlight :: Highlight -> TermDoc -> TermDoc-withHighlight h d = pushToken h <> d <> popToken h
− Text/Trifecta/Highlight/Prim.hs
@@ -1,47 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Highlight.Prim--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Highlight.Prim- ( Highlight(..)- , Highlights- ) where--import Data.Ix-import Text.Trifecta.IntervalMap-import Text.Trifecta.Rope.Delta--data Highlight- = EscapeCode- | Number - | Comment- | CharLiteral- | StringLiteral- | Constant- | Statement- | Special- | Symbol- | Identifier- | ReservedIdentifier- | Operator- | ReservedOperator- | Constructor- | ReservedConstructor- | ConstructorOperator- | ReservedConstructorOperator- | BadInput- | Unbound- | Layout- | MatchedSymbols- | LiterateComment- | LiterateSyntax- deriving (Eq,Ord,Show,Read,Enum,Ix,Bounded)--type Highlights = IntervalMap Delta Highlight
− Text/Trifecta/Highlight/Rendering/HTML.hs
@@ -1,48 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Highlight.Rendering.HTML--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Highlight.Rendering.HTML - ( Doc(..)- , doc- ) where--import Data.Monoid-import Prelude hiding (head)-import Text.Blaze-import Text.Blaze.Html5 hiding (b,i)-import Text.Blaze.Html5.Attributes hiding (title)-import Text.Trifecta.Highlight.Class-import Text.Trifecta.Rope.Highlighted---- | Represents a source file like an HsColour rendered document-data Doc = Doc - { docTitle :: String- , docCss :: String -- href for the css file- , docContent :: HighlightedRope- }---- | ------ > renderHtml $ toHtml $ addHighlights highlightedRope $ doc "Foo.hs"-doc :: String -> Doc-doc t = Doc t "trifecta.css" mempty--instance ToHtml Doc where- toHtml (Doc t css cs) = docTypeHtml $ do- head $ do- preEscapedString "<!-- Generated by trifecta, http://github.com/ekmett/trifecta/ -->\n"- title $ toHtml t- link ! rel "stylesheet" ! type_ "text/css" ! href (toValue css)- body $ toHtml cs--instance Highlightable Doc where - addHighlights h (Doc t c r) = Doc t c (addHighlights h r)
− Text/Trifecta/IntervalMap.hs
@@ -1,275 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.IntervalMap--- Copyright : (c) Edward Kmett 2011--- (c) Ross Paterson 2008--- License : BSD-style--- Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable (MPTCs, type families, functional dependencies)------ Interval maps implemented using the 'FingerTree' type, following--- section 4.8 of------ * Ralf Hinze and Ross Paterson,--- \"Finger trees: a simple general-purpose data structure\",--- /Journal of Functional Programming/ 16:2 (2006) pp 197-217.--- <http://www.soi.city.ac.uk/~ross/papers/FingerTree.html>------ An amortized running time is given for each operation, with /n/--- referring to the size of the priority queue. These bounds hold even--- in a persistent (shared) setting.------ /Note/: Many of these operations have the same names as similar--- operations on lists in the "Prelude". The ambiguity may be resolved--- using either qualification or the @hiding@ clause.------ Unlike "Data.IntervalMap.FingerTree", this version sorts things so--- that the largest interval from a given point comes first. This way--- if you have nested intervals, you get the outermost interval before --- the contained intervals.--------------------------------------------------------------------------------module Text.Trifecta.IntervalMap - (- -- * Intervals- Interval(..)- -- * Interval maps- , IntervalMap(..), singleton, insert- -- * Searching- , search, intersections, dominators- -- * Prepending an offset onto every interval in the map- , offset- -- * The result monoid- , IntInterval(..)- , fromList- ) where--import Control.Applicative hiding (empty)-import qualified Data.FingerTree as FT-import Data.FingerTree (FingerTree, Measured(..), ViewL(..), (<|), (><))-import Data.Functor.Plus--import Data.Traversable (Traversable(traverse))-import Data.Foldable (Foldable(foldMap))-import Data.Bifunctor-import Data.Semigroup-import Data.Semigroup.Reducer-import Data.Semigroup.Union-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Data.Key-import Data.Pointed--------------------------------------- 4.8 Application: interval trees--------------------------------------- | A closed interval. The lower bound should be less than or equal--- to the higher bound.-data Interval v = Interval { low :: v, high :: v }- deriving Show--instance Ord v => Semigroup (Interval v) where- Interval a b <> Interval c d = Interval (min a c) (max b d)---- assumes the monoid and ordering are compatible.-instance (Ord v, Monoid v) => Reducer v (Interval v) where - unit v = Interval v v- cons v (Interval a b) = Interval (v `mappend` a) (v `mappend` b)- snoc (Interval a b) v = Interval (a `mappend` v) (b `mappend` v)--instance Eq v => Eq (Interval v) where- Interval a b == Interval c d = a == c && d == b--instance Ord v => Ord (Interval v) where- compare (Interval a b) (Interval c d) = case compare a c of- LT -> LT- EQ -> compare d b -- reversed to put larger intervals first- GT -> GT--instance Functor Interval where- fmap f (Interval a b) = Interval (f a) (f b)--instance Foldable Interval where- foldMap f (Interval a b) = f a `mappend` f b--instance Traversable Interval where- traverse f (Interval a b) = Interval <$> f a <*> f b--instance Foldable1 Interval where- foldMap1 f (Interval a b) = f a <> f b--instance Traversable1 Interval where- traverse1 f (Interval a b) = Interval <$> f a <.> f b--instance Pointed Interval where- point v = Interval v v --data Node v a = Node (Interval v) a--type instance Key (Node v) = Interval v--instance Functor (Node v) where- fmap f (Node i x) = Node i (f x)--instance Bifunctor Node where- bimap f g (Node v a) = Node (fmap f v) (g a)--instance Keyed (Node v) where- mapWithKey f (Node i x) = Node i (f i x)--instance Foldable (Node v) where- foldMap f (Node _ x) = f x--instance FoldableWithKey (Node v) where- foldMapWithKey f (Node k v) = f k v--instance Traversable (Node v) where- traverse f (Node i x) = Node i <$> f x--instance TraversableWithKey (Node v) where- traverseWithKey f (Node i x) = Node i <$> f i x--instance Foldable1 (Node v) where- foldMap1 f (Node _ x) = f x--instance FoldableWithKey1 (Node v) where- foldMapWithKey1 f (Node k v) = f k v--instance Traversable1 (Node v) where- traverse1 f (Node i x) = Node i <$> f x--instance TraversableWithKey1 (Node v) where- traverseWithKey1 f (Node i x) = Node i <$> f i x---- rightmost interval (including largest lower bound) and largest upper bound.-data IntInterval v = NoInterval | IntInterval (Interval v) v--instance Ord v => Monoid (IntInterval v) where- mempty = NoInterval- NoInterval `mappend` i = i- i `mappend` NoInterval = i- IntInterval _ hi1 `mappend` IntInterval int2 hi2 =- IntInterval int2 (max hi1 hi2)--instance Ord v => Measured (IntInterval v) (Node v a) where- measure (Node i _) = IntInterval i (high i)---- | Map of closed intervals, possibly with duplicates.--- The 'Foldable' and 'Traversable' instances process the intervals in--- lexicographical order.-newtype IntervalMap v a = IntervalMap { runIntervalMap :: FingerTree (IntInterval v) (Node v a) } --- ordered lexicographically by interval--type instance Key (IntervalMap v) = Interval v--instance Functor (IntervalMap v) where- fmap f (IntervalMap t) = IntervalMap (FT.unsafeFmap (fmap f) t)--instance Keyed (IntervalMap v) where- mapWithKey f (IntervalMap t) = IntervalMap (FT.unsafeFmap (mapWithKey f) t)--instance Foldable (IntervalMap v) where- foldMap f (IntervalMap t) = foldMap (foldMap f) t--instance FoldableWithKey (IntervalMap v) where- foldMapWithKey f (IntervalMap t) = foldMap (foldMapWithKey f) t --instance Traversable (IntervalMap v) where- traverse f (IntervalMap t) =- IntervalMap <$> FT.unsafeTraverse (traverse f) t--instance TraversableWithKey (IntervalMap v) where- traverseWithKey f (IntervalMap t) = - IntervalMap <$> FT.unsafeTraverse (traverseWithKey f) t--instance Ord v => Measured (IntInterval v) (IntervalMap v a) where- measure (IntervalMap m) = measure m--largerError :: a-largerError = error "Text.Trifecta.IntervalMap.larger: the impossible happened"---- | /O(m log (n/\//m))/. Merge two interval maps.--- The map may contain duplicate intervals; entries with equal intervals--- are kept in the original order.-instance Ord v => HasUnion (IntervalMap v a) where- union (IntervalMap xs) (IntervalMap ys) = IntervalMap (merge1 xs ys) where - merge1 as bs = case FT.viewl as of- EmptyL -> bs- a@(Node i _) :< as' -> l >< a <| merge2 as' r- where - (l, r) = FT.split larger bs- larger (IntInterval k _) = k >= i- larger _ = largerError- merge2 as bs = case FT.viewl bs of- EmptyL -> as- b@(Node i _) :< bs' -> l >< b <| merge1 r bs'- where - (l, r) = FT.split larger as- larger (IntInterval k _) = k >= i- larger _ = largerError--instance Ord v => HasUnion0 (IntervalMap v a) where- empty = IntervalMap FT.empty--instance Ord v => Monoid (IntervalMap v a) where- mempty = empty- mappend = union--instance Ord v => Alt (IntervalMap v) where- (<!>) = union--instance Ord v => Plus (IntervalMap v) where- zero = empty---- | /O(n)/. Add a delta to each interval in the map-offset :: (Ord v, Monoid v) => v -> IntervalMap v a -> IntervalMap v a -offset v (IntervalMap m) = IntervalMap $ FT.fmap' (first (mappend v)) m---- | /O(1)/. Interval map with a single entry.-singleton :: Ord v => Interval v -> a -> IntervalMap v a-singleton i x = IntervalMap (FT.singleton (Node i x))---- | /O(log n)/. Insert an interval into a map.--- The map may contain duplicate intervals; the new entry will be inserted--- before any existing entries for the same interval.-insert :: Ord v => v -> v -> a -> IntervalMap v a -> IntervalMap v a-insert lo hi _ m | lo > hi = m-insert lo hi x (IntervalMap t) = IntervalMap (l >< Node i x <| r) where - i = Interval lo hi- (l, r) = FT.split larger t- larger (IntInterval k _) = k >= i- larger _ = largerError---- | /O(k log (n/\//k))/. All intervals that contain the given interval,--- in lexicographical order.-dominators :: Ord v => v -> v -> IntervalMap v a -> [(Interval v, a)]-dominators i j = intersections j i ---- | /O(k log (n/\//k))/. All intervals that contain the given point,--- in lexicographical order.-search :: Ord v => v -> IntervalMap v a -> [(Interval v, a)]-search p = intersections p p---- | /O(k log (n/\//k))/. All intervals that intersect with the given--- interval, in lexicographical order.-intersections :: Ord v => v -> v -> IntervalMap v a -> [(Interval v, a)]-intersections lo hi (IntervalMap t) = matches (FT.takeUntil (greater hi) t) where - matches xs = case FT.viewl (FT.dropUntil (atleast lo) xs) of- EmptyL -> []- Node i x :< xs' -> (i, x) : matches xs'--atleast :: Ord v => v -> IntInterval v -> Bool-atleast k (IntInterval _ hi) = k <= hi-atleast _ _ = False--greater :: Ord v => v -> IntInterval v -> Bool-greater k (IntInterval i _) = low i > k-greater _ _ = False--fromList :: Ord v => [(v, v, a)] -> IntervalMap v a-fromList = foldr ins empty where - ins (lo, hi, n) = insert lo hi n-
− Text/Trifecta/Language.hs
@@ -1,34 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Language--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Language- ( Language(..)- , runLanguage- , LanguageDef(..)- , MonadLanguage(..)- , asksLanguage- , identifier- , reserved- , reservedByteString- , op- , reservedOp- , reservedOpByteString- , emptyLanguageDef- , haskellLanguageDef- , haskell98LanguageDef- ) where--import Text.Trifecta.Language.Class-import Text.Trifecta.Language.Combinators-import Text.Trifecta.Language.Prim-import Text.Trifecta.Language.Monad-import Text.Trifecta.Language.Style-
− Text/Trifecta/Language/Class.hs
@@ -1,59 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Language.Class--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Language.Class- ( MonadLanguage(..)- , asksLanguage- ) where--import Control.Monad (liftM)-import Control.Monad.Trans.Class-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Identity-import qualified Control.Monad.Trans.Writer.Strict as Strict-import qualified Control.Monad.Trans.State.Strict as Strict-import qualified Control.Monad.Trans.RWS.Strict as Strict-import qualified Control.Monad.Trans.Writer.Lazy as Lazy-import qualified Control.Monad.Trans.State.Lazy as Lazy-import qualified Control.Monad.Trans.RWS.Lazy as Lazy-import Data.Monoid-import Text.Trifecta.Language.Prim-import Text.Trifecta.Parser.Class--class MonadParser m => MonadLanguage m where- askLanguage :: m (LanguageDef m)--asksLanguage :: MonadLanguage m => (LanguageDef m -> r) -> m r-asksLanguage f = liftM f askLanguage--instance MonadLanguage m => MonadLanguage (Strict.StateT s m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance MonadLanguage m => MonadLanguage (Lazy.StateT s m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance (Monoid w, MonadLanguage m) => MonadLanguage (Strict.WriterT w m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance (Monoid w, MonadLanguage m) => MonadLanguage (Lazy.WriterT w m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance MonadLanguage m => MonadLanguage (ReaderT s m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance MonadLanguage m => MonadLanguage (IdentityT m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance (Monoid w, MonadLanguage m) => MonadLanguage (Strict.RWST r w s m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance (Monoid w, MonadLanguage m) => MonadLanguage (Lazy.RWST r w s m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage
− Text/Trifecta/Language/Combinators.hs
@@ -1,42 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Language.Combinators--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Language.Combinators- ( identifier- , reserved- , reservedByteString- , op- , reservedOp- , reservedOpByteString- ) where--import Data.ByteString-import Text.Trifecta.Language.Class-import Text.Trifecta.Language.Prim-import Text.Trifecta.Parser.Identifier--identifier :: MonadLanguage m => m ByteString-identifier = asksLanguage languageIdentifierStyle >>= ident--reserved :: MonadLanguage m => String -> m ()-reserved i = asksLanguage languageIdentifierStyle >>= \style -> reserve style i--reservedByteString :: MonadLanguage m => ByteString -> m ()-reservedByteString i = asksLanguage languageIdentifierStyle >>= \style -> reserveByteString style i--op :: MonadLanguage m => m ByteString-op = asksLanguage languageOperatorStyle >>= ident--reservedOp :: MonadLanguage m => String -> m ()-reservedOp i = asksLanguage languageOperatorStyle >>= \style -> reserve style i--reservedOpByteString :: MonadLanguage m => ByteString -> m ()-reservedOpByteString i = asksLanguage languageOperatorStyle >>= \style -> reserveByteString style i
− Text/Trifecta/Language/Monad.hs
@@ -1,79 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GeneralizedNewtypeDeriving #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Language.Monad--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Language.Monad- ( Language(..)- , runLanguage- ) where--import Control.Applicative-import Control.Monad ()-import Control.Monad.Trans.Class-import Control.Monad.Reader-import Control.Monad.Writer.Class-import Control.Monad.State.Class-import Control.Monad.Cont.Class-import Text.Trifecta.Diagnostic.Class-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Mark-import Text.Trifecta.Parser.Token.Style-import Text.Trifecta.Language.Prim-import Text.Trifecta.Language.Class--newtype Language m a = Language { unlanguage :: ReaderT (LanguageDef (Language m)) m a }- deriving (Functor,Applicative,Alternative,Monad,MonadPlus,MonadCont)--runLanguage :: Language m a -> LanguageDef (Language m) -> m a-runLanguage = runReaderT . unlanguage--instance MonadParser m => MonadLanguage (Language m) where- askLanguage = Language ask--instance MonadTrans Language where- lift = Language . lift--instance MonadParser m => MonadParser (Language m) where- highlightInterval h s e = lift $ highlightInterval h s e- someSpace = asksLanguage languageCommentStyle >>= buildSomeSpaceParser (lift someSpace)- nesting (Language (ReaderT m)) = Language $ ReaderT $ nesting . m- semi = lift semi- try (Language m) = Language $ try m- labels (Language m) ss = Language $ labels m ss- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- skipping = lift . skipping- unexpected = lift . unexpected- position = lift position- line = lift line- lookAhead (Language m) = Language (lookAhead m)- slicedWith f (Language m) = Language $ ReaderT $ slicedWith f . runReaderT m--instance MonadMark d m => MonadMark d (Language m) where- mark = lift mark- release = lift . release--instance MonadDiagnostic e m => MonadDiagnostic e (Language m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance MonadState s m => MonadState s (Language m) where- get = Language $ lift get- put s = Language $ lift $ put s--instance MonadWriter w m => MonadWriter w (Language m) where- tell = Language . lift . tell- pass = Language . pass . unlanguage- listen = Language . listen . unlanguage--instance MonadReader e m => MonadReader e (Language m) where- ask = Language $ lift ask- local f (Language m) = Language $ ReaderT $ \e -> local f (runReaderT m e)
− Text/Trifecta/Language/Prim.hs
@@ -1,28 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Language.Prim--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Language.Prim- ( LanguageDef(..)- , liftLanguageDef- ) where--import Control.Monad.Trans.Class-import Text.Trifecta.Parser.Token.Style-import Text.Trifecta.Parser.Identifier--data LanguageDef m = LanguageDef- { languageCommentStyle :: CommentStyle- , languageIdentifierStyle :: IdentifierStyle m- , languageOperatorStyle :: IdentifierStyle m- }--liftLanguageDef :: (MonadTrans t, Monad m) => LanguageDef m -> LanguageDef (t m)-liftLanguageDef (LanguageDef c i o) = LanguageDef c (liftIdentifierStyle i) (liftIdentifierStyle o)
− Text/Trifecta/Language/Style.hs
@@ -1,26 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Language.Style--- Copyright : (c) Edward Kmett 2011--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable--- -------------------------------------------------------------------------------module Text.Trifecta.Language.Style- ( emptyLanguageDef- , haskellLanguageDef- , haskell98LanguageDef- ) where--import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Token.Style-import Text.Trifecta.Parser.Identifier.Style-import Text.Trifecta.Language.Prim--emptyLanguageDef, haskellLanguageDef, haskell98LanguageDef :: MonadParser m => LanguageDef m-emptyLanguageDef = LanguageDef emptyCommentStyle emptyIdents emptyOps-haskellLanguageDef = LanguageDef haskellCommentStyle haskellIdents haskellOps-haskell98LanguageDef = LanguageDef haskellCommentStyle haskell98Idents haskell98Ops
− Text/Trifecta/Layout.hs
@@ -1,23 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Layout--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Layout- ( Layout(..)- , LayoutMark(..)- , MonadLayout(..)- , LayoutState(..)- , runLayout- , defaultLayoutState- ) where--import Text.Trifecta.Layout.Monad-import Text.Trifecta.Layout.Class-import Text.Trifecta.Layout.Prim
− Text/Trifecta/Layout/Class.hs
@@ -1,64 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Layout.Class--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Layout.Class- ( MonadLayout(..)- ) where--import Data.Monoid-import Control.Monad.Trans.Class-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Identity-import qualified Control.Monad.Trans.State.Lazy as Lazy-import qualified Control.Monad.Trans.State.Strict as Strict-import qualified Control.Monad.Trans.Writer.Lazy as Lazy-import qualified Control.Monad.Trans.Writer.Strict as Strict-import qualified Control.Monad.Trans.RWS.Lazy as Lazy-import qualified Control.Monad.Trans.RWS.Strict as Strict-import Text.Trifecta.Layout.Prim-import Text.Trifecta.Parser.Class--class MonadParser m => MonadLayout m where- layout :: m LayoutToken- layoutState :: (LayoutState -> (a, LayoutState)) -> m a--instance MonadLayout m => MonadLayout (Strict.StateT s m) where- layout = lift layout- layoutState = lift . layoutState--instance MonadLayout m => MonadLayout (Lazy.StateT s m) where- layout = lift layout- layoutState = lift . layoutState--instance MonadLayout m => MonadLayout (ReaderT e m) where- layout = lift layout- layoutState = lift . layoutState--instance (Monoid w, MonadLayout m) => MonadLayout (Strict.WriterT w m) where- layout = lift layout- layoutState = lift . layoutState--instance (Monoid w, MonadLayout m) => MonadLayout (Lazy.WriterT w m) where- layout = lift layout- layoutState = lift . layoutState--instance (Monoid w, MonadLayout m) => MonadLayout (Strict.RWST r w s m) where- layout = lift layout- layoutState = lift . layoutState--instance (Monoid w, MonadLayout m) => MonadLayout (Lazy.RWST r w s m) where- layout = lift layout- layoutState = lift . layoutState--instance MonadLayout m => MonadLayout (IdentityT m) where- layout = lift layout- layoutState = lift . layoutState
− Text/Trifecta/Layout/Combinators.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Layout.Combinators--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Layout.Combinators- ( layoutEq- , getLayout- , setLayout- , modLayout- , disableLayout- , enableLayout- , laidout- ) where--import Control.Applicative-import Control.Monad (guard)-import Data.Lens.Common-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Token.Combinators-import qualified Text.Trifecta.Highlight.Prim as Highlight-import Text.Trifecta.Layout.Class-import Text.Trifecta.Layout.Prim--getLayout :: MonadLayout m => Lens LayoutState t -> m t-getLayout l = layoutState $ \s -> (getL l s, s)--setLayout :: MonadLayout m => Lens LayoutState t -> t -> m ()-setLayout l t = layoutState $ \s -> ((), setL l t s)--modLayout :: MonadLayout m => Lens LayoutState t -> (t -> t) -> m ()-modLayout l f = layoutState $ \s -> ((), modL l f s)--disableLayout :: MonadLayout m => m a -> m a-disableLayout p = do- r <- rend- modLayout layoutStack (DisabledLayout r:)- result <- p- stk <- getLayout layoutStack- case stk of- DisabledLayout r':xs | delta r == delta r' -> result <$ setLayout layoutStack xs- _ -> unexpected "layout"--enableLayout :: MonadLayout m => m a -> m a-enableLayout p = do- result <- highlight Highlight.Layout $ do- r <- rend- modLayout layoutStack (IndentedLayout r:)- p- result <$ layout <?> "virtual right brace"--laidout :: MonadLayout m => m a -> m a-laidout p = braces p <|> enableLayout p--layoutEq :: MonadLayout m => LayoutToken -> m ()-layoutEq s = try $ do- r <- layout- guard (s == r)-
− Text/Trifecta/Layout/Monad.hs
@@ -1,112 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, GeneralizedNewtypeDeriving, FlexibleInstances, UndecidableInstances #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Layout.Monad--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Layout.Monad- ( Layout(..)- , runLayout- ) where--import Control.Applicative-import Control.Category-import Control.Monad-import Control.Monad.State.Class-import Control.Monad.Trans.State.Strict (StateT(..))-import Control.Monad.Writer.Class-import Control.Monad.Reader.Class-import Control.Monad.Cont.Class-import Control.Monad.Trans.Class-import Prelude hiding ((.), id)-import Text.Trifecta.Diagnostic.Class-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Mark-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Layout.Prim-import Text.Trifecta.Layout.Class-import Text.Trifecta.Layout.Combinators-import Text.Trifecta.Rope.Delta---- | Adds Haskell-style "layout" to base parser-newtype Layout m a = Layout { unlayout :: StateT LayoutState m a }- deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadTrans, MonadCont)--runLayout :: Monad m => Layout m a -> LayoutState -> m (a, LayoutState)-runLayout = runStateT . unlayout--instance MonadParser m => MonadParser (Layout m) where- satisfy p = try $ layoutEq Other *> lift (satisfy p)- satisfy8 p = try $ layoutEq Other *> lift (satisfy8 p)- line = lift line- unexpected = lift . unexpected- try = Layout . try . unlayout- labels m s = Layout $ labels (unlayout m) s- skipMany = Layout . skipMany . unlayout- highlightInterval h s e = lift $ highlightInterval h s e- someSpace = try $ (layoutEq WhiteSpace <?> "")- nesting (Layout m) = disableLayout $ Layout (nesting m)- semi = getLayout layoutStack >>= \ stk -> case stk of- (DisabledLayout _:_) -> lift semi- _ -> try (';' <$ layoutEq VirtualSemi <?> "virtual semi-colon")- <|> lift semi- skipping = lift . skipping- position = lift position- slicedWith f (Layout m) = Layout $ slicedWith f m- lookAhead (Layout m) = Layout $ lookAhead m--instance MonadMark d m => MonadMark (LayoutMark d) (Layout m) where- mark = LayoutMark <$> getLayout id <*> lift mark- release (LayoutMark s m) = lift (release m) *> setLayout id s--instance MonadDiagnostic e m => MonadDiagnostic e (Layout m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance MonadParser m => MonadLayout (Layout m) where- layout = buildLayoutParser (lift whiteSpace)- layoutState f = Layout . StateT $ return . f--buildLayoutParser :: MonadLayout m => m () -> m LayoutToken-buildLayoutParser realWhiteSpace = do- bol <- getLayout layoutBol- m <- position- realWhiteSpace- r <- position- if near m r && not bol- then onside m r- else getLayout layoutStack >>= \stk -> case compare (column r) (depth stk) of- GT -> onside m r- EQ -> return VirtualSemi- LT -> case stk of- (IndentedLayout _:xs) -> VirtualRightBrace <$ setLayout layoutStack xs <* setLayout layoutBol True- _ -> unexpected "layout context"- where- onside m r- | r /= m = pure WhiteSpace- | otherwise = setLayout layoutBol False *> option Other (VirtualRightBrace <$ eof <* trailing)- trailing = getLayout layoutStack >>= \ stk -> case stk of- (IndentedLayout _:xs) -> setLayout layoutStack xs- _ -> empty- depth [] = 0- depth (IndentedLayout r:_) = column r- depth (DisabledLayout _:_) = -1--instance MonadState s m => MonadState s (Layout m) where- get = Layout $ lift get- put = Layout . lift . put--instance MonadReader e m => MonadReader e (Layout m) where- ask = Layout $ lift ask- local f (Layout m) = Layout $ local f m--instance MonadWriter w m => MonadWriter w (Layout m) where- tell = Layout . lift . tell- listen (Layout m) = Layout $ listen m- pass (Layout m) = Layout $ pass m
− Text/Trifecta/Layout/Prim.hs
@@ -1,86 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Layout.Prim--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Layout.Prim- ( LayoutToken(..)- , LayoutState(..)- , LayoutContext(..)- , LayoutMark(..)- , defaultLayoutState- , layoutBol- , layoutStack- ) where--import Data.Functor-import Data.Lens.Common-import Data.Foldable-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Data.Traversable-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Diagnostic.Rendering.Prim--data LayoutToken- = VirtualSemi- | VirtualRightBrace- | WhiteSpace- | Other- deriving (Eq,Ord,Show,Read)--data LayoutContext- = IndentedLayout Rendering- | DisabledLayout Rendering--instance HasDelta LayoutContext where- delta (IndentedLayout r) = delta r- delta (DisabledLayout r) = delta r--instance HasBytes LayoutContext where- bytes = bytes . delta--data LayoutState = LayoutState- { _layoutBol :: Bool- , _layoutStack :: [LayoutContext]- }--defaultLayoutState :: LayoutState-defaultLayoutState = LayoutState False []--layoutBol :: Lens LayoutState Bool-layoutBol = lens _layoutBol (\s l -> l { _layoutBol = s})--layoutStack :: Lens LayoutState [LayoutContext]-layoutStack = lens _layoutStack (\s l -> l { _layoutStack = s})--data LayoutMark d = LayoutMark LayoutState d--instance Functor LayoutMark where- fmap f (LayoutMark s a) = LayoutMark s (f a)--instance Foldable LayoutMark where- foldMap f (LayoutMark _ a) = f a--instance Traversable LayoutMark where- traverse f (LayoutMark s a) = LayoutMark s <$> f a--instance Foldable1 LayoutMark where- foldMap1 f (LayoutMark _ a) = f a--instance Traversable1 LayoutMark where- traverse1 f (LayoutMark s a) = LayoutMark s <$> f a--instance HasDelta d => HasDelta (LayoutMark d) where- delta (LayoutMark _ d) = delta d--instance HasBytes d => HasBytes (LayoutMark d) where- bytes (LayoutMark _ d) = bytes d
− Text/Trifecta/Literate.hs
@@ -1,23 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Literate--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Literate- ( Literate(..)- , LiterateMark(..)- , MonadLiterate(..)- , LiterateState(..)- , runLiterate- , defaultLiterateState- ) where--import Text.Trifecta.Literate.Monad-import Text.Trifecta.Literate.Class-import Text.Trifecta.Literate.Prim
− Text/Trifecta/Literate/Class.hs
@@ -1,54 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Literate.Class--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Literate.Class- ( MonadLiterate(..)- ) where--import Control.Monad.Trans.Class-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Identity-import qualified Control.Monad.Trans.State.Strict as Strict-import qualified Control.Monad.Trans.State.Lazy as Lazy-import qualified Control.Monad.Trans.Writer.Strict as Strict-import qualified Control.Monad.Trans.Writer.Lazy as Lazy-import qualified Control.Monad.Trans.RWS.Strict as Strict-import qualified Control.Monad.Trans.RWS.Lazy as Lazy-import Data.Monoid-import Text.Trifecta.Parser.Class-import Text.Trifecta.Literate.Prim--class MonadParser m => MonadLiterate m where- literateState :: (LiterateState -> (a, LiterateState)) -> m a--instance MonadLiterate m => MonadLiterate (Strict.StateT s m) where- literateState = lift . literateState--instance MonadLiterate m => MonadLiterate (Lazy.StateT s m) where- literateState = lift . literateState--instance (Monoid w, MonadLiterate m) => MonadLiterate (Strict.WriterT w m) where- literateState = lift . literateState--instance (Monoid w, MonadLiterate m) => MonadLiterate (Lazy.WriterT w m) where- literateState = lift . literateState--instance (Monoid w, MonadLiterate m) => MonadLiterate (Strict.RWST r w s m) where- literateState = lift . literateState--instance (Monoid w, MonadLiterate m) => MonadLiterate (Lazy.RWST r w s m) where- literateState = lift . literateState--instance MonadLiterate m => MonadLiterate (IdentityT m) where- literateState = lift . literateState--instance MonadLiterate m => MonadLiterate (ReaderT e m) where- literateState = lift . literateState
− Text/Trifecta/Literate/Combinators.hs
@@ -1,85 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Literate.Combinators--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Literate.Combinators- ( someLiterateSpace- , getLiterate- , putLiterate- ) where--import Data.Char (isSpace)-import Control.Applicative-import Control.Monad-import Text.Trifecta.Rope.Delta-import qualified Text.Trifecta.Highlight.Prim as Highlight-import Text.Trifecta.Literate.Prim-import Text.Trifecta.Literate.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Combinators--getLiterate :: MonadLiterate m => m LiterateState-getLiterate = literateState $ \s -> (s, s)--putLiterate :: MonadLiterate m => LiterateState -> m ()-putLiterate s = literateState $ \_ -> ((), s)--skipLine :: MonadParser m => m ()-skipLine = do- r <- restOfLine- skipping (delta r)--someLiterateSpace :: MonadLiterate m => m ()-someLiterateSpace = do- s <- getLiterate- case s of- IlliterateStart -> skipSome $ satisfy isSpace- LiterateStart -> position >>= \m -> track m <|> begin m <|> blank m <|> other m- LiterateCode -> do- skipSome $ satisfy isSpace- option () $ position >>= \m -> when (column m == 0) $ do- highlight Highlight.LiterateSyntax (string "\\end{code}") *> skipLine- begin m <|> blank m <|> other m- LiterateTrack -> skipSome horizontalSpace >> skipOptional bird- <|> bird- where- bird = newline *> position >>= \m -> track m <|> blank m---- parse space excluding newlines-horizontalSpace :: MonadLiterate m => m Char-horizontalSpace = satisfy $ \s -> s /= '\n' && isSpace s--track, begin, blank, other :: MonadLiterate m => Delta -> m ()-track s = do- e <- position- try $ highlight Highlight.LiterateSyntax (char '>')- *> highlightInterval Highlight.LiterateComment s e- *> skipSome horizontalSpace- tracks <|> putLiterate LiterateTrack where- tracks = do- s' <- newline *> position- track s' <|> blank s'--begin s = do- try $ highlight Highlight.LiterateSyntax (string "\begin{code}") *> skipLine- position >>= highlightInterval Highlight.LiterateComment s- putLiterate LiterateCode- whiteSpace--other s = do- notChar '>' *> skipLine- begin s <|> blank s <|> other s--blank s = do- k <- try $ do- skipMany horizontalSpace- True <$ newline <|> False <$ eof- when k $ track s <|> begin s <|> blank s <|> other s
− Text/Trifecta/Literate/Monad.hs
@@ -1,94 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GeneralizedNewtypeDeriving #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Literate.Monad--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Literate.Monad- ( Literate(..)- , runLiterate- ) where--import Control.Applicative-import Control.Monad-import Control.Monad.Trans.State.Strict (StateT(..))-import Control.Monad.Trans.Class-import Control.Monad.State.Class-import Control.Monad.Cont.Class-import Control.Monad.Reader.Class-import Control.Monad.Writer.Class-import Data.Semigroup-import Text.Trifecta.Diagnostic.Class-import Text.Trifecta.Language.Prim-import Text.Trifecta.Language.Class-import Text.Trifecta.Literate.Prim-import Text.Trifecta.Literate.Class-import Text.Trifecta.Literate.Combinators-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Parser.Mark-import Text.Trifecta.Rope.Delta--newtype Literate m a = Literate { unliterate :: StateT LiterateState m a }- deriving (Functor,Applicative,Alternative,Monad,MonadPlus,MonadTrans,MonadCont)--runLiterate :: Monad m => Literate m a -> LiterateState -> m (a, LiterateState)-runLiterate = runStateT . unliterate--instance MonadParser m => MonadParser (Literate m) where- someSpace = someLiterateSpace- highlightInterval h s e = lift $ highlightInterval h s e- try (Literate m) = Literate $ try m- nesting (Literate m) = Literate $ nesting m- skipMany (Literate m) = Literate $ skipMany m- slicedWith f (Literate m) = Literate $ slicedWith f m- labels (Literate m) p = Literate $ labels m p- semi = lift semi- line = lift line- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- unexpected = lift . unexpected- position = lift position- skipping d- | near (Columns 0 0) d = lift $ skipping d -- we don't change literate states within a line- | otherwise = do- s <- position- let e = s <> d- () <$ (manyTill (someSpace <|> () <$ anyChar) $ position >>= \p -> guard (e <= p))- lookAhead (Literate (StateT p)) = Literate $ StateT $ \s -> do- as' <- lookAhead $ p s- return (fst as', s)--instance MonadParser m => MonadLiterate (Literate m) where- literateState f = Literate $ StateT $ return . f--instance MonadMark d m => MonadMark (LiterateMark d) (Literate m) where- mark = LiterateMark <$> getLiterate <*> lift mark- release (LiterateMark s d) = lift (release d) *> putLiterate s--instance MonadLanguage m => MonadLanguage (Literate m) where- askLanguage = liftM liftLanguageDef $ lift askLanguage--instance MonadDiagnostic e m => MonadDiagnostic e (Literate m) where- throwDiagnostic = lift . throwDiagnostic- logDiagnostic = lift . logDiagnostic--instance MonadState s m => MonadState s (Literate m) where- get = lift get- put = lift . put--instance MonadReader e m => MonadReader e (Literate m) where- ask = lift ask- local f (Literate m) = Literate $ local f m--instance MonadWriter w m => MonadWriter w (Literate m) where- tell = lift . tell- listen (Literate m) = Literate $ listen m- pass (Literate m) = Literate $ pass m
− Text/Trifecta/Literate/Prim.hs
@@ -1,60 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Literate.Prim--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Literate.Prim- ( LiterateState(..)- , defaultLiterateState- , LiterateMark(..)- ) where--import Data.Functor-import Data.Foldable-import Data.Traversable-import Data.Semigroup-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta--data LiterateState- = LiterateStart -- ^ Parsing literate syntax- | IlliterateStart -- ^ Disable literate parsing- | LiterateCode -- ^ In the midst of a @\begin{code} ... \end{code}@ block- | LiterateTrack -- ^ In the midst of a @> ...@ block--defaultLiterateState :: LiterateState-defaultLiterateState = LiterateStart--data LiterateMark d = LiterateMark LiterateState d--instance Functor LiterateMark where- fmap f (LiterateMark s a) = LiterateMark s (f a)--instance Foldable LiterateMark where- foldMap f (LiterateMark _ a) = f a--instance Traversable LiterateMark where- traverse f (LiterateMark s a) = LiterateMark s <$> f a--instance Foldable1 LiterateMark where- foldMap1 f (LiterateMark _ a) = f a--instance Traversable1 LiterateMark where- traverse1 f (LiterateMark s a) = LiterateMark s <$> f a--instance HasDelta d => HasDelta (LiterateMark d) where- delta (LiterateMark _ d) = delta d--instance HasBytes d => HasBytes (LiterateMark d) where- bytes (LiterateMark _ d) = bytes d--instance Semigroup d => Semigroup (LiterateMark d) where- LiterateMark _ d <> LiterateMark s e = LiterateMark s (d <> e)
− Text/Trifecta/Parser.hs
@@ -1,47 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Parser- ( module Text.Trifecta.Parser.ByteString- , module Text.Trifecta.Parser.Char- , module Text.Trifecta.Parser.Class- , module Text.Trifecta.Parser.Combinators- , module Text.Trifecta.Parser.Identifier- , module Text.Trifecta.Parser.Prim- , module Text.Trifecta.Parser.Result- , module Text.Trifecta.Parser.Rich- , module Text.Trifecta.Parser.Token- -- * Expressive Diagnostics- -- ** Text.Trifecta.Diagnostic.Rendering.Caret- , caret- , careted- -- ** Text.Trifecta.Diagnostic.Rendering.Span- , span- , spanned- -- ** Text.Trifecta.Diagnostic.Rendering.Fixit- , fixit-- ) where--import Text.Trifecta.Diagnostic.Rendering.Caret (caret, careted)-import Text.Trifecta.Diagnostic.Rendering.Span (span, spanned)-import Text.Trifecta.Diagnostic.Rendering.Fixit (fixit)-import Text.Trifecta.Parser.ByteString-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Parser.Identifier-import Text.Trifecta.Parser.Prim-import Text.Trifecta.Parser.Result-import Text.Trifecta.Parser.Rich-import Text.Trifecta.Parser.Token--import Prelude ()
− Text/Trifecta/Parser/ByteString.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, Rank2Types #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.ByteString--- Copyright : (c) Edward Kmett 2011--- License : BSD-style (see the LICENSE file)------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable (mptcs, fundeps)------ Loading a file as a strict bytestring in one step.------------------------------------------------------------------------------------module Text.Trifecta.Parser.ByteString- ( parseFromFile- , parseFromFileEx- , parseByteString- , parseTest- ) where--import Control.Applicative-import Control.Monad (unless)-import Data.Semigroup-import Data.Foldable-import qualified Data.ByteString as B-import System.Console.Terminfo.PrettyPrint-import Text.Trifecta.Parser.Mark-import Text.Trifecta.Parser.Prim-import Text.Trifecta.Parser.Step-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Parser.Result-import Data.Sequence as Seq-import qualified Data.ByteString.UTF8 as UTF8----- | @parseFromFile p filePath@ runs a parser @p@ on the--- input read from @filePath@ using 'ByteString.readFile'. All diagnostic messages--- emitted over the course of the parse attempt are shown to the user on the console.------ > main = do--- > result <- parseFromFile numbers "digits.txt"--- > case result of--- > Nothing -> return ()--- > Just a -> print $ sum a--parseFromFile :: Show a => (forall r. Parser r String a) -> String -> IO (Maybe a)-parseFromFile p fn = do- result <- parseFromFileEx p fn- case result of- Success xs a -> Just a <$ unless (Seq.null xs) (displayLn (toList xs))- Failure xs -> Nothing <$ unless (Seq.null xs) (displayLn (toList xs))---- | @parseFromFileEx p filePath@ runs a parser @p@ on the--- input read from @filePath@ using 'ByteString.readFile'. Returns all diagnostic messages--- emitted over the course of the parse and the answer if the parse was successful.------ > main = do--- > result <- parseFromFileEx (many number) "digits.txt"--- > case result of--- > Failure xs -> unless (Seq.null xs) $ displayLn xs--- > Success xs a ->--- > unless (Seq.null xs) $ displayLn xs--- > print $ sum a--- >--parseFromFileEx :: Show a => (forall r. Parser r String a) -> String -> IO (Result TermDoc a)-parseFromFileEx p fn = parseByteString p (Directed (UTF8.fromString fn) 0 0 0 0) <$> B.readFile fn---- | @parseByteString p delta i@ runs a parser @p@ on @i@.--parseByteString :: Show a => (forall r. Parser r String a) -> Delta -> UTF8.ByteString -> Result TermDoc a-parseByteString p d inp = starve- $ feed inp- $ stepParser (fmap prettyTerm)- (why prettyTerm)- (release d *> p)- mempty- True- mempty- mempty---parseTest :: Show a => (forall r. Parser r String a) -> String -> IO ()-parseTest p s = case parseByteString p mempty (UTF8.fromString s) of- Failure xs -> displayLn $ toList xs- Success xs a -> do- unless (Seq.null xs) $ displayLn $ toList xs- print a-
− Text/Trifecta/Parser/Char.hs
@@ -1,204 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts, PatternGuards #-}-{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Char--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Parser.Char- ( oneOf -- :: MonadParser m => [Char] -> m Char- , noneOf -- :: MonadParser m => [Char] -> m Char- , oneOfSet -- :: MonadParser m => CharSet -> m Char- , noneOfSet -- :: MonadParser m => CharSet -> m Char- , spaces -- :: MonadParser m => m ()- , space -- :: MonadParser m => m Char- , newline -- :: MonadParser m => m Char- , tab -- :: MonadParser m => m Char- , upper -- :: MonadParser m => m Char- , lower -- :: MonadParser m => m Char- , alphaNum -- :: MonadParser m => m Char- , letter -- :: MonadParser m => m Char- , digit -- :: MonadParser m => m Char- , hexDigit -- :: MonadParser m => m Char- , octDigit -- :: MonadParser m => m Char- , char -- :: MonadParser m => Char -> m Char- , notChar -- :: MonadParser m => Char -> m Char- , anyChar -- :: MonadParser m => m Char- , string -- :: MonadParser m => String -> m String- , byteString -- :: MonadParser m => ByteString -> m ByteString- ) where--import Data.Char-import Control.Applicative-import Control.Monad (guard)-import Text.Trifecta.Parser.Class-import Text.Trifecta.Rope.Delta-import qualified Data.IntSet as IntSet-import Data.CharSet (CharSet(..))-import qualified Data.CharSet as CharSet-import qualified Data.CharSet.ByteSet as ByteSet-import qualified Data.ByteString as Strict-import Data.ByteString.Internal (w2c,c2w)-import Data.ByteString.UTF8 as UTF8---- | @oneOf cs@ succeeds if the current character is in the supplied--- list of characters @cs@. Returns the parsed character. See also--- 'satisfy'.--- --- > vowel = oneOf "aeiou"-oneOf :: MonadParser m => [Char] -> m Char-oneOf xs = oneOfSet (CharSet.fromList xs)-{-# INLINE oneOf #-}---- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current--- character /not/ in the supplied list of characters @cs@. Returns the--- parsed character.------ > consonant = noneOf "aeiou"-noneOf :: MonadParser m => [Char] -> m Char-noneOf xs = noneOfSet (CharSet.fromList xs)-{-# INLINE noneOf #-}---- | @oneOfSet cs@ succeeds if the current character is in the supplied--- set of characters @cs@. Returns the parsed character. See also--- 'satisfy'.--- --- > vowel = oneOf "aeiou"-oneOfSet :: MonadParser m => CharSet -> m Char-oneOfSet (CharSet True bs is)- | (_,r) <- IntSet.split 0x80 is, IntSet.null r = w2c <$> satisfy8 (\w -> ByteSet.member w bs)- | otherwise = satisfy (\c -> IntSet.member (fromEnum c) is)-oneOfSet (CharSet False bs is) - | (_,r) <- IntSet.split 0x80 is, not (IntSet.null r) = satisfy (\c -> not (IntSet.member (fromEnum c) is))- | otherwise = satisfyAscii (\c -> not (ByteSet.member (c2w c) bs))-{-# INLINE oneOfSet #-}- --- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current--- character /not/ in the supplied list of characters @cs@. Returns the--- parsed character.------ > consonant = noneOf "aeiou"-noneOfSet :: MonadParser m => CharSet -> m Char-noneOfSet s = oneOfSet (CharSet.complement s)-{-# INLINE noneOfSet #-}---- | Skips /zero/ or more white space characters. See also 'skipMany' and--- 'whiteSpace'.-spaces :: MonadParser m => m ()-spaces = skipMany space <?> "white space"---- | Parses a white space character (any character which satisfies 'isSpace')--- Returns the parsed character. -space :: MonadParser m => m Char-space = satisfy isSpace <?> "space"-{-# INLINE space #-}---- | Parses a newline character (\'\\n\'). Returns a newline character. -newline :: MonadParser m => m Char-newline = char '\n' <?> "new-line"-{-# INLINE newline #-}---- | Parses a tab character (\'\\t\'). Returns a tab character. -tab :: MonadParser m => m Char-tab = char '\t' <?> "tab"-{-# INLINE tab #-}---- | Parses an upper case letter (a character between \'A\' and \'Z\').--- Returns the parsed character. -upper :: MonadParser m => m Char-upper = satisfy isUpper <?> "uppercase letter"-{-# INLINE upper #-}---- | Parses a lower case character (a character between \'a\' and \'z\').--- Returns the parsed character. -lower :: MonadParser m => m Char-lower = satisfy isLower <?> "lowercase letter"-{-# INLINE lower #-}---- | Parses a letter or digit (a character between \'0\' and \'9\').--- Returns the parsed character. --alphaNum :: MonadParser m => m Char-alphaNum = satisfy isAlphaNum <?> "letter or digit"-{-# INLINE alphaNum #-}---- | Parses a letter (an upper case or lower case character). Returns the--- parsed character. --letter :: MonadParser m => m Char-letter = satisfy isAlpha <?> "letter"-{-# INLINE letter #-}---- | Parses a digit. Returns the parsed character. --digit :: MonadParser m => m Char-digit = satisfy isDigit <?> "digit"-{-# INLINE digit #-}---- | Parses a hexadecimal digit (a digit or a letter between \'a\' and--- \'f\' or \'A\' and \'F\'). Returns the parsed character. -hexDigit :: MonadParser m => m Char-hexDigit = satisfy isHexDigit <?> "hexadecimal digit"-{-# INLINE hexDigit #-}---- | Parses an octal digit (a character between \'0\' and \'7\'). Returns--- the parsed character. -octDigit :: MonadParser m => m Char-octDigit = satisfy isOctDigit <?> "octal digit"-{-# INLINE octDigit #-}---- | @char c@ parses a single character @c@. Returns the parsed--- character (i.e. @c@).------ > semiColon = char ';'-char :: MonadParser m => Char -> m Char-char c - | c <= w2c 0x7f, w <- c2w c = w2c <$> satisfy8 (w ==) <?> show [c]- | otherwise = satisfy (c ==) <?> show [c]-{-# INLINE char #-}---- | @notChar c@ parses any single character other than @c@. Returns the parsed--- character.------ > semiColon = char ';'-notChar :: MonadParser m => Char -> m Char-notChar c - | fromEnum c <= 0x7f = satisfyAscii (c /=)- | otherwise = satisfy (c /=)-{-# INLINE notChar #-}---- | This parser succeeds for any character. Returns the parsed character. -anyChar :: MonadParser m => m Char-anyChar = satisfy (const True)---- | @string s@ parses a sequence of characters given by @s@. Returns--- the parsed string (i.e. @s@).------ > divOrMod = string "div" --- > <|> string "mod"-string :: MonadParser m => String -> m String-string s = s <$ byteString (UTF8.fromString s) <?> show s---- | @byteString s@ parses a sequence of bytes given by @s@. Returns--- the parsed byteString (i.e. @s@).------ > divOrMod = string "div" --- > <|> string "mod"-byteString :: MonadParser m => Strict.ByteString -> m Strict.ByteString-byteString bs = do- r <- restOfLine- let lr = Strict.length r- lbs = Strict.length bs- guard $ lr > 0- case compare lbs lr of- LT | bs `Strict.isPrefixOf` r -> bs <$ skipping (delta bs)- EQ | bs == r -> bs <$ skipping (delta bs)- GT | r `Strict.isPrefixOf` bs -> bs <$ skipping (delta r) *> byteString (Strict.drop lr bs)- _ -> empty - <?> show (UTF8.toString bs)
− Text/Trifecta/Parser/Char8.hs
@@ -1,213 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts, PatternGuards #-}-{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Char8--- Copyright : (c) Edward Kmett 2011--- License : BSD-style (see the LICENSE file)--- --- Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable (mptcs, fundeps)--- --- This provides a thin backwards compatibility layer for folks who--- want to write parsers for languages where characters are bytes--- and don't need to deal with unicode issues. Diagnostics will still--- report the correct column number in the absence of high ascii characters--- but if you have those in your source file, you probably aren't going to--- want to draw those to the screen anyways.------------------------------------------------------------------------------------module Text.Trifecta.Parser.Char8- ( satisfy -- :: MonadParser m => (Char -> Bool) -> m Char- , oneOf -- :: MonadParser m => [Char] -> m Char- , noneOf -- :: MonadParser m => [Char] -> m Char- , oneOfSet -- :: MonadParser m => ByteSet -> m Char- , noneOfSet -- :: MonadParser m => ByteSet -> m Char- , spaces -- :: MonadParser m => m ()- , space -- :: MonadParser m => m Char- , newline -- :: MonadParser m => m Char- , tab -- :: MonadParser m => m Char- , upper -- :: MonadParser m => m Char- , lower -- :: MonadParser m => m Char- , alphaNum -- :: MonadParser m => m Char- , letter -- :: MonadParser m => m Char- , digit -- :: MonadParser m => m Char- , hexDigit -- :: MonadParser m => m Char- , octDigit -- :: MonadParser m => m Char- , char -- :: MonadParser m => Char -> m Char- , notChar -- :: MonadParser m => Char -> m Char- , anyChar -- :: MonadParser m => m Char- , string -- :: MonadParser m => String -> m String- , byteString -- :: MonadParser m => ByteString -> m ByteString- ) where--import Data.Char-import Control.Applicative-import Control.Monad (guard)-import Text.Trifecta.Parser.Class hiding (satisfy)-import Text.Trifecta.Rope.Delta-import Data.CharSet.ByteSet (ByteSet(..))-import qualified Data.CharSet.ByteSet as ByteSet-import qualified Data.ByteString as Strict-import Data.ByteString.Internal (w2c,c2w)-import qualified Data.ByteString.Char8 as Char8---- | Using this instead of 'Text.Trifecta.Parser.Class.satisfy'--- you too can time travel back to when men were men and characters--- fit into 8 bits like God intended. It might also be useful--- when writing lots of fiddly protocol code, where the UTF8 decoding--- is probably a very bad idea.-satisfy :: MonadParser m => (Char -> Bool) -> m Char-satisfy f = w2c <$> satisfy8 (\w -> f (w2c w))---- | @oneOf cs@ succeeds if the current character is in the supplied--- list of characters @cs@. Returns the parsed character. See also--- 'satisfy'.--- --- > vowel = oneOf "aeiou"-oneOf :: MonadParser m => [Char] -> m Char-oneOf xs = oneOfSet (ByteSet.fromList (map c2w xs))-{-# INLINE oneOf #-}---- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current--- character /not/ in the supplied list of characters @cs@. Returns the--- parsed character.------ > consonant = noneOf "aeiou"-noneOf :: MonadParser m => [Char] -> m Char-noneOf xs = noneOfSet (ByteSet.fromList (map c2w xs))-{-# INLINE noneOf #-}---- | @oneOfSet cs@ succeeds if the current character is in the supplied--- set of characters @cs@. Returns the parsed character. See also--- 'satisfy'.--- --- > vowel = oneOf "aeiou"-oneOfSet :: MonadParser m => ByteSet -> m Char-oneOfSet bs = w2c <$> satisfy8 (\w -> ByteSet.member w bs)-{-# INLINE oneOfSet #-}- --- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current--- character /not/ in the supplied list of characters @cs@. Returns the--- parsed character.------ > consonant = noneOf "aeiou"-noneOfSet :: MonadParser m => ByteSet -> m Char-noneOfSet s = w2c <$> satisfy8 (\w -> not (ByteSet.member w s))-{-# INLINE noneOfSet #-}---- | Skips /zero/ or more white space characters. See also 'skipMany' and--- 'whiteSpace'.-spaces :: MonadParser m => m ()-spaces = skipMany space <?> "white space"---- | Parses a white space character (any character which satisfies 'isSpace')--- Returns the parsed character. -space :: MonadParser m => m Char-space = satisfy isSpace <?> "space"-{-# INLINE space #-}---- | Parses a newline character (\'\\n\'). Returns a newline character. -newline :: MonadParser m => m Char-newline = char '\n' <?> "new-line"-{-# INLINE newline #-}---- | Parses a tab character (\'\\t\'). Returns a tab character. -tab :: MonadParser m => m Char-tab = char '\t' <?> "tab"-{-# INLINE tab #-}---- | Parses an upper case letter (a character between \'A\' and \'Z\').--- Returns the parsed character. -upper :: MonadParser m => m Char-upper = satisfy isUpper <?> "uppercase letter"-{-# INLINE upper #-}---- | Parses a lower case character (a character between \'a\' and \'z\').--- Returns the parsed character. -lower :: MonadParser m => m Char-lower = satisfy isLower <?> "lowercase letter"-{-# INLINE lower #-}---- | Parses a letter or digit (a character between \'0\' and \'9\').--- Returns the parsed character. --alphaNum :: MonadParser m => m Char-alphaNum = satisfy isAlphaNum <?> "letter or digit"-{-# INLINE alphaNum #-}---- | Parses a letter (an upper case or lower case character). Returns the--- parsed character. --letter :: MonadParser m => m Char-letter = satisfy isAlpha <?> "letter"-{-# INLINE letter #-}---- | Parses a digit. Returns the parsed character. --digit :: MonadParser m => m Char-digit = satisfy isDigit <?> "digit"-{-# INLINE digit #-}---- | Parses a hexadecimal digit (a digit or a letter between \'a\' and--- \'f\' or \'A\' and \'F\'). Returns the parsed character. -hexDigit :: MonadParser m => m Char-hexDigit = satisfy isHexDigit <?> "hexadecimal digit"-{-# INLINE hexDigit #-}---- | Parses an octal digit (a character between \'0\' and \'7\'). Returns--- the parsed character. -octDigit :: MonadParser m => m Char-octDigit = satisfy isOctDigit <?> "octal digit"-{-# INLINE octDigit #-}---- | @char c@ parses a single character @c@. Returns the parsed--- character (i.e. @c@).------ > semiColon = char ';'-char :: MonadParser m => Char -> m Char-char c = satisfy (c ==) <?> show [c]-{-# INLINE char #-}---- | @char c@ parses a single character @c@. Returns the parsed--- character (i.e. @c@).------ > semiColon = char ';'-notChar :: MonadParser m => Char -> m Char-notChar c = satisfy (c /=)-{-# INLINE notChar #-}---- | This parser succeeds for any character. Returns the parsed character. -anyChar :: MonadParser m => m Char-anyChar = satisfy (const True)---- | @string s@ parses a sequence of characters given by @s@. Returns--- the parsed string (i.e. @s@).------ > divOrMod = string "div" --- > <|> string "mod"-string :: MonadParser m => String -> m String-string s = s <$ byteString (Char8.pack s) <?> show s---- | @byteString s@ parses a sequence of bytes given by @s@. Returns--- the parsed byteString (i.e. @s@).------ > divOrMod = string "div" --- > <|> string "mod"-byteString :: MonadParser m => Strict.ByteString -> m Strict.ByteString-byteString bs = do- r <- restOfLine- let lr = Strict.length r- lbs = Strict.length bs- guard $ lr > 0- case compare lbs lr of- LT | bs `Strict.isPrefixOf` r -> bs <$ skipping (delta bs)- | otherwise -> empty- EQ | bs == r -> bs <$ skipping (delta bs)- | otherwise -> empty- GT | r `Strict.isPrefixOf` bs -> bs <$ skipping (delta r) *> byteString (Strict.drop lr bs)- | otherwise -> empty- <?> show (Char8.unpack bs)
− Text/Trifecta/Parser/Class.hs
@@ -1,271 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Class--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable----------------------------------------------------------------------------------module Text.Trifecta.Parser.Class- ( MonadParser(..)- , satisfyAscii- , restOfLine- , (<?>)- , sliced- , rend- , whiteSpace- , highlight- ) where--import Control.Applicative-import Control.Monad (MonadPlus(..))-import Control.Monad.Trans.Class-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-import Control.Monad.Trans.RWS.Lazy as Lazy-import Control.Monad.Trans.RWS.Strict as Strict-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Identity-import Data.Word-import Data.ByteString as Strict-import Data.Char (isSpace)-import Data.ByteString.Internal (w2c)-import Data.Semigroup-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Highlight.Prim-import Text.Trifecta.Diagnostic.Rendering.Prim--infix 0 <?>--class (Alternative m, MonadPlus m) => MonadParser m where- -- | Take a parser that may consume input, and on failure, go back to where we started and fail as if we didn't consume input.- try :: m a -> m a-- -- Used to implement (<?>), runs the parser then sets the 'expected' tokens to the list supplied- labels :: m a -> [String] -> m a-- -- | A version of many that discards its input. Specialized because it can often be implemented more cheaply.- skipMany :: m a -> m ()- skipMany p = () <$ many p-- -- | Parse a single character of the input, with UTF-8 decoding- satisfy :: (Char -> Bool) -> m Char-- -- | Parse a single byte of the input, without UTF-8 decoding- satisfy8 :: (Word8 -> Bool) -> m Word8-- -- | Usually, someSpace consists of /one/ or more occurrences of a 'space'.- -- Some parsers may choose to recognize line comments or block (multi line)- -- comments as white space as well.- someSpace :: m ()- someSpace = space *> skipMany space- where space = satisfy isSpace-- -- | Called when we enter a nested pair of symbols.- -- Overloadable to disable layout or highlight nested contexts.- nesting :: m a -> m a- nesting = id-- -- | Lexeme parser |semi| parses the character \';\' and skips any- -- trailing white space. Returns the character \';\'.- semi :: m Char- semi = (satisfyAscii (';'==) <?> ";") <* (someSpace <|> pure ())-- -- | Used to emit an error on an unexpected token- unexpected :: String -> m a-- -- | Retrieve the contents of the current line (from the beginning of the line)- line :: m ByteString-- skipping :: Delta -> m ()-- -- | @highlightInterval@ is called internally in the token parsers.- -- It delimits ranges of the input recognized by certain parsers that- -- are useful for syntax highlighting. An interested monad could- -- choose to listen to these events and construct an interval tree- -- for later pretty printing purposes.- highlightInterval :: Highlight -> Delta -> Delta -> m ()- highlightInterval _ _ _ = pure ()-- position :: m Delta-- -- | run a parser, grabbing all of the text between its start and end points- slicedWith :: (a -> Strict.ByteString -> r) -> m a -> m r-- -- | @lookAhead p@ parses @p@ without consuming any input.- lookAhead :: m a -> m a---instance MonadParser m => MonadParser (Lazy.StateT s m) where- try (Lazy.StateT m) = Lazy.StateT $ try . m- labels (Lazy.StateT m) ss = Lazy.StateT $ \s -> labels (m s) ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (Lazy.StateT m) = Lazy.StateT $ nesting . m- skipping = lift . skipping- position = lift position- slicedWith f (Lazy.StateT m) = Lazy.StateT $ \s -> slicedWith (\(a,s') b -> (f a b, s')) $ m s- lookAhead (Lazy.StateT m) = Lazy.StateT $ lookAhead . m--instance MonadParser m => MonadParser (Strict.StateT s m) where- try (Strict.StateT m) = Strict.StateT $ try . m- labels (Strict.StateT m) ss = Strict.StateT $ \s -> labels (m s) ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (Strict.StateT m) = Strict.StateT $ nesting . m- skipping = lift . skipping- position = lift position- slicedWith f (Strict.StateT m) = Strict.StateT $ \s -> slicedWith (\(a,s') b -> (f a b, s')) $ m s- lookAhead (Strict.StateT m) = Strict.StateT $ lookAhead . m--instance MonadParser m => MonadParser (ReaderT e m) where- try (ReaderT m) = ReaderT $ try . m- labels (ReaderT m) ss = ReaderT $ \s -> labels (m s) ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (ReaderT m) = ReaderT $ nesting . m- skipping = lift . skipping- position = lift position- slicedWith f (ReaderT m) = ReaderT $ slicedWith f . m- lookAhead (ReaderT m) = ReaderT $ lookAhead . m--instance (MonadParser m, Monoid w) => MonadParser (Strict.WriterT w m) where- try (Strict.WriterT m) = Strict.WriterT $ try m- labels (Strict.WriterT m) ss = Strict.WriterT $ labels m ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (Strict.WriterT m) = Strict.WriterT $ nesting m- skipping = lift . skipping- position = lift position- slicedWith f (Strict.WriterT m) = Strict.WriterT $ slicedWith (\(a,s') b -> (f a b, s')) m- lookAhead (Strict.WriterT m) = Strict.WriterT $ lookAhead m--instance (MonadParser m, Monoid w) => MonadParser (Lazy.WriterT w m) where- try (Lazy.WriterT m) = Lazy.WriterT $ try m- labels (Lazy.WriterT m) ss = Lazy.WriterT $ labels m ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (Lazy.WriterT m) = Lazy.WriterT $ nesting m- skipping = lift . skipping- position = lift position- slicedWith f (Lazy.WriterT m) = Lazy.WriterT $ slicedWith (\(a,s') b -> (f a b, s')) m- lookAhead (Lazy.WriterT m) = Lazy.WriterT $ lookAhead m--instance (MonadParser m, Monoid w) => MonadParser (Lazy.RWST r w s m) where- try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)- labels (Lazy.RWST m) ss = Lazy.RWST $ \r s -> labels (m r s) ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (Lazy.RWST m) = Lazy.RWST $ \r s -> nesting (m r s)- skipping = lift . skipping- position = lift position- slicedWith f (Lazy.RWST m) = Lazy.RWST $ \r s -> slicedWith (\(a,s',w) b -> (f a b, s',w)) $ m r s- lookAhead (Lazy.RWST m) = Lazy.RWST $ \r s -> lookAhead $ m r s--instance (MonadParser m, Monoid w) => MonadParser (Strict.RWST r w s m) where- try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)- labels (Strict.RWST m) ss = Strict.RWST $ \r s -> labels (m r s) ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (Strict.RWST m) = Strict.RWST $ \r s -> nesting (m r s)- skipping = lift . skipping- position = lift position- slicedWith f (Strict.RWST m) = Strict.RWST $ \r s -> slicedWith (\(a,s',w) b -> (f a b, s',w)) $ m r s- lookAhead (Strict.RWST m) = Strict.RWST $ \r s -> lookAhead $ m r s--instance MonadParser m => MonadParser (IdentityT m) where- try = IdentityT . try . runIdentityT- labels (IdentityT m) ss = IdentityT $ labels m ss- line = lift line- unexpected = lift . unexpected- satisfy = lift . satisfy- satisfy8 = lift . satisfy8- someSpace = lift someSpace- semi = lift semi- highlightInterval h s e = lift $ highlightInterval h s e- nesting (IdentityT m) = IdentityT $ nesting m- skipping = lift . skipping- position = lift position- slicedWith f (IdentityT m) = IdentityT $ slicedWith f m- lookAhead (IdentityT m) = IdentityT $ lookAhead m---- | Skip zero or more bytes worth of white space. More complex parsers are --- free to consider comments as white space.-whiteSpace :: MonadParser m => m ()-whiteSpace = someSpace <|> return ()-{-# INLINE whiteSpace #-}--satisfyAscii :: MonadParser m => (Char -> Bool) -> m Char-satisfyAscii p = w2c <$> satisfy8 (\w -> w <= 0x7f && p (w2c w))-{-# INLINE satisfyAscii #-}---- | grab the remainder of the current line-restOfLine :: MonadParser m => m ByteString-restOfLine = do- m <- position- Strict.drop (fromIntegral (columnByte m)) <$> line-{-# INLINE restOfLine #-}---- | label a parser with a name-(<?>) :: MonadParser m => m a -> String -> m a-p <?> msg = labels p [msg]-{-# INLINE (<?>) #-}---- | run a parser, grabbing all of the text between its start and end points and discarding the original result-sliced :: MonadParser m => m a -> m ByteString-sliced = slicedWith (\_ bs -> bs)-{-# INLINE sliced #-}--rend :: MonadParser m => m Rendering-rend = rendering <$> position <*> line-{-# INLINE rend #-}---- | run a parser, highlighting all of the text between its start and end points.-highlight :: MonadParser m => Highlight -> m a -> m a-highlight h p = do- m <- position- x <- p- r <- position- x <$ highlightInterval h m r-{-# INLINE highlight #-}
− Text/Trifecta/Parser/Combinators.hs
@@ -1,207 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Combinators--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable------ Commonly used generic combinators-----------------------------------------------------------------------------------module Text.Trifecta.Parser.Combinators- ( choice- , option- , optional -- from Control.Applicative, parsec optionMaybe- , skipOptional -- parsec optional- , between- , skipSome -- parsec skipMany1- , some -- from Control.Applicative, parsec many1- , many -- from Control.Applicative- , sepBy- , sepBy1- , sepEndBy1- , sepEndBy- , endBy1- , endBy- , count- , chainl- , chainr- , chainl1- , chainr1- , eof- , manyTill- , notFollowedBy- ) where--import Data.Traversable-import Control.Applicative-import Control.Monad-import qualified Data.ByteString as B-import Text.Trifecta.Parser.Class---- | @choice ps@ tries to apply the parsers in the list @ps@ in order,--- until one of them succeeds. Returns the value of the succeeding--- parser.-choice :: Alternative m => [m a] -> m a-choice = foldr (<|>) empty---- | @option x p@ tries to apply parser @p@. If @p@ fails without--- consuming input, it returns the value @x@, otherwise the value--- returned by @p@.------ > priority = option 0 (do{ d <- digit--- > ; return (digitToInt d)--- > })-option :: Alternative m => a -> m a -> m a-option x p = p <|> pure x---- | @skipOptional p@ tries to apply parser @p@. It will parse @p@ or nothing.--- It only fails if @p@ fails after consuming input. It discards the result--- of @p@. (Plays the role of parsec's optional, which conflicts with Applicative's optional)-skipOptional :: Alternative m => m a -> m ()-skipOptional p = (() <$ p) <|> pure ()---- | @between open close p@ parses @open@, followed by @p@ and @close@.--- Returns the value returned by @p@.------ > braces = between (symbol "{") (symbol "}")-between :: Applicative m => m bra -> m ket -> m a -> m a-between bra ket p = bra *> p <* ket---- | @skipSome p@ applies the parser @p@ /one/ or more times, skipping--- its result. (aka skipMany1 in parsec)-skipSome :: MonadParser m => m a -> m ()-skipSome p = p *> skipMany p---- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated--- by @sep@. Returns a list of values returned by @p@.------ > commaSep p = p `sepBy` (symbol ",")-sepBy :: Alternative m => m a -> m sep -> m [a]-sepBy p sep = sepBy1 p sep <|> pure []---- | @sepBy1 p sep@ parses /one/ or more occurrences of @p@, separated--- by @sep@. Returns a list of values returned by @p@.-sepBy1 :: Alternative m => m a -> m sep -> m [a]-sepBy1 p sep = (:) <$> p <*> many (sep *> p)---- | @sepEndBy1 p sep@ parses /one/ or more occurrences of @p@,--- separated and optionally ended by @sep@. Returns a list of values--- returned by @p@.-sepEndBy1 :: Alternative m => m a -> m sep -> m [a]-sepEndBy1 p sep = flip id <$> p <*> ((flip (:) <$> (sep *> sepEndBy p sep)) <|> pure pure)---- | @sepEndBy p sep@ parses /zero/ or more occurrences of @p@,--- separated and optionally ended by @sep@, ie. haskell style--- statements. Returns a list of values returned by @p@.------ > haskellStatements = haskellStatement `sepEndBy` semi-sepEndBy :: Alternative m => m a -> m sep -> m [a]-sepEndBy p sep = sepEndBy1 p sep <|> pure []---- | @endBy1 p sep@ parses /one/ or more occurrences of @p@, seperated--- and ended by @sep@. Returns a list of values returned by @p@.-endBy1 :: Alternative m => m a -> m sep -> m [a]-endBy1 p sep = some (p <* sep)---- | @endBy p sep@ parses /zero/ or more occurrences of @p@, seperated--- and ended by @sep@. Returns a list of values returned by @p@.------ > cStatements = cStatement `endBy` semi-endBy :: Alternative m => m a -> m sep -> m [a]-endBy p sep = many (p <* sep)---- | @count n p@ parses @n@ occurrences of @p@. If @n@ is smaller or--- equal to zero, the parser equals to @return []@. Returns a list of--- @n@ values returned by @p@.-count :: Applicative m => Int -> m a -> m [a]-count n p | n <= 0 = pure []- | otherwise = sequenceA (replicate n p)---- | @chainr p op x@ parser /zero/ or more occurrences of @p@,--- separated by @op@ Returns a value obtained by a /right/ associative--- application of all functions returned by @op@ to the values returned--- by @p@. If there are no occurrences of @p@, the value @x@ is--- returned.-chainr :: Alternative m => m a -> m (a -> a -> a) -> a -> m a-chainr p op x = chainr1 p op <|> pure x---- | @chainl p op x@ parser /zero/ or more occurrences of @p@,--- separated by @op@. Returns a value obtained by a /left/ associative--- application of all functions returned by @op@ to the values returned--- by @p@. If there are zero occurrences of @p@, the value @x@ is--- returned.-chainl :: Alternative m => m a -> m (a -> a -> a) -> a -> m a-chainl p op x = chainl1 p op <|> pure x---- | @chainl1 p op x@ parser /one/ or more occurrences of @p@,--- separated by @op@ Returns a value obtained by a /left/ associative--- application of all functions returned by @op@ to the values returned--- by @p@. . This parser can for example be used to eliminate left--- recursion which typically occurs in expression grammars.------ > expr = term `chainl1` addop--- > term = factor `chainl1` mulop--- > factor = parens expr <|> integer--- >--- > mulop = do{ symbol "*"; return (*) }--- > <|> do{ symbol "/"; return (div) }--- >--- > addop = do{ symbol "+"; return (+) }--- > <|> do{ symbol "-"; return (-) }-chainl1 :: Alternative m => m a -> m (a -> a -> a) -> m a-chainl1 p op = scan where- scan = flip id <$> p <*> rst- rst = (\f y g x -> g (f x y)) <$> op <*> p <*> rst <|> pure id---- | @chainr1 p op x@ parser /one/ or more occurrences of |p|,--- separated by @op@ Returns a value obtained by a /right/ associative--- application of all functions returned by @op@ to the values returned--- by @p@.-chainr1 :: Alternative m => m a -> m (a -> a -> a) -> m a-chainr1 p op = scan where- scan = flip id <$> p <*> rst- rst = (flip <$> op <*> scan) <|> pure id---- | @manyTill p end@ applies parser @p@ /zero/ or more times until--- parser @end@ succeeds. Returns the list of values returned by @p@.--- This parser can be used to scan comments:------ > simpleComment = do{ string "<!--"--- > ; manyTill anyChar (try (string "-->"))--- > }------ Note the overlapping parsers @anyChar@ and @string \"-->\"@, and--- therefore the use of the 'try' combinator.-manyTill :: Alternative m => m a -> m end -> m [a]-manyTill p end = go where go = ([] <$ end) <|> ((:) <$> p <*> go)---- * MonadParsers---- | This parser only succeeds at the end of the input. This is not a--- primitive parser but it is defined using 'notFollowedBy'.------ > eof = notFollowedBy anyChar <?> "end of input"-eof :: MonadParser m => m ()-eof = do- l <- restOfLine- guard $ B.null l- <?> "end of input"---- | @notFollowedBy p@ only succeeds when parser @p@ fails. This parser--- does not consume any input. This parser can be used to implement the--- \'longest match\' rule. For example, when recognizing keywords (for--- example @let@), we want to make sure that a keyword is not followed--- by a legal identifier character, in which case the keyword is--- actually an identifier (for example @lets@). We can program this--- behaviour as follows:------ > keywordLet = try (do{ string "let"--- > ; notFollowedBy alphaNum--- > })-notFollowedBy :: (MonadParser m, Show a) => m a -> m ()-notFollowedBy p = try ((try p >>= unexpected . show) <|> pure ())
− Text/Trifecta/Parser/Expr.hs
@@ -1,167 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Expr--- Copyright : (c) Edward Kmett--- (c) Paolo Martini 2007--- (c) Daan Leijen 1999-2001, --- License : BSD-style (see the LICENSE file)--- --- Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable--- --- A helper module to parse \"expressions\".--- Builds a parser given a table of operators and associativities.--- --------------------------------------------------------------------------------module Text.Trifecta.Parser.Expr- ( Assoc(..), Operator(..), OperatorTable- , buildExpressionParser- ) where--import Control.Applicative-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Combinators---------------------------------------------------------------- Assoc and OperatorTable---------------------------------------------------------------- | This data type specifies the associativity of operators: left, right--- or none.--data Assoc - = AssocNone- | AssocLeft- | AssocRight---- | This data type specifies operators that work on values of type @a@.--- An operator is either binary infix or unary prefix or postfix. A--- binary operator has also an associated associativity.--data Operator m a - = Infix (m (a -> a -> a)) Assoc- | Prefix (m (a -> a))- | Postfix (m (a -> a))---- | An @OperatorTable m a@ is a list of @Operator m a@--- lists. The list is ordered in descending--- precedence. All operators in one list have the same precedence (but--- may have a different associativity).--type OperatorTable m a = [[Operator m a]]---------------------------------------------------------------- Convert an OperatorTable and basic term parser into--- a full fledged expression parser---------------------------------------------------------------- | @buildExpressionParser table term@ builds an expression parser for--- terms @term@ with operators from @table@, taking the associativity--- and precedence specified in @table@ into account. Prefix and postfix--- operators of the same precedence can only occur once (i.e. @--2@ is--- not allowed if @-@ is prefix negate). Prefix and postfix operators--- of the same precedence associate to the left (i.e. if @++@ is--- postfix increment, than @-2++@ equals @-1@, not @-3@).------ The @buildExpressionParser@ takes care of all the complexity--- involved in building expression parser. Here is an example of an--- expression parser that handles prefix signs, postfix increment and--- basic arithmetic.------ > expr = buildExpressionParser table term--- > <?> "expression"--- >--- > term = parens expr --- > <|> natural--- > <?> "simple expression"--- >--- > table = [ [prefix "-" negate, prefix "+" id ]--- > , [postfix "++" (+1)]--- > , [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]--- > , [binary "+" (+) AssocLeft, binary "-" (-) AssocLeft ]--- > ]--- > --- > binary name fun assoc = Infix (do{ reservedOp name; return fun }) assoc--- > prefix name fun = Prefix (do{ reservedOp name; return fun })--- > postfix name fun = Postfix (do{ reservedOp name; return fun })--buildExpressionParser :: MonadParser m- => OperatorTable m a- -> m a- -> m a-buildExpressionParser operators simpleExpr- = foldl (makeParser) simpleExpr operators- where- makeParser term ops- = let (rassoc,lassoc,nassoc,prefix,postfix) = foldr splitOp ([],[],[],[],[]) ops-- rassocOp = choice rassoc- lassocOp = choice lassoc- nassocOp = choice nassoc- prefixOp = choice prefix <?> ""- postfixOp = choice postfix <?> ""-- ambigious assoc op= try $ op *> fail ("ambiguous use of a " ++ assoc ++ " associative operator")-- ambigiousRight = ambigious "right" rassocOp- ambigiousLeft = ambigious "left" lassocOp- ambigiousNon = ambigious "non" nassocOp-- termP = do{ pre <- prefixP- ; x <- term- ; post <- postfixP- ; return (post (pre x))- }-- postfixP = postfixOp <|> return id-- prefixP = prefixOp <|> return id-- rassocP x = do{ f <- rassocOp- ; y <- termP >>= rassocP1- ; return (f x y)- }- <|> ambigiousLeft- <|> ambigiousNon- -- <|> return x-- rassocP1 x = rassocP x <|> return x-- lassocP x = do{ f <- lassocOp- ; y <- termP- ; lassocP1 (f x y)- }- <|> ambigiousRight- <|> ambigiousNon- -- <|> return x-- lassocP1 x = lassocP x <|> return x-- nassocP x = do{ f <- nassocOp- ; y <- termP- ; ambigiousRight- <|> ambigiousLeft- <|> ambigiousNon- <|> return (f x y)- }- -- <|> return x-- in do{ x <- termP- ; rassocP x <|> lassocP x <|> nassocP x <|> return x- <?> "operator"- }--- splitOp (Infix op assoc) (rassoc,lassoc,nassoc,prefix,postfix)- = case assoc of- AssocNone -> (rassoc,lassoc,op:nassoc,prefix,postfix)- AssocLeft -> (rassoc,op:lassoc,nassoc,prefix,postfix)- AssocRight -> (op:rassoc,lassoc,nassoc,prefix,postfix)-- splitOp (Prefix op) (rassoc,lassoc,nassoc,prefix,postfix)- = (rassoc,lassoc,nassoc,op:prefix,postfix)-- splitOp (Postfix op) (rassoc,lassoc,nassoc,prefix,postfix)- = (rassoc,lassoc,nassoc,prefix,op:postfix)
− Text/Trifecta/Parser/Identifier.hs
@@ -1,67 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Identifier--- Copyright : (c) Edward Kmett 2011--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable------ > idStyle = haskellIdentifierStyle { styleReserved = ... }--- > identifier = ident haskellIdentifierStyle--- > reserved = reserve haskellIdentifierStyle----------------------------------------------------------------------------------module Text.Trifecta.Parser.Identifier- ( IdentifierStyle(..)- , liftIdentifierStyle- , ident- , reserve- , reserveByteString- ) where--import Data.ByteString as Strict hiding (map, zip, foldl, foldr)-import Data.ByteString.UTF8 as UTF8-import Data.HashSet as HashSet-import Control.Applicative-import Control.Monad (when)-import Control.Monad.Trans.Class-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Parser.Token.Combinators-import Text.Trifecta.Highlight.Prim--data IdentifierStyle m = IdentifierStyle- { styleName :: String- , styleStart :: m ()- , styleLetter :: m ()- , styleReserved :: HashSet ByteString- , styleHighlight :: Highlight- , styleReservedHighlight :: Highlight- }---- | Lift an identifier style into a monad transformer-liftIdentifierStyle :: (MonadTrans t, Monad m) => IdentifierStyle m -> IdentifierStyle (t m)-liftIdentifierStyle s =- s { styleStart = lift (styleStart s)- , styleLetter = lift (styleLetter s)- }---- | parse a reserved operator or identifier using a given style-reserve :: MonadParser m => IdentifierStyle m -> String -> m ()-reserve s name = reserveByteString s $! UTF8.fromString name---- | parse a reserved operator or identifier using a given style specified by bytestring-reserveByteString :: MonadParser m => IdentifierStyle m -> ByteString -> m ()-reserveByteString s name = lexeme $ try $ do- _ <- highlight (styleReservedHighlight s) $ byteString name- notFollowedBy (styleLetter s) <?> "end of " ++ show name---- | parse an non-reserved identifier or symbol-ident :: MonadParser m => IdentifierStyle m -> m ByteString-ident s = lexeme $ try $ do- name <- highlight (styleHighlight s) (sliced (styleStart s *> skipMany (styleLetter s))) <?> styleName s- when (member name (styleReserved s)) $ unexpected $ "reserved " ++ styleName s ++ " " ++ show name- return name
− Text/Trifecta/Parser/Identifier/Style.hs
@@ -1,70 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Identifier.Style--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable----------------------------------------------------------------------------------module Text.Trifecta.Parser.Identifier.Style- (- -- identifier styles- emptyIdents, haskellIdents, haskell98Idents- -- operator styles- , emptyOps, haskellOps, haskell98Ops- ) where--import Data.ByteString as Strict hiding (map, zip, foldl, foldr)-import Data.ByteString.UTF8 as UTF8-import Data.HashSet as HashSet-import Data.Monoid-import Control.Applicative-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Identifier-import Text.Trifecta.Highlight.Prim--set :: [String] -> HashSet ByteString-set = HashSet.fromList . fmap UTF8.fromString--emptyOps, haskell98Ops, haskellOps :: MonadParser m => IdentifierStyle m-emptyOps = IdentifierStyle- { styleName = "operator"- , styleStart = styleLetter emptyOps- , styleLetter = () <$ oneOf ":!#$%&*+./<=>?@\\^|-~"- , styleReserved = mempty- , styleHighlight = Operator- , styleReservedHighlight = ReservedOperator- }-haskell98Ops = emptyOps- { styleReserved = set ["::","..","=","\\","|","<-","->","@","~","=>"]- }-haskellOps = haskell98Ops--emptyIdents, haskell98Idents, haskellIdents :: MonadParser m => IdentifierStyle m-emptyIdents = IdentifierStyle- { styleName = "identifier"- , styleStart = () <$ (letter <|> char '_')- , styleLetter = () <$ (alphaNum <|> oneOf "_'")- , styleReserved = set []- , styleHighlight = Identifier- , styleReservedHighlight = ReservedIdentifier }--haskell98Idents = emptyIdents- { styleReserved = set haskell98ReservedIdents }-haskellIdents = haskell98Idents- { styleLetter = styleLetter haskell98Idents <|> () <$ char '#'- , styleReserved = set $ haskell98ReservedIdents ++- ["foreign","import","export","primitive","_ccall_","_casm_" ,"forall"]- }--haskell98ReservedIdents :: [String]-haskell98ReservedIdents =- ["let","in","case","of","if","then","else","data","type"- ,"class","default","deriving","do","import","infix"- ,"infixl","infixr","instance","module","newtype"- ,"where","primitive" -- "as","qualified","hiding"- ]
− Text/Trifecta/Parser/It.hs
@@ -1,147 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, BangPatterns, MagicHash, UnboxedTuples, TypeFamilies #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.It--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable------ harder, better, faster, stronger...------------------------------------------------------------------------------module Text.Trifecta.Parser.It - ( It(Pure, It)- , needIt- , wantIt- , simplifyIt- , runIt- , fillIt- , rewindIt- , sliceIt- , stepIt- ) where--import Control.Applicative-import Control.Comonad-import Control.Monad-import Data.Semigroup-import Data.ByteString as Strict-import Data.ByteString.Lazy as Lazy-import Data.Functor.Bind-import Data.Profunctor-import Data.Key as Key-import Text.Trifecta.Rope.Prim as Rope-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Parser.Step-import Text.Trifecta.Util.Combinators as Util--data It r a- = Pure a - | It a (r -> It r a)--instance Show a => Show (It r a) where- showsPrec d (Pure a) = showParen (d > 10) $ showString "Pure " . showsPrec 11 a- showsPrec d (It a _) = showParen (d > 10) $ showString "It " . showsPrec 11 a . showString " ..."--instance Functor (It r) where- fmap f (Pure a) = Pure $ f a- fmap f (It a k) = It (f a) $ fmap f . k--type instance Key (It r) = r--instance Profunctor It where- lmap _ (Pure a) = Pure a- lmap f (It a k) = It a (lmap f . k . f)-- rmap g (Pure a) = Pure (g a)- rmap g (It a k) = It (g a) (rmap g . k)--instance Applicative (It r) where- pure = Pure- Pure f <*> Pure a = Pure $ f a- Pure f <*> It a ka = It (f a) $ fmap f . ka- It f kf <*> Pure a = It (f a) $ fmap ($a) . kf- It f kf <*> It a ka = It (f a) $ \r -> kf r <*> ka r--instance Indexable (It r) where- index (Pure a) _ = a- index (It _ k) r = extract (k r)--instance Lookup (It r) where- lookup = lookupDefault--instance Zip (It r) where- zipWith = liftA2--simplifyIt :: It r a -> r -> It r a-simplifyIt (It _ k) r = k r-simplifyIt pa _ = pa--instance Monad (It r) where- return = Pure- Pure a >>= f = f a- It a k >>= f = It (extract (f a)) $ \r -> case k r of - It a' k' -> It (Key.index (f a') r) $ k' >=> f- Pure a' -> simplifyIt (f a') r--instance Apply (It r) where (<.>) = (<*>) -instance Bind (It r) where (>>-) = (>>=) --instance Extend (It r) where- duplicate p@Pure{} = Pure p- duplicate p@(It _ k) = It p (duplicate . k)-- extend f p@Pure{} = Pure (f p)- extend f p@(It _ k) = It (f p) (extend f . k)---- | It is a cofree comonad-instance Comonad (It r) where- extract (Pure a) = a- extract (It a _) = a--needIt :: a -> (r -> Maybe a) -> It r a-needIt z f = k where - k = It z $ \r -> case f r of - Just a -> Pure a- Nothing -> k--wantIt :: a -> (r -> (# Bool, a #)) -> It r a-wantIt z f = It z k where - k r = case f r of- (# False, a #) -> It a k- (# True, a #) -> Pure a---- scott decoding-runIt :: (a -> o) -> (a -> (r -> It r a) -> o) -> It r a -> o-runIt p _ (Pure a) = p a-runIt _ i (It a k) = i a k---- * Rope specifics---- | Given a position, go there, and grab the text forward from that point-fillIt :: r -> (Delta -> Strict.ByteString -> r) -> Delta -> It Rope r-fillIt kf ks n = wantIt kf $ \r -> - (# bytes n < bytes (rewind (delta r))- , grabLine n r kf ks #) --stepIt :: It Rope a -> Step e a-stepIt = go mempty where- go r (Pure a) = StepDone r mempty a- go r (It a k) = StepCont r (pure a) $ \s -> go s (k s)- --- | Return the text of the line that contains a given position-rewindIt :: Delta -> It Rope (Maybe Strict.ByteString)-rewindIt n = wantIt Nothing $ \r -> - (# bytes n < bytes (rewind (delta r))- , grabLine (rewind n) r Nothing $ const Just #)--sliceIt :: Delta -> Delta -> It Rope Strict.ByteString-sliceIt !i !j = wantIt mempty $ \r -> - (# bj < bytes (rewind (delta r))- , grabRest i r mempty $ const $ Util.fromLazy . Lazy.take (fromIntegral (bj - bi)) #)- where- bi = bytes i- bj = bytes j
− Text/Trifecta/Parser/Mark.hs
@@ -1,67 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Mark--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable----------------------------------------------------------------------------------module Text.Trifecta.Parser.Mark- ( MonadMark(..)- ) where--import Control.Monad.Trans.Class-import Control.Monad.Trans.State.Lazy as Lazy-import Control.Monad.Trans.State.Strict as Strict-import Control.Monad.Trans.Writer.Lazy as Lazy-import Control.Monad.Trans.Writer.Strict as Strict-import Control.Monad.Trans.RWS.Lazy as Lazy-import Control.Monad.Trans.RWS.Strict as Strict-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Identity-import Data.Monoid-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Parser.Class--class (MonadParser m, HasDelta d) => MonadMark d m | m -> d where- -- | mark the current location so it can be used in constructing a span, or for later seeking- mark :: m d- -- | Seek a previously marked location- release :: d -> m ()--instance MonadMark d m => MonadMark d (Lazy.StateT s m) where- mark = lift mark- release = lift . release--instance MonadMark d m => MonadMark d (Strict.StateT s m) where- mark = lift mark- release = lift . release--instance MonadMark d m => MonadMark d (ReaderT e m) where- mark = lift mark- release = lift . release--instance (MonadMark d m, Monoid w) => MonadMark d (Strict.WriterT w m) where- mark = lift mark- release = lift . release--instance (MonadMark d m, Monoid w) => MonadMark d (Lazy.WriterT w m) where- mark = lift mark- release = lift . release--instance (MonadMark d m, Monoid w) => MonadMark d (Lazy.RWST r w s m) where- mark = lift mark- release = lift . release--instance (MonadMark d m, Monoid w) => MonadMark d (Strict.RWST r w s m) where- mark = lift mark- release = lift . release--instance MonadMark d m => MonadMark d (IdentityT m) where- mark = lift mark- release = lift . release-
− Text/Trifecta/Parser/Perm.hs
@@ -1,141 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Perm--- Copyright : (c) Edward Kmett 2011--- (c) Paolo Martini 2007--- (c) Daan Leijen 1999-2001--- License : BSD-style--- --- Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable--- --- This module implements permutation parsers. The algorithm is described in:--- --- /Parsing Permutation Phrases,/--- by Arthur Baars, Andres Loh and Doaitse Swierstra.--- Published as a functional pearl at the Haskell Workshop 2001.--- --------------------------------------------------------------------------------{-# LANGUAGE ExistentialQuantification #-}--module Text.Trifecta.Parser.Perm- ( Perm- , permute- , (<||>), (<$$>)- , (<|?>), (<$?>)- ) where--import Control.Applicative-import Text.Trifecta.Parser.Combinators (choice)--infixl 1 <||>, <|?>-infixl 2 <$$>, <$?>--{---------------------------------------------------------------- Building a permutation parser----------------------------------------------------------------}---- | The expression @perm \<||> p@ adds parser @p@ to the permutation--- parser @perm@. The parser @p@ is not allowed to accept empty input ---- use the optional combinator ('<|?>') instead. Returns a--- new permutation parser that includes @p@. --(<||>) :: Functor m => Perm m (a -> b) -> m a -> Perm m b-(<||>) perm p = add perm p---- | The expression @f \<$$> p@ creates a fresh permutation parser--- consisting of parser @p@. The the final result of the permutation--- parser is the function @f@ applied to the return value of @p@. The--- parser @p@ is not allowed to accept empty input - use the optional--- combinator ('<$?>') instead.------ If the function @f@ takes more than one parameter, the type variable--- @b@ is instantiated to a functional type which combines nicely with--- the adds parser @p@ to the ('<||>') combinator. This--- results in stylized code where a permutation parser starts with a--- combining function @f@ followed by the parsers. The function @f@--- gets its parameters in the order in which the parsers are specified,--- but actual input can be in any order.--(<$$>) :: Functor m => (a -> b) -> m a -> Perm m b-(<$$>) f p = newPerm f <||> p---- | The expression @perm \<||> (x,p)@ adds parser @p@ to the--- permutation parser @perm@. The parser @p@ is optional - if it can--- not be applied, the default value @x@ will be used instead. Returns--- a new permutation parser that includes the optional parser @p@. --(<|?>) :: Functor m => Perm m (a -> b) -> (a, m a) -> Perm m b-(<|?>) perm (x,p) = addOpt perm x p---- | The expression @f \<$?> (x,p)@ creates a fresh permutation parser--- consisting of parser @p@. The the final result of the permutation--- parser is the function @f@ applied to the return value of @p@. The--- parser @p@ is optional - if it can not be applied, the default value--- @x@ will be used instead. --(<$?>) :: Functor m => (a -> b) -> (a, m a) -> Perm m b-(<$?>) f (x,p) = newPerm f <|?> (x,p)--{---------------------------------------------------------------- The permutation tree----------------------------------------------------------------}---- | The type @Perm m a@ denotes a permutation parser that,--- when converted by the 'permute' function, parses --- using the base parsing monad @m@ and returns a value of--- type @a@ on success.------ Normally, a permutation parser is first build with special operators--- like ('<||>') and than transformed into a normal parser--- using 'permute'.--data Perm m a = Perm (Maybe a) [Branch m a]--instance Functor m => Functor (Perm m) where- fmap f (Perm x xs) = Perm (fmap f x) (fmap f <$> xs)--data Branch m a = forall b. Branch (Perm m (b -> a)) (m b)--instance Functor m => Functor (Branch m) where- fmap f (Branch perm p) = Branch (fmap (f.) perm) p---- | The parser @permute perm@ parses a permutation of parser described--- by @perm@. For example, suppose we want to parse a permutation of:--- an optional string of @a@'s, the character @b@ and an optional @c@.--- This can be described by:------ > test = permute (tuple <$?> ("",some (char 'a'))--- > <||> char 'b' --- > <|?> ('_',char 'c'))--- > where--- > tuple a b c = (a,b,c)---- transform a permutation tree into a normal parser-permute :: Alternative m => Perm m a -> m a-permute (Perm def xs)- = choice (map branch xs ++ e)- where- e = maybe [] (pure . pure) def- branch (Branch perm p) = flip id <$> p <*> permute perm- --- build permutation trees-newPerm :: (a -> b) -> Perm m (a -> b)-newPerm f = Perm (Just f) []--add :: Functor m => Perm m (a -> b) -> m a -> Perm m b-add perm@(Perm _mf fs) p- = Perm Nothing (first:map insert fs)- where- first = Branch perm p- insert (Branch perm' p')- = Branch (add (fmap flip perm') p) p'--addOpt :: Functor m => Perm m (a -> b) -> a -> m a -> Perm m b-addOpt perm@(Perm mf fs) x p- = Perm (fmap ($ x) mf) (first:map insert fs)- where- first = Branch perm p- insert (Branch perm' p') = Branch (addOpt (fmap flip perm') x p) p'
− Text/Trifecta/Parser/Prim.hs
@@ -1,322 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts, Rank2Types, FlexibleInstances, BangPatterns #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Prim--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : non-portable----------------------------------------------------------------------------------module Text.Trifecta.Parser.Prim- ( Parser(..)- , why- , stepParser- , manyAccum- ) where---import Control.Applicative-import Control.Monad.Error.Class-import Control.Monad.Writer.Class-import Control.Monad.Cont.Class-import Control.Monad-import Control.Comonad-import qualified Data.Functor.Plus as Plus-import Data.Functor.Plus hiding (some, many)-import Data.Function-import Data.Semigroup-import Data.Foldable-import qualified Data.List as List-import Data.Functor.Bind (Bind((>>-)))-import qualified Text.Trifecta.IntervalMap as IntervalMap-import Data.Set as Set hiding (empty, toList)-import Data.ByteString as Strict hiding (empty)-import Data.Sequence as Seq hiding (empty)-import Data.ByteString.UTF8 as UTF8-import Text.PrettyPrint.Free hiding (line)-import Text.Trifecta.Diagnostic.Class-import Text.Trifecta.Diagnostic.Prim-import Text.Trifecta.Diagnostic.Level-import Text.Trifecta.Diagnostic.Err-import Text.Trifecta.Diagnostic.Err.State-import Text.Trifecta.Diagnostic.Err.Log-import Text.Trifecta.Diagnostic.Rendering.Caret-import Text.Trifecta.Highlight.Class-import Text.Trifecta.Highlight.Prim-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.It-import Text.Trifecta.Parser.Mark-import Text.Trifecta.Parser.Step-import Text.Trifecta.Parser.Result-import Text.Trifecta.Rope.Delta as Delta-import Text.Trifecta.Rope.Prim-import Text.Trifecta.Rope.Bytes--data Parser r e a = Parser- { unparser ::- (a -> ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- uncommitted ok- ( ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- uncommitted err- (a -> ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- committed ok- ( ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- committed err- ErrLog e -> Bool -> Delta -> ByteString -> It Rope r- }--instance Functor (Parser r e) where- fmap f (Parser m) = Parser $ \ eo ee co -> m (eo . f) ee (co . f)- {-# INLINE fmap #-}- a <$ Parser m = Parser $ \ eo ee co -> m (\_ -> eo a) ee (\_ -> co a)- {-# INLINE (<$) #-}--instance Apply (Parser r e) where (<.>) = (<*>)-instance Applicative (Parser r e) where- pure a = Parser $ \ eo _ _ _ -> eo a mempty- {-# INLINE pure #-}- (<*>) = ap- {-# INLINE (<*>) #-}-{-- Parser m <*> Parser n = Parser $ \ eo ee co ce ->- m (\f e -> n (\a e' -> eo (f a) (e <> e')) ee (\a e' -> co (f a) (e <> e')) ce) ee- (\f e -> n (\a e' -> co (f a) (e <> e')) ce (\a e' -> co (f a) (e <> e')) ce) ce- {-# INLINE (<*>) #-}- Parser m <* Parser n = Parser $ \ eo ee co ce ->- m (\a e -> n (\_ e' -> eo a (e <> e')) ee (\_ e' -> co a (e <> e')) ce) ee- (\a e -> n (\_ e' -> co a (e <> e')) ce (\_ e' -> co a (e <> e')) ce) ce- {-# INLINE (<*) #-}- Parser m *> Parser n = Parser $ \ eo ee co ce ->- m (\_ e -> n (\a e' -> eo a (e <> e')) ee (\a e' -> co a (e <> e')) ce) ee- (\_ e -> n (\a e' -> co a (e <> e')) ce (\a e' -> co a (e <> e')) ce) ce- {-# INLINE (*>) #-}--}--instance Alt (Parser r e) where- (<!>) = (<|>)- many p = Prelude.reverse <$> manyAccum (:) p- some p = p *> many p-instance Plus (Parser r e) where zero = empty-instance Alternative (Parser r e) where- empty = Parser $ \_ ee _ _ -> ee mempty- {-# INLINE empty #-}- Parser m <|> Parser n = Parser $ \ eo ee co ce ->- m eo (\e -> n (\a e'-> eo a (e <> e')) (\e' -> ee (e <> e')) co ce)- co ce- {-# INLINE (<|>) #-}- many p = Prelude.reverse <$> manyAccum (:) p- {-# INLINE many #-}- some p = (:) <$> p <*> many p--instance Semigroup (Parser r e a) where- (<>) = (<|>)--instance Monoid (Parser r e a) where- mappend = (<|>)- mempty = empty--instance Bind (Parser r e) where (>>-) = (>>=)-instance Monad (Parser r e) where- return a = Parser $ \ eo _ _ _ -> eo a mempty- {-# INLINE return #-}- Parser m >>= k = Parser $ \ eo ee co ce ->- m (\a e -> unparser (k a) (\b e' -> eo b (e <> e')) (\e' -> ee (e <> e')) co ce) ee- (\a e -> unparser (k a) (\b e' -> co b (e <> e')) (\e' -> ce (e <> e')) co ce) ce- {-# INLINE (>>=) #-}- (>>) = (*>)- {-# INLINE (>>) #-}- fail s = Parser $ \ _ ee _ _ l b8 d bs -> ee mempty { errMessage = FailErr (renderingCaret d bs) s } l b8 d bs- {-# INLINE fail #-}---instance MonadPlus (Parser r e) where- mzero = empty- mplus = (<|>)--instance MonadWriter (ErrLog e) (Parser r e) where- tell w = Parser $ \eo _ _ _ l -> eo () mempty (l <> w)- {-# INLINE tell #-}- listen (Parser m) = Parser $ \eo ee co ce l ->- m (\ a e' l' -> eo (a,l') e' (l <> l'))- (\ e' l' -> ee e' (l <> l'))- (\ a e' l' -> co (a,l') e' (l <> l'))- (\ e' l' -> ce e' (l <> l'))- mempty- {-# INLINE listen #-}- pass (Parser m) = Parser $ \eo ee co ce l ->- m (\(a,p) e' l' -> eo a e' (l <> p l'))- (\ e' l' -> ee e' (l <> l'))- (\(a,p) e' l' -> co a e' (l <> p l'))- (\ e' l' -> ce e' (l <> l'))- mempty- {-# INLINE pass #-}--manyAccum :: (a -> [a] -> [a]) -> Parser r e a -> Parser r e [a]-manyAccum acc (Parser p) = Parser $ \eo _ co ce ->- let walk xs x _ = p manyErr (\_ -> co (acc x xs) mempty) (walk (acc x xs)) ce- manyErr _ e l b8 d bs = ce e { errMessage = PanicErr (renderingCaret d bs) "'many' applied to a parser that accepted an empty string" } l b8 d bs- in p manyErr (eo []) (walk []) ce--instance MonadDiagnostic e (Parser r e) where- throwDiagnostic e@(Diagnostic _ l _ _)- | l == Fatal || l == Panic = Parser $ \_ _ _ ce -> ce mempty { errMessage = Err e }- | otherwise = Parser $ \_ ee _ _ -> ee mempty { errMessage = Err e }- logDiagnostic d = Parser $ \eo _ _ _ l -> eo () mempty l { errLog = errLog l |> d }--instance MonadError (ErrState e) (Parser r e) where- throwError m = Parser $ \_ ee _ _ -> ee m- {-# INLINE throwError #-}- catchError (Parser m) k = Parser $ \ eo ee co ce ->- m eo (\e -> unparser (k e) eo ee co ce) co ce- {-# INLINE catchError #-}--ascii :: ByteString -> Bool-ascii = Strict.all (<=0x7f)--liftIt :: It Rope a -> Parser r e a-liftIt m = Parser $ \ eo _ _ _ l b8 d bs -> do- a <- m- eo a mempty l b8 d bs-{-# INLINE liftIt #-}--instance MonadParser (Parser r e) where- try (Parser m) = Parser $ \ eo ee co ce l b8 d bs -> m eo ee co (\e l' _ _ _ ->- if fatalErr (errMessage e)- then ce e (l <> l') b8 d bs- else ee e (l <> l') b8 d bs- ) l b8 d bs- {-# INLINE try #-}- highlightInterval h s e = Parser $ \eo _ _ _ l -> eo () mempty l { errHighlights = IntervalMap.insert s e h (errHighlights l) }- {-# INLINE highlightInterval #-}-- skipping d = do- m <- mark- release $ m <> d- {-# INLINE skipping #-}-- unexpected s = Parser $ \ _ ee _ _ l b8 d bs -> ee mempty { errMessage = FailErr (renderingCaret d bs) $ "unexpected " ++ s } l b8 d bs- {-# INLINE unexpected #-}-- labels (Parser p) msgs = Parser $ \ eo ee -> p- (\a e l b8 d bs ->- eo a (if knownErr (errMessage e)- then e { errExpected = Set.fromList (Prelude.map (:^ Caret d bs) msgs) `union` errExpected e }- else e) l b8 d bs)- (\e l b8 d bs -> ee e { errExpected = Set.fromList $ Prelude.map (:^ Caret d bs) msgs } l b8 d bs)- {-# INLINE labels #-}- line = Parser $ \eo _ _ _ l b8 d bs -> eo bs mempty l b8 d bs- {-# INLINE line #-}- skipMany p = () <$ manyAccum (\_ _ -> []) p- {-# INLINE skipMany #-}- satisfy f = Parser $ \ _ ee co _ l b8 d bs ->- if b8 -- fast path- then let b = columnByte d in (- if b >= 0 && b < fromIntegral (Strict.length bs)- then case toEnum $ fromEnum $ Strict.index bs (fromIntegral b) of- c | not (f c) -> ee mempty l b8 d bs- | b == fromIntegral (Strict.length bs) - 1 -> let !ddc = d <> delta c- in join $ fillIt ( if c == '\n'- then co c mempty l True ddc mempty- else co c mempty l b8 ddc bs )- (\d' bs' -> co c mempty l (ascii bs') d' bs')- ddc- | otherwise -> co c mempty l b8 (d <> delta c) bs- else ee mempty { errMessage = FailErr (renderingCaret d bs) "unexpected EOF" } l b8 d bs)- else case UTF8.uncons $ Strict.drop (fromIntegral (columnByte d)) bs of- Nothing -> ee mempty { errMessage = FailErr (renderingCaret d bs) "unexpected EOF" } l b8 d bs- Just (c, xs)- | not (f c) -> ee mempty l b8 d bs- | Strict.null xs -> let !ddc = d <> delta c- in join $ fillIt ( if c == '\n'- then co c mempty l True ddc mempty- else co c mempty l b8 ddc bs)- (\d' bs' -> co c mempty l (ascii bs') d' bs')- ddc- | otherwise -> co c mempty l b8 (d <> delta c) bs- satisfy8 f = Parser $ \ _ ee co _ l b8 d bs ->- let b = columnByte d in- if b >= 0 && b < fromIntegral (Strict.length bs)- then case toEnum $ fromEnum $ Strict.index bs (fromIntegral b) of- c | not (f c) -> ee mempty l b8 d bs- | b == fromIntegral (Strict.length bs - 1) -> let !ddc = d <> delta c- in join $ fillIt ( if c == 10- then co c mempty l True ddc mempty- else co c mempty l b8 ddc bs )- (\d' bs' -> co c mempty l (ascii bs') d' bs')- ddc- | otherwise -> co c mempty l b8 (d <> delta c) bs- else ee mempty { errMessage = FailErr (renderingCaret d bs) "unexpected EOF" } l b8 d bs- position = Parser $ \eo _ _ _ l b8 d -> eo d mempty l b8 d- {-# INLINE position #-}- slicedWith f p = do- m <- position- a <- p- r <- position- f a <$> liftIt (sliceIt m r)- {-# INLINE slicedWith #-}- lookAhead (Parser m) = Parser $ \eo ee _ ce l b8 d bs ->- m eo ee (\a e l' _ _ _ -> eo a e (l <> l') b8 d bs) ce l b8 d bs- {-# INLINE lookAhead #-}--instance MonadCont (Parser r e) where- callCC f = Parser $ \ eo ee co ce l b8 d bs -> unparser (f (\a -> Parser $ \_ _ _ _ l' _ _ _ -> eo a mempty l' b8 d bs)) eo ee co ce l b8 d bs--instance MonadMark Delta (Parser r e) where- mark = position- {-# INLINE mark #-}- release d' = Parser $ \_ ee co _ l b8 d bs -> do- mbs <- rewindIt d'- case mbs of- Just bs' -> co () mempty l (ascii bs') d' bs'- Nothing- | bytes d' == bytes (rewind d) + fromIntegral (Strict.length bs) -> if near d d'- then co () mempty l (ascii bs) d' bs- else co () mempty l True d' mempty- | otherwise -> ee mempty l b8 d bs--data St e a = JuSt a !(ErrState e) !(ErrLog e) !Bool !Delta !ByteString- | NoSt !(ErrState e) !(ErrLog e) !Bool !Delta !ByteString--stepParser :: (Diagnostic e -> Diagnostic t) ->- (ErrState e -> Highlights -> Bool -> Delta -> ByteString -> Diagnostic t) ->- (forall r. Parser r e a) -> ErrLog e -> Bool -> Delta -> ByteString -> Step t a-stepParser yl y (Parser p) l0 b80 d0 bs0 =- go mempty $ p ju no ju no l0 b80 d0 bs0- where- ju a e l b8 d bs = Pure (JuSt a e l b8 d bs)- no e l b8 d bs = Pure (NoSt e l b8 d bs)- go r (Pure (JuSt a _ l _ _ _)) = StepDone r (yl . addHighlights (errHighlights l) <$> errLog l) a- go r (Pure (NoSt e l b8 d bs)) = StepFail r ((yl . addHighlights (errHighlights l) <$> errLog l) |> y e (errHighlights l) b8 d bs)- go r (It ma k) = StepCont r (case ma of- JuSt a _ l _ _ _ -> Success (yl . addHighlights (errHighlights l) <$> errLog l) a- NoSt e l b8 d bs -> Failure ((yl . addHighlights (errHighlights l) <$> errLog l) |> y e (errHighlights l) b8 d bs))- (go <*> k)--why :: Pretty e => (e -> Doc t) -> ErrState e -> Highlights -> Bool -> Delta -> ByteString -> Diagnostic (Doc t)-why pp (ErrState ss m) hs _ d bs- | Prelude.null now = explicateWith empty m- | knownErr m = explicateWith (char ',' <+> ex) m- | otherwise = Diagnostic rightHere Error ex notes- where- ex = expect now- ignoreBlanks = go . List.nub . List.sort where- go [] = []- go [""] = ["space"]- go xs = List.filter (/= "") xs- expect xs = text "expected:" <+> fillSep (punctuate (char ',') (Prelude.map text $ ignoreBlanks $ Prelude.map extract xs))- (now,later) = List.partition (\x -> errLoc m == Just (delta x)) $ toList ss- clusters = List.groupBy ((==) `on` delta) $ List.sortBy (compare `on` delta) later- diagnoseCluster c = Diagnostic (Right $ addHighlights hs $ renderingCaret dc bsc) Note (expect c) [] where- _ :^ Caret dc bsc = Prelude.head c- notes = Prelude.map diagnoseCluster clusters- rightHere = Right $ addHighlights hs $ renderingCaret d bs-- explicateWith x EmptyErr = Diagnostic rightHere Error ((text "unspecified error") <> x) notes- explicateWith x (FailErr r s) = Diagnostic (Right $ addHighlights hs r) Error ((fillSep $ text <$> words s) <> x) notes- explicateWith x (PanicErr r s) = Diagnostic (Right $ addHighlights hs r) Panic ((fillSep $ text <$> words s) <> x) notes- explicateWith x (Err (Diagnostic r l e es)) = Diagnostic (addHighlights hs <$> r) l (pp e <> x) (notes ++ fmap (addHighlights hs . fmap pp) es)-- errLoc EmptyErr = Just d- errLoc (FailErr r _) = Just $ delta r- errLoc (PanicErr r _) = Just $ delta r- errLoc (Err (Diagnostic (Left _) _ _ _)) = Nothing- errLoc (Err (Diagnostic (Right r) _ _ _)) = Just $ delta r
− Text/Trifecta/Parser/Result.hs
@@ -1,82 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Result--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Parser.Result - ( Result(..)- ) where--import Control.Applicative-import Data.Semigroup-import Data.Foldable-import Data.Functor.Apply-import Data.Functor.Plus-import Data.Traversable-import Data.Bifunctor-import Data.Sequence as Seq-import Text.Trifecta.Diagnostic.Prim-import Text.PrettyPrint.Free-import System.Console.Terminfo.PrettyPrint--data Result e a- = Success !(Seq (Diagnostic e)) a- | Failure !(Seq (Diagnostic e))- deriving Show--instance (Pretty e, Show a) => Pretty (Result e a) where- pretty (Success xs a) - | Seq.null xs = pretty (show a)- | otherwise = prettyList (toList xs) `above` pretty (show a)- pretty (Failure xs) = prettyList $ toList xs--instance (PrettyTerm e, Show a) => PrettyTerm (Result e a) where- prettyTerm (Success xs a)- | Seq.null xs = pretty (show a)- | otherwise = prettyTermList (toList xs) `above` pretty (show a)- prettyTerm (Failure xs) = prettyTermList $ toList xs--instance Functor (Result e) where- fmap f (Success xs a) = Success xs (f a)- fmap _ (Failure xs) = Failure xs--instance Bifunctor Result where- bimap f g (Success xs a) = Success (fmap (fmap f) xs) (g a)- bimap f _ (Failure xs) = Failure (fmap (fmap f) xs)--instance Foldable (Result e) where- foldMap f (Success _ a) = f a- foldMap _ (Failure _) = mempty--instance Traversable (Result e) where- traverse f (Success xs a) = Success xs <$> f a- traverse _ (Failure xs) = pure $ Failure xs--instance Applicative (Result e) where- pure = Success mempty- Success xs f <*> Success ys a = Success (xs <> ys) (f a)- Success xs _ <*> Failure ys = Failure (xs <> ys)- Failure xs <*> Success ys _ = Failure (xs <> ys)- Failure xs <*> Failure ys = Failure (xs <> ys)--instance Apply (Result e) where- (<.>) = (<*>)--instance Alt (Result e) where- Failure xs <!> Failure ys = Failure (xs <> ys)- Success xs a <!> Success ys _ = Success (xs <> ys) a- Success xs a <!> Failure ys = Success (xs <> ys) a- Failure xs <!> Success ys a = Success (xs <> ys) a--instance Plus (Result e) where- zero = Failure mempty--instance Alternative (Result e) where - (<|>) = (<!>)- empty = zero
− Text/Trifecta/Parser/Rich.hs
@@ -1,26 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Rich--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Parser.Rich- ( Rich- , rich- ) where--import Control.Monad (liftM)-import Text.Trifecta.Layout-import Text.Trifecta.Language-import Text.Trifecta.Language.Prim-import Text.Trifecta.Literate--type Rich m = Layout (Language (Literate m))--rich :: Monad m => LiterateState -> LanguageDef m -> Rich m a -> m (a, LiterateState)-rich lit def p = runLiterate (runLanguage (fst `liftM` runLayout p defaultLayoutState) (liftLanguageDef (liftLanguageDef def))) lit
− Text/Trifecta/Parser/Step.hs
@@ -1,63 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Step--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Parser.Step - ( Step(..)- , feed- , starve- , stepResult- ) where--import Data.Bifunctor-import Data.Semigroup.Reducer-import Data.Sequence-import Text.Trifecta.Rope.Prim-import Text.Trifecta.Diagnostic.Prim-import Text.Trifecta.Parser.Result--data Step e a- = StepDone !Rope !(Seq (Diagnostic e)) a- | StepFail !Rope !(Seq (Diagnostic e))- | StepCont !Rope (Result e a) (Rope -> Step e a)--instance (Show e, Show a) => Show (Step e a) where- showsPrec d (StepDone r xs a) = showParen (d > 10) $ - showString "StepDone " . showsPrec 11 r . showChar ' ' . showsPrec 11 xs . showChar ' ' . showsPrec 11 a- showsPrec d (StepFail r xs) = showParen (d > 10) $ - showString "StepFail " . showsPrec 11 r . showChar ' ' . showsPrec 11 xs- showsPrec d (StepCont r fin _) = showParen (d > 10) $ - showString "StepCont " . showsPrec 11 r . showChar ' ' . showsPrec 11 fin . showString " ..."- -instance Functor (Step e) where- fmap f (StepDone r xs a) = StepDone r xs (f a)- fmap _ (StepFail r xs) = StepFail r xs- fmap f (StepCont r z k) = StepCont r (fmap f z) (fmap f . k)--instance Bifunctor Step where- bimap f g (StepDone r xs a) = StepDone r (fmap (fmap f) xs) (g a)- bimap f _ (StepFail r xs) = StepFail r (fmap (fmap f) xs)- bimap f g (StepCont r z k) = StepCont r (bimap f g z) (bimap f g . k)--feed :: Reducer t Rope => t -> Step e r -> Step e r-feed t (StepDone r xs a) = StepDone (snoc r t) xs a-feed t (StepFail r xs) = StepFail (snoc r t) xs-feed t (StepCont r _ k) = k (snoc r t)--starve :: Step e a -> Result e a-starve (StepDone _ xs a) = Success xs a-starve (StepFail _ xs) = Failure xs-starve (StepCont _ z _) = z--stepResult :: Rope -> Result e a -> Step e a-stepResult r (Success xs a) = StepDone r xs a-stepResult r (Failure xs) = StepFail r xs-
− Text/Trifecta/Parser/Token.hs
@@ -1,24 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Token--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Parser.Token- ( module Text.Trifecta.Parser.Token.Combinators- -- * Text.Trifecta.Parser.Token.Prim- , decimal- , hexadecimal- , octal- ) where--import Text.Trifecta.Parser.Token.Prim-import Text.Trifecta.Parser.Token.Combinators---- expected to be imported manually--- import Text.Trifecta.Parser.Token.Style
− Text/Trifecta/Parser/Token/Combinators.hs
@@ -1,197 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Token.Combinators--- Copyright : (c) Edward Kmett 2011,--- (c) Daan Leijen 1999-2001--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable--- -------------------------------------------------------------------------------module Text.Trifecta.Parser.Token.Combinators- ( lexeme- , charLiteral- , stringLiteral- , natural- , integer- , double- , naturalOrDouble- , symbol- , symbolic- , parens- , braces- , angles- , brackets- , comma- , colon- , dot- , semiSep- , semiSep1- , commaSep- , commaSep1- ) where--import Data.ByteString as Strict hiding (map, zip, foldl, foldr)-import Control.Applicative-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Parser.Token.Prim-import Text.Trifecta.Highlight.Prim---- | @lexeme p@ first applies parser @p@ and then the 'whiteSpace'--- parser, returning the value of @p@. Every lexical--- token (lexeme) is defined using @lexeme@, this way every parse--- starts at a point without white space. Parsers that use @lexeme@ are--- called /lexeme/ parsers in this document.------ The only point where the 'whiteSpace' parser should be--- called explicitly is the start of the main parser in order to skip--- any leading white space.------ > mainParser = do { whiteSpace--- > ; ds <- many (lexeme digit)--- > ; eof--- > ; return (sum ds)--- > }-lexeme :: MonadParser m => m a -> m a-lexeme p = p <* whiteSpace---- | This lexeme parser parses a single literal character. Returns the--- literal character value. This parsers deals correctly with escape--- sequences. The literal character is parsed according to the grammar--- rules defined in the Haskell report (which matches most programming--- languages quite closely). -charLiteral :: MonadParser m => m Char-charLiteral = lexeme charLiteral'---- | This lexeme parser parses a literal string. Returns the literal--- string value. This parsers deals correctly with escape sequences and--- gaps. The literal string is parsed according to the grammar rules--- defined in the Haskell report (which matches most programming--- languages quite closely). --stringLiteral :: MonadParser m => m String-stringLiteral = lexeme stringLiteral'---- | This lexeme parser parses a natural number (a positive whole--- number). Returns the value of the number. The number can be--- specified in 'decimal', 'hexadecimal' or--- 'octal'. The number is parsed according to the grammar--- rules in the Haskell report. --natural :: MonadParser m => m Integer-natural = lexeme natural'---- | This lexeme parser parses an integer (a whole number). This parser--- is like 'natural' except that it can be prefixed with--- sign (i.e. \'-\' or \'+\'). Returns the value of the number. The--- number can be specified in 'decimal', 'hexadecimal'--- or 'octal'. The number is parsed according--- to the grammar rules in the Haskell report. --integer :: MonadParser m => m Integer-integer = lexeme int <?> "integer"- where- sign = negate <$ char '-'- <|> id <$ char '+'- <|> pure id- int = lexeme (highlight Operator sign) <*> natural'---- | This lexeme parser parses a floating point value. Returns the value--- of the number. The number is parsed according to the grammar rules--- defined in the Haskell report. --double :: MonadParser m => m Double-double = lexeme double'---- | This lexeme parser parses either 'natural' or a 'float'.--- Returns the value of the number. This parsers deals with--- any overlap in the grammar rules for naturals and floats. The number--- is parsed according to the grammar rules defined in the Haskell report. --naturalOrDouble :: MonadParser m => m (Either Integer Double)-naturalOrDouble = lexeme naturalOrDouble'---- | Lexeme parser @symbol s@ parses 'string' @s@ and skips--- trailing white space. --symbol :: MonadParser m => ByteString -> m ByteString-symbol name = lexeme (highlight Symbol (byteString name))---- | Lexeme parser @symbolic s@ parses 'char' @s@ and skips--- trailing white space. --symbolic :: MonadParser m => Char -> m Char-symbolic name = lexeme (highlight Symbol (char name))---- | Lexeme parser @parens p@ parses @p@ enclosed in parenthesis,--- returning the value of @p@.--parens :: MonadParser m => m a -> m a-parens = nesting . between (symbolic '(') (symbolic ')')---- | Lexeme parser @braces p@ parses @p@ enclosed in braces (\'{\' and--- \'}\'), returning the value of @p@. --braces :: MonadParser m => m a -> m a-braces = nesting . between (symbolic '{') (symbolic '}')---- | Lexeme parser @angles p@ parses @p@ enclosed in angle brackets (\'\<\'--- and \'>\'), returning the value of @p@. --angles :: MonadParser m => m a -> m a-angles = nesting . between (symbolic '<') (symbolic '>')---- | Lexeme parser @brackets p@ parses @p@ enclosed in brackets (\'[\'--- and \']\'), returning the value of @p@. --brackets :: MonadParser m => m a -> m a-brackets = nesting . between (symbolic '[') (symbolic ']')---- | Lexeme parser @comma@ parses the character \',\' and skips any--- trailing white space. Returns the string \",\". --comma :: MonadParser m => m Char-comma = symbolic ','---- | Lexeme parser @colon@ parses the character \':\' and skips any--- trailing white space. Returns the string \":\". --colon :: MonadParser m => m Char-colon = symbolic ':'---- | Lexeme parser @dot@ parses the character \'.\' and skips any--- trailing white space. Returns the string \".\". --dot :: MonadParser m => m Char-dot = symbolic '.'---- | Lexeme parser @semiSep p@ parses /zero/ or more occurrences of @p@--- separated by 'semi'. Returns a list of values returned by--- @p@.--semiSep :: MonadParser m => m a -> m [a]-semiSep p = sepBy p semi---- | Lexeme parser @semiSep1 p@ parses /one/ or more occurrences of @p@--- separated by 'semi'. Returns a list of values returned by @p@. --semiSep1 :: MonadParser m => m a -> m [a]-semiSep1 p = sepBy1 p semi---- | Lexeme parser @commaSep p@ parses /zero/ or more occurrences of--- @p@ separated by 'comma'. Returns a list of values returned--- by @p@. --commaSep :: MonadParser m => m a -> m [a]-commaSep p = sepBy p comma---- | Lexeme parser @commaSep1 p@ parses /one/ or more occurrences of--- @p@ separated by 'comma'. Returns a list of values returned--- by @p@. --commaSep1 :: MonadParser m => m a -> m [a]-commaSep1 p = sepBy p comma
− Text/Trifecta/Parser/Token/Prim.hs
@@ -1,217 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Token.Prim--- Copyright : (c) Edward Kmett 2011,--- (c) Daan Leijen 1999-2001--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable----------------------------------------------------------------------------------module Text.Trifecta.Parser.Token.Prim- ( charLiteral'- , characterChar- , stringLiteral'- , natural'- , integer'- , double'- , naturalOrDouble'- , decimal- , hexadecimal- , octal- ) where--import Data.Char (digitToInt)-import Data.Foldable-import Control.Applicative-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Highlight.Prim---- | This parser parses a single literal character. Returns the--- literal character value. This parsers deals correctly with escape--- sequences. The literal character is parsed according to the grammar--- rules defined in the Haskell report (which matches most programming--- languages quite closely).------ This parser does NOT swallow trailing whitespace.-charLiteral' :: MonadParser m => m Char-charLiteral' = highlight CharLiteral (between (char '\'') (char '\'' <?> "end of character") characterChar)- <?> "character"--characterChar, charEscape, charLetter :: MonadParser m => m Char-characterChar = charLetter <|> charEscape- <?> "literal character"-charEscape = highlight EscapeCode $ char '\\' *> escapeCode-charLetter = satisfy (\c -> (c /= '\'') && (c /= '\\') && (c > '\026'))---- | This parser parses a literal string. Returns the literal--- string value. This parsers deals correctly with escape sequences and--- gaps. The literal string is parsed according to the grammar rules--- defined in the Haskell report (which matches most programming--- languages quite closely).------ This parser does NOT swallow trailing whitespace-stringLiteral' :: MonadParser m => m String-stringLiteral' = highlight StringLiteral lit where- lit = Prelude.foldr (maybe id (:)) "" <$> between (char '"') (char '"' <?> "end of string") (many stringChar)- <?> "literal string"- stringChar = Just <$> stringLetter- <|> stringEscape- <?> "string character"- stringLetter = satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))-- stringEscape = highlight EscapeCode $ char '\\' *> esc where- esc = Nothing <$ escapeGap- <|> Nothing <$ escapeEmpty- <|> Just <$> escapeCode- escapeEmpty = char '&'- escapeGap = do skipSome space- char '\\' <?> "end of string gap"--escapeCode :: MonadParser m => m Char-escapeCode = (charEsc <|> charNum <|> charAscii <|> charControl) <?> "escape code"- where- charControl = (\c -> toEnum (fromEnum c - fromEnum 'A')) <$> (char '^' *> upper)- charNum = toEnum . fromInteger <$> num where- num = decimal- <|> (char 'o' *> number 8 octDigit)- <|> (char 'x' *> number 16 hexDigit)- charEsc = choice $ parseEsc <$> escMap- parseEsc (c,code) = code <$ char c- escMap = zip ("abfnrtv\\\"\'") ("\a\b\f\n\r\t\v\\\"\'")- charAscii = choice $ parseAscii <$> asciiMap- parseAscii (asc,code) = try $ code <$ string asc- asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2)- ascii2codes, ascii3codes :: [String]- ascii2codes = [ "BS","HT","LF","VT","FF","CR","SO"- , "SI","EM","FS","GS","RS","US","SP"]- ascii3codes = ["NUL","SOH","STX","ETX","EOT","ENQ","ACK"- ,"BEL","DLE","DC1","DC2","DC3","DC4","NAK"- ,"SYN","ETB","CAN","SUB","ESC","DEL"]- ascii2, ascii3 :: [Char]- ascii2 = ['\BS','\HT','\LF','\VT','\FF','\CR','\SO','\SI'- ,'\EM','\FS','\GS','\RS','\US','\SP']- ascii3 = ['\NUL','\SOH','\STX','\ETX','\EOT','\ENQ','\ACK'- ,'\BEL','\DLE','\DC1','\DC2','\DC3','\DC4','\NAK'- ,'\SYN','\ETB','\CAN','\SUB','\ESC','\DEL']----- | This parser parses a natural number (a positive whole--- number). Returns the value of the number. The number can be--- specified in 'decimal', 'hexadecimal' or--- 'octal'. The number is parsed according to the grammar--- rules in the Haskell report.------ This parser does NOT swallow trailing whitespace.-natural' :: MonadParser m => m Integer-natural' = highlight Number nat <?> "natural"--number :: MonadParser m => Integer -> m Char -> m Integer-number base baseDigit = do- digits <- some baseDigit- return $! foldl' (\x d -> base*x + toInteger (digitToInt d)) 0 digits---- | This parser parses an integer (a whole number). This parser--- is like 'natural' except that it can be prefixed with--- sign (i.e. \'-\' or \'+\'). Returns the value of the number. The--- number can be specified in 'decimal', 'hexadecimal'--- or 'octal'. The number is parsed according--- to the grammar rules in the Haskell report.------ This parser does NOT swallow trailing whitespace.------ Also, unlike the 'integer' parser, this parser does not admit spaces--- between the sign and the number.--integer' :: MonadParser m => m Integer-integer' = int <?> "integer"--sign :: MonadParser m => m (Integer -> Integer)-sign = highlight Operator- $ negate <$ char '-'- <|> id <$ char '+'- <|> pure id--int :: MonadParser m => m Integer-int = {-lexeme-} sign <*> highlight Number nat-nat, zeroNumber :: MonadParser m => m Integer-nat = zeroNumber <|> decimal-zeroNumber = char '0' *> (hexadecimal <|> octal <|> decimal <|> return 0) <?> ""---- | This parser parses a floating point value. Returns the value--- of the number. The number is parsed according to the grammar rules--- defined in the Haskell report.------ This parser does NOT swallow trailing whitespace.--double' :: MonadParser m => m Double-double' = highlight Number floating <?> "double"--floating :: MonadParser m => m Double-floating = decimal >>= fractExponent--fractExponent :: MonadParser m => Integer -> m Double-fractExponent n = (\fract expo -> (fromInteger n + fract) * expo) <$> fraction <*> option 1.0 exponent'- <|> (fromInteger n *) <$> exponent' where- fraction = Prelude.foldr op 0.0 <$> (char '.' *> (some digit <?> "fraction"))- op d f = (f + fromIntegral (digitToInt d))/10.0- exponent' = do- _ <- oneOf "eE"- f <- sign- e <- decimal <?> "exponent"- return (power (f e))- <?> "exponent"- power e- | e < 0 = 1.0/power(-e)- | otherwise = fromInteger (10^e)----- | This parser parses either 'natural' or a 'double'.--- Returns the value of the number. This parsers deals with--- any overlap in the grammar rules for naturals and floats. The number--- is parsed according to the grammar rules defined in the Haskell report.------ This parser does NOT swallow trailing whitespace.--naturalOrDouble' :: MonadParser m => m (Either Integer Double)-naturalOrDouble' = highlight Number natDouble <?> "number"--natDouble, zeroNumFloat, decimalFloat :: MonadParser m => m (Either Integer Double)-natDouble- = char '0' *> zeroNumFloat- <|> decimalFloat-zeroNumFloat- = Left <$> (hexadecimal <|> octal)- <|> decimalFloat- <|> fractFloat 0- <|> return (Left 0)-decimalFloat = do- n <- decimal- option (Left n) (fractFloat n)--fractFloat :: MonadParser m => Integer -> m (Either Integer Double)-fractFloat n = Right <$> fractExponent n---- | Parses a positive whole number in the decimal system. Returns the--- value of the number.--decimal :: MonadParser m => m Integer-decimal = number 10 digit---- | Parses a positive whole number in the hexadecimal system. The number--- should be prefixed with \"x\" or \"X\". Returns the value of the--- number.--hexadecimal :: MonadParser m => m Integer-hexadecimal = oneOf "xX" *> number 16 hexDigit---- | Parses a positive whole number in the octal system. The number--- should be prefixed with \"o\" or \"O\". Returns the value of the--- number.--octal :: MonadParser m => m Integer-octal = oneOf "oO" *> number 8 octDigit
− Text/Trifecta/Parser/Token/Style.hs
@@ -1,74 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Token.Style--- Copyright : (c) Edward Kmett 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable----------------------------------------------------------------------------------module Text.Trifecta.Parser.Token.Style- ( CommentStyle(..)- , emptyCommentStyle- , javaCommentStyle- , haskellCommentStyle- , buildSomeSpaceParser- ) where--import Control.Applicative-import Data.List (nub)-import qualified Data.ByteString.Char8 as B-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Highlight.Prim--data CommentStyle = CommentStyle- { commentStart :: String- , commentEnd :: String- , commentLine :: String- , commentNesting :: Bool- }--emptyCommentStyle, javaCommentStyle, haskellCommentStyle :: CommentStyle-emptyCommentStyle = CommentStyle "" "" "" True-javaCommentStyle = CommentStyle "/*" "*/" "//" True-haskellCommentStyle = CommentStyle "{-" "-}" "--" True---- | Use this to easily build the definition of whiteSpace for your MonadParser--- given a comment style and an underlying someWhiteSpace parser-buildSomeSpaceParser :: MonadParser m => m () -> CommentStyle -> m ()-buildSomeSpaceParser simpleSpace (CommentStyle startStyle endStyle lineStyle nestingStyle)- | noLine && noMulti = skipSome (simpleSpace <?> "")- | noLine = skipSome (simpleSpace <|> multiLineComment <?> "")- | noMulti = skipSome (simpleSpace <|> oneLineComment <?> "")- | otherwise = skipSome (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")- where- noLine = null lineStyle- noMulti = null startStyle- oneLineComment = highlight Comment $ do- _ <- try $ string lineStyle- r <- restOfLine- let b = B.length r- skipping $ if b /= 0 && B.last r == '\n' then Lines 1 0 (fromIntegral b) 0 else delta r- multiLineComment = highlight Comment $ do- _ <- try $ string startStyle- inComment- inComment- | nestingStyle = inCommentMulti- | otherwise = inCommentSingle- inCommentMulti- = () <$ try (string endStyle)- <|> multiLineComment *> inCommentMulti- <|> skipSome (noneOf startEnd) *> inCommentMulti- <|> oneOf startEnd *> inCommentMulti- <?> "end of comment"- startEnd = nub (endStyle ++ startStyle)- inCommentSingle- = () <$ try (string endStyle)- <|> skipSome (noneOf startEnd) *> inCommentSingle- <|> oneOf startEnd *> inCommentSingle- <?> "end of comment"
− Text/Trifecta/Rope.hs
@@ -1,26 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Rope--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Rope - ( Rope, rope, strands- -- * Strands of a rope- , Strand(..), strand- -- * Properties- , Delta(..)- , HasDelta(..)- , HasBytes(..)- , HighlightedRope(..)- ) where--import Text.Trifecta.Rope.Prim-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Highlighted
− Text/Trifecta/Rope/Bytes.hs
@@ -1,27 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Rope.Bytes--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Rope.Bytes- ( HasBytes(..)- ) where--import Data.ByteString as Strict-import Data.FingerTree-import Data.Int (Int64)--class HasBytes t where- bytes :: t -> Int64--instance HasBytes ByteString where- bytes = fromIntegral . Strict.length--instance (Measured v a, HasBytes v) => HasBytes (FingerTree v a) where- bytes = bytes . measure
− Text/Trifecta/Rope/Delta.hs
@@ -1,169 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Rope.Delta--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Rope.Delta- ( Delta(..)- , HasDelta(..)- , nextTab- , rewind- , near- , column- , columnByte- ) where--import Control.Applicative-import Data.Semigroup-import Data.Hashable-import Data.Int-import Data.Word-import Data.Foldable-import Data.Function (on)-import Data.FingerTree hiding (empty)-import Data.ByteString hiding (empty)-import qualified Data.ByteString.UTF8 as UTF8-import Text.Trifecta.Rope.Bytes-import Text.PrettyPrint.Free hiding (column)-import System.Console.Terminfo.PrettyPrint--data Delta- = Columns {-# UNPACK #-} !Int64 -- the number of characters- {-# UNPACK #-} !Int64 -- the number of bytes- | Tab {-# UNPACK #-} !Int64 -- the number of characters before the tab- {-# UNPACK #-} !Int64 -- the number of characters after the tab- {-# UNPACK #-} !Int64 -- the number of bytes- | Lines {-# UNPACK #-} !Int64 -- the number of newlines contained- {-# UNPACK #-} !Int64 -- the number of characters since the last newline- {-# UNPACK #-} !Int64 -- number of bytes- {-# UNPACK #-} !Int64 -- the number of bytes since the last newline- | Directed !ByteString -- current file name- {-# UNPACK #-} !Int64 -- the number of lines since the last line directive- {-# UNPACK #-} !Int64 -- the number of characters since the last newline- {-# UNPACK #-} !Int64 -- number of bytes- {-# UNPACK #-} !Int64 -- the number of bytes since the last newline- deriving Show--instance Eq Delta where- (==) = (==) `on` bytes--instance Ord Delta where- compare = compare `on` bytes--instance (HasDelta l, HasDelta r) => HasDelta (Either l r) where- delta = either delta delta--instance Pretty Delta where- pretty p = prettyTerm p *> empty--instance PrettyTerm Delta where- prettyTerm d = case d of- Columns c _ -> k f 0 c- Tab x y _ -> k f 0 (nextTab x + y)- Lines l c _ _ -> k f l c- Directed fn l c _ _ -> k (UTF8.toString fn) l c- where- k fn ln cn = bold (pretty fn) <> char ':' <> bold (int64 (ln+1)) <> char ':' <> bold (int64 (cn+1))- f = "(interactive)"--int64 :: Int64 -> Doc e-int64 = pretty . show--column :: HasDelta t => t -> Int64-column t = case delta t of- Columns c _ -> c- Tab b a _ -> nextTab b + a- Lines _ c _ _ -> c- Directed _ _ c _ _ -> c-{-# INLINE column #-}--columnByte :: Delta -> Int64-columnByte (Columns _ b) = b-columnByte (Tab _ _ b) = b-columnByte (Lines _ _ _ b) = b-columnByte (Directed _ _ _ _ b) = b-{-# INLINE columnByte #-}--instance HasBytes Delta where- bytes (Columns _ b) = b- bytes (Tab _ _ b) = b- bytes (Lines _ _ b _) = b- bytes (Directed _ _ _ b _) = b--instance Hashable Delta where- hash (Columns c a) = 0 `hashWithSalt` c `hashWithSalt` a- hash (Tab x y a) = 1 `hashWithSalt` x `hashWithSalt` y `hashWithSalt` a- hash (Lines l c b a) = 2 `hashWithSalt` l `hashWithSalt` c `hashWithSalt` b `hashWithSalt` a- hash (Directed p l c b a) = 3 `hashWithSalt` p `hashWithSalt` l `hashWithSalt` c `hashWithSalt` b `hashWithSalt` a--instance Monoid Delta where- mempty = Columns 0 0- mappend = (<>)--instance Semigroup Delta where- Columns c a <> Columns d b = Columns (c + d) (a + b)- Columns c a <> Tab x y b = Tab (c + x) y (a + b)- Columns _ a <> Lines l c t a' = Lines l c (t + a) a'- Columns _ a <> Directed p l c t a' = Directed p l c (t + a) a'- Lines l c t a <> Columns d b = Lines l (c + d) (t + b) (a + b)- Lines l c t a <> Tab x y b = Lines l (nextTab (c + x) + y) (t + b) (a + b)- Lines l _ t _ <> Lines m d t' b = Lines (l + m) d (t + t') b- Lines _ _ t _ <> Directed p l c t' a = Directed p l c (t + t') a- Tab x y a <> Columns d b = Tab x (y + d) (a + b)- Tab x y a <> Tab x' y' b = Tab x (nextTab (y + x') + y') (a + b)- Tab _ _ a <> Lines l c t a' = Lines l c (t + a ) a'- Tab _ _ a <> Directed p l c t a' = Directed p l c (t + a ) a'- Directed p l c t a <> Columns d b = Directed p l (c + d) (t + b ) (a + b)- Directed p l c t a <> Tab x y b = Directed p l (nextTab (c + x) + y) (t + b ) (a + b)- Directed p l _ t _ <> Lines m d t' b = Directed p (l + m) d (t + t') b- Directed _ _ _ t _ <> Directed p l c t' b = Directed p l c (t + t') b- -nextTab :: Int64 -> Int64-nextTab x = x + (8 - mod x 8)-{-# INLINE nextTab #-}--rewind :: Delta -> Delta-rewind (Lines n _ b d) = Lines n 0 (b - d) 0-rewind (Directed p n _ b d) = Directed p n 0 (b - d) 0-rewind _ = Columns 0 0-{-# INLINE rewind #-}--near :: (HasDelta s, HasDelta t) => s -> t -> Bool-near s t = rewind (delta s) == rewind (delta t)-{-# INLINE near #-}--class HasDelta t where- delta :: t -> Delta--instance HasDelta Delta where- delta = id--instance HasDelta Char where- delta '\t' = Tab 0 0 1- delta '\n' = Lines 1 0 1 0- delta c- | o <= 0x7f = Columns 1 1- | o <= 0x7ff = Columns 1 2- | o <= 0xffff = Columns 1 3- | otherwise = Columns 1 4- where o = fromEnum c--instance HasDelta Word8 where- delta 9 = Tab 0 0 1- delta 10 = Lines 1 0 1 0- delta n- | n <= 0x7f = Columns 1 1- | n >= 0xc0 && n <= 0xf4 = Columns 1 1- | otherwise = Columns 0 1--instance HasDelta ByteString where- delta = foldMap delta . unpack--instance (Measured v a, HasDelta v) => HasDelta (FingerTree v a) where- delta = delta . measure
− Text/Trifecta/Rope/Highlighted.hs
@@ -1,98 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Rope.Highlighted--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Rope.Highlighted- ( HighlightedRope(..)- ) where--import qualified Data.ByteString.Lazy.Char8 as L-import qualified Data.ByteString.Lazy.UTF8 as LazyUTF8-import Data.Foldable as F-import Data.Int (Int64)-import Text.Trifecta.IntervalMap as IM-import Data.Key hiding ((!))-import Data.List (sort)-import Data.Semigroup-import Data.Semigroup.Union-import Prelude hiding (head)-import System.Console.Terminfo.PrettyPrint-import Text.Blaze-import Text.Blaze.Internal-import Text.Blaze.Html5 hiding (b,i)-import Text.Blaze.Html5.Attributes hiding (title)-import Text.Trifecta.Rope.Delta-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Prim-import Text.Trifecta.Highlight.Class-import Text.Trifecta.Highlight.Effects-import Text.Trifecta.Highlight.Prim-import Text.PrettyPrint.Free--data HighlightedRope = HighlightedRope - { ropeHighlights :: !Highlights- , ropeContent :: {-# UNPACK #-} !Rope - }--instance HasDelta HighlightedRope where- delta = delta . ropeContent--instance HasBytes HighlightedRope where- bytes = bytes . ropeContent--instance Semigroup HighlightedRope where- HighlightedRope h bs <> HighlightedRope h' bs' = HighlightedRope (h `union` IM.offset (delta bs) h') (bs <> bs')--instance Monoid HighlightedRope where- mappend = (<>) - mempty = HighlightedRope mempty mempty--instance Highlightable HighlightedRope where- addHighlights h (HighlightedRope h' r) = HighlightedRope (h `union` h') r--data Located a = a :@ {-# UNPACK #-} !Int64-infix 5 :@-instance Eq (Located a) where- _ :@ m == _ :@ n = m == n-instance Ord (Located a) where- compare (_ :@ m) (_ :@ n) = compare m n--instance ToHtml HighlightedRope where- toHtml (HighlightedRope intervals r) = pre $ go 0 lbs effects where - lbs = L.fromChunks [bs | Strand bs _ <- F.toList (strands r)]- ln no = a ! name (toValue $ "line-" ++ show no) $ Empty- effects = sort $ [ i | (Interval lo hi, tok) <- intersections mempty (delta r) intervals- , i <- [ (Leaf "span" "<span" ">" ! class_ (toValue $ show tok)) :@ bytes lo- , preEscapedString "</span>" :@ bytes hi- ]- ] ++ mapWithKey (\k i -> ln k :@ i) (L.elemIndices '\n' lbs)- go _ cs [] = unsafeLazyByteString cs- go b cs ((eff :@ eb) : es) - | eb <= b = eff >> go b cs es - | otherwise = unsafeLazyByteString om >> go eb nom es- where (om,nom) = L.splitAt (fromIntegral (eb - b)) cs--instance Pretty HighlightedRope where- pretty (HighlightedRope _ r) = hsep $ [ pretty bs | Strand bs _ <- F.toList (strands r)]--instance PrettyTerm HighlightedRope where- prettyTerm (HighlightedRope intervals r) = go 0 lbs effects where- lbs = L.fromChunks [bs | Strand bs _ <- F.toList (strands r)]- effects = sort $ [ i | (Interval lo hi, tok) <- intersections mempty (delta r) intervals- , i <- [ pushToken tok :@ bytes lo- , popToken tok :@ bytes hi- ]- ]- go _ cs [] = prettyTerm (LazyUTF8.toString cs)- go b cs ((eff :@ eb) : es) - | eb <= b = eff <> go b cs es - | otherwise = prettyTerm (LazyUTF8.toString om) <> go eb nom es- where (om,nom) = L.splitAt (fromIntegral (eb - b)) cs
− Text/Trifecta/Rope/Prim.hs
@@ -1,114 +0,0 @@-{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, BangPatterns, PatternGuards #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Rope.Prim--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Rope.Prim- ( Rope(..)- , rope- , Strand(..)- , strand- , strands- , grabRest- , grabLine- ) where--import Data.Semigroup-import Data.Semigroup.Reducer-import Data.ByteString (ByteString)-import qualified Data.ByteString as Strict-import qualified Data.ByteString.Lazy as Lazy-import qualified Data.ByteString.UTF8 as UTF8-import Data.FingerTree as FingerTree-import Data.Foldable (toList)-import Data.Hashable-import Data.Int (Int64)-import Text.Trifecta.Util.Combinators as Util-import Text.Trifecta.Rope.Bytes-import Text.Trifecta.Rope.Delta--data Strand- = Strand {-# UNPACK #-} !ByteString !Delta- | LineDirective {-# UNPACK #-} !ByteString {-# UNPACK #-} !Int64- deriving Show--strand :: ByteString -> Strand-strand bs = Strand bs (delta bs)--instance Measured Delta Strand where- measure (Strand _ s) = delta s- measure (LineDirective p l) = delta (Directed p l 0 0 0)--instance Hashable Strand where- hash (Strand h _) = hashWithSalt 0 h- hash (LineDirective p l) = hash l `hashWithSalt` p--instance HasDelta Strand where- delta = measure--instance HasBytes Strand where- bytes (Strand _ d) = bytes d- bytes _ = 0--data Rope = Rope !Delta !(FingerTree Delta Strand) deriving Show--rope :: FingerTree Delta Strand -> Rope-rope r = Rope (measure r) r--strands :: Rope -> FingerTree Delta Strand-strands (Rope _ r) = r---- | grab a the contents of a rope from a given location up to a newline-grabRest :: Delta -> Rope -> r -> (Delta -> Lazy.ByteString -> r) -> r-grabRest i t kf ks = trim (delta l) (bytes i - bytes l) (toList r) where- trim j 0 (Strand h _ : xs) = go j h xs- trim _ k (Strand h _ : xs) = go i (Strict.drop (fromIntegral k) h) xs- trim j k (p : xs) = trim (j <> delta p) k xs - trim _ _ [] = kf- go j h s = ks j $ Lazy.fromChunks $ h : [ a | Strand a _ <- s ]- (l, r) = FingerTree.split (\b -> bytes b > bytes i) $ strands t---- | grab a the contents of a rope from a given location up to a newline-grabLine :: Delta -> Rope -> r -> (Delta -> Strict.ByteString -> r) -> r-grabLine i t kf ks = grabRest i t kf $ \c -> ks c . Util.fromLazy . Util.takeLine--instance HasBytes Rope where- bytes = bytes . measure--instance HasDelta Rope where- delta = measure--instance Measured Delta Rope where- measure (Rope s _) = s--instance Monoid Rope where- mempty = Rope mempty mempty- mappend = (<>)--instance Semigroup Rope where- Rope mx x <> Rope my y = Rope (mx <> my) (x `mappend` y)--instance Reducer Rope Rope where- unit = id--instance Reducer Strand Rope where- unit s = rope (FingerTree.singleton s)- cons s (Rope mt t) = Rope (delta s `mappend` mt) (s <| t)- snoc (Rope mt t) !s = Rope (mt `mappend` delta s) (t |> s)--instance Reducer Strict.ByteString Rope where- unit = unit . strand- cons = cons . strand- snoc r = snoc r . strand--instance Reducer [Char] Rope where- unit = unit . strand . UTF8.fromString- cons = cons . strand . UTF8.fromString- snoc r = snoc r . strand . UTF8.fromString
− Text/Trifecta/Util/Array.hs
@@ -1,378 +0,0 @@-{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Util.Array--- Copyright : Edward Kmett 2011--- Johan Tibell 2011--- License : BSD3------ Maintainer : ekmett@gmail.com--- Stability : experimental--- Portability : unknown------ Fast zero based arrays, based on the implementation in the HAMT-branch of--- unordered-containers-------------------------------------------------------------------------------module Text.Trifecta.Util.Array- ( Array- , MArray-- -- * Creation- , new- , new_- , empty- , singleton-- -- * Basic interface- , length- , lengthM- , read- , write- , index- , index_- , indexM_- , update- , insert- , delete-- , unsafeFreeze- , run- , run2- , copy- , copyM-- -- * Folds- , foldl'- , foldr-- , thaw- , map- , map'- , traverse- , filter- ) where--import qualified Data.Traversable as Traversable-import Control.Applicative (Applicative)-import Control.DeepSeq-import Control.Monad.ST-import GHC.Exts-import GHC.ST (ST(..))-import Prelude hiding (filter, foldr, length, map, read)----------------------------------------------------------------------------#if defined(ASSERTS)--- This fugly hack is brought by GHC's apparent reluctance to deal--- with MagicHash and UnboxedTuples when inferring types. Eek!-# define CHECK_BOUNDS(_func_,_len_,_k_) \-if (_k_) < 0 || (_k_) >= (_len_) then error ("Data.HashMap.Array." ++ (_func_) ++ ": bounds error, offset " ++ show (_k_) ++ ", length " ++ show (_len_)) else-# define CHECK_OP(_func_,_op_,_lhs_,_rhs_) \-if not ((_lhs_) _op_ (_rhs_)) then error ("Data.HashMap.Array." ++ (_func_) ++ ": Check failed: _lhs_ _op_ _rhs_ (" ++ show (_lhs_) ++ " vs. " ++ show (_rhs_) ++ ")") else-# define CHECK_GT(_func_,_lhs_,_rhs_) CHECK_OP(_func_,>,_lhs_,_rhs_)-# define CHECK_LE(_func_,_lhs_,_rhs_) CHECK_OP(_func_,<=,_lhs_,_rhs_)-#else-# define CHECK_BOUNDS(_func_,_len_,_k_)-# define CHECK_OP(_func_,_op_,_lhs_,_rhs_)-# define CHECK_GT(_func_,_lhs_,_rhs_)-# define CHECK_LE(_func_,_lhs_,_rhs_)-#endif--data Array a = Array {- unArray :: !(Array# a)-#if __GLASGOW_HASKELL__ < 702- , length :: {-# UNPACK #-} !Int-#endif- }--#if __GLASGOW_HASKELL__ >= 702-length :: Array a -> Int-length ary = I# (sizeofArray# (unArray ary))-{-# INLINE length #-}-#endif---- | Smart constructor-array :: Array# a -> Int -> Array a-#if __GLASGOW_HASKELL__ >= 702-array ary _n = Array ary-#else-array = Array-#endif-{-# INLINE array #-}--data MArray s a = MArray {- unMArray :: !(MutableArray# s a)-#if __GLASGOW_HASKELL__ < 702- , lengthM :: {-# UNPACK #-} !Int-#endif- }--#if __GLASGOW_HASKELL__ >= 702-lengthM :: MArray s a -> Int-lengthM mary = I# (sizeofMutableArray# (unMArray mary))-{-# INLINE lengthM #-}-#endif---- | Smart constructor-marray :: MutableArray# s a -> Int -> MArray s a-#if __GLASGOW_HASKELL__ >= 702-marray mary _n = MArray mary-#else-marray = MArray-#endif-{-# INLINE marray #-}----------------------------------------------------------------------------instance NFData a => NFData (Array a) where- rnf = rnfArray--rnfArray :: NFData a => Array a -> ()-rnfArray ary0 = go ary0 n0 0 where- n0 = length ary0- go !ary !n !i- | i >= n = ()- | otherwise = rnf (index ary i) `seq` go ary n (i+1)-{-# INLINE rnfArray #-}---- | Create a new mutable array of specified size, in the specified--- state thread, with each element containing the specified initial--- value.-new :: Int -> a -> ST s (MArray s a)-new n@(I# n#) b =- CHECK_GT("new",n,(0 :: Int))- ST $ \s -> case newArray# n# b s of- (# s', ary #) -> (# s', marray ary n #)-{-# INLINE new #-}--new_ :: Int -> ST s (MArray s a)-new_ n = new n undefinedElem--empty :: Array a-empty = run (new_ 0)--singleton :: a -> Array a-singleton x = run (new 1 x)-{-# INLINE singleton #-}--read :: MArray s a -> Int -> ST s a-read ary _i@(I# i#) = ST $ \ s ->- CHECK_BOUNDS("read", lengthM ary, _i)- readArray# (unMArray ary) i# s-{-# INLINE read #-}--write :: MArray s a -> Int -> a -> ST s ()-write ary _i@(I# i#) b = ST $ \ s ->- CHECK_BOUNDS("write", lengthM ary, _i)- case writeArray# (unMArray ary) i# b s of- s' -> (# s' , () #)-{-# INLINE write #-}--index :: Array a -> Int -> a-index ary _i@(I# i#) =- CHECK_BOUNDS("index", length ary, _i)- case indexArray# (unArray ary) i# of (# b #) -> b-{-# INLINE index #-}--index_ :: Array a -> Int -> ST s a-index_ ary _i@(I# i#) =- CHECK_BOUNDS("index_", length ary, _i)- case indexArray# (unArray ary) i# of (# b #) -> return b-{-# INLINE index_ #-}--indexM_ :: MArray s a -> Int -> ST s a-indexM_ ary _i@(I# i#) =- CHECK_BOUNDS("index_", lengthM ary, _i)- ST $ \ s# -> readArray# (unMArray ary) i# s#-{-# INLINE indexM_ #-}--unsafeFreeze :: MArray s a -> ST s (Array a)-unsafeFreeze mary = - ST $ \s -> case unsafeFreezeArray# (unMArray mary) s of- (# s', ary #) -> (# s', array ary (lengthM mary) #)-{-# INLINE unsafeFreeze #-}--run :: (forall s . ST s (MArray s e)) -> Array e-run act = runST $ act >>= unsafeFreeze-{-# INLINE run #-}--run2 :: (forall s. ST s (MArray s e, a)) -> (Array e, a)-run2 k = runST $ do- (marr,b) <- k- arr <- unsafeFreeze marr- return (arr,b)---- | Unsafely copy the elements of an array. Array bounds are not checked.-copy :: Array e -> Int -> MArray s e -> Int -> Int -> ST s ()-#if __GLASGOW_HASKELL__ >= 702-copy !src !_sidx@(I# sidx#) !dst !_didx@(I# didx#) _n@(I# n#) =- CHECK_LE("copy", _sidx + _n, length src)- CHECK_LE("copy", _didx + _n, lengthM dst)- ST $ \ s# -> case copyArray# (unArray src) sidx# (unMArray dst) didx# n# s# of- s2 -> (# s2, () #)-#else-copy !src !sidx !dst !didx n =- CHECK_LE("copy", sidx + n, length src)- CHECK_LE("copy", didx + n, lengthM dst)- copy_loop sidx didx 0 where- copy_loop !i !j !c- | c >= n = return ()- | otherwise = do- b <- index_ src i- write dst j b- copy_loop (i+1) (j+1) (c+1)-#endif---- | Unsafely copy the elements of an array. Array bounds are not checked.-copyM :: MArray s e -> Int -> MArray s e -> Int -> Int -> ST s ()-#if __GLASGOW_HASKELL__ >= 702-copyM !src !_sidx@(I# sidx#) !dst !_didx@(I# didx#) _n@(I# n#) =- CHECK_BOUNDS("copyM: src", lengthM src, _sidx + _n - 1)- CHECK_BOUNDS("copyM: dst", lengthM dst, _didx + _n - 1)- ST $ \ s# -> case copyMutableArray# (unMArray src) sidx# (unMArray dst) didx# n# s# of- s2 -> (# s2, () #)-#else-copyM !src !sidx !dst !didx n =- CHECK_BOUNDS("copyM: src", lengthM src, sidx + n - 1)- CHECK_BOUNDS("copyM: dst", lengthM dst, didx + n - 1)- copy_loop sidx didx 0 where- copy_loop !i !j !c- | c >= n = return ()- | otherwise = do - b <- indexM_ src i- write dst j b- copy_loop (i+1) (j+1) (c+1)-#endif---- | /O(n)/ Insert an element at the given position in this array,--- increasing its size by one.-insert :: Array e -> Int -> e -> Array e-insert ary idx b =- CHECK_BOUNDS("insert", count + 1, idx)- run $ do- mary <- new_ (count+1)- copy ary 0 mary 0 idx- write mary idx b- copy ary idx mary (idx+1) (count-idx)- return mary - where !count = length ary-{-# INLINE insert #-}---- | /O(n)/ Update the element at the given position in this array.-update :: Array e -> Int -> e -> Array e-update ary idx b =- CHECK_BOUNDS("update", count, idx)- run $ do- mary <- thaw ary 0 count- write mary idx b- return mary- where !count = length ary-{-# INLINE update #-}--foldl' :: (b -> a -> b) -> b -> Array a -> b-foldl' f = \ z0 ary0 -> go ary0 (length ary0) 0 z0 where- go ary n i !z- | i >= n = z- | otherwise = go ary n (i+1) (f z (index ary i))-{-# INLINE foldl' #-}--foldr :: (a -> b -> b) -> b -> Array a -> b-foldr f = \ z0 ary0 -> go ary0 (length ary0) 0 z0 where- go ary n i z- | i >= n = z- | otherwise = f (index ary i) (go ary n (i+1) z)-{-# INLINE foldr #-}--undefinedElem :: a-undefinedElem = error "Undefined element"--thaw :: Array e -> Int -> Int -> ST s (MArray s e)-#if __GLASGOW_HASKELL__ >= 702-thaw !ary !_o@(I# o#) !n@(I# n#) =- CHECK_LE("thaw", _o + n, length ary)- ST $ \ s -> case thawArray# (unArray ary) o# n# s of- (# s2, mary# #) -> (# s2, marray mary# n #)-#else-thaw !ary !o !n =- CHECK_LE("thaw", o + n, length ary)- do mary <- new_ n- copy ary o mary 0 n- return mary-#endif-{-# INLINE thaw #-}---- | /O(n)/ Delete an element at the given position in this array,--- decreasing its size by one.-delete :: Array e -> Int -> Array e-delete ary idx = run $ do- mary <- new_ (count-1)- copy ary 0 mary 0 idx- copy ary (idx+1) mary idx (count-(idx+1))- return mary- where !count = length ary-{-# INLINE delete #-}--map :: (a -> b) -> Array a -> Array b-map f = \ ary ->- let !n = length ary- in run $ do- mary <- new_ n- go ary mary 0 n- where- go ary mary i n- | i >= n = return mary- | otherwise = do- write mary i $ f (index ary i)- go ary mary (i+1) n-{-# INLINE map #-}---- | Strict version of 'map'.-map' :: (a -> b) -> Array a -> Array b-map' f = \ ary ->- let !n = length ary- in run $ do- mary <- new_ n- go ary mary 0 n- where- go ary mary i n- | i >= n = return mary- | otherwise = do- write mary i $! f (index ary i)- go ary mary (i+1) n-{-# INLINE map' #-}--fromList :: Int -> [a] -> Array a-fromList n xs0 = run $ do- mary <- new_ n- go xs0 mary 0- where- go [] !mary !_ = return mary- go (x:xs) mary i = do write mary i x- go xs mary (i+1)--toList :: Array a -> [a]-toList = foldr (:) []--traverse :: Applicative f => (a -> f b) -> Array a -> f (Array b)-traverse f = \ ary ->- fromList (length ary) `fmap`- Traversable.traverse f (toList ary)-{-# INLINE traverse #-}--filter :: (a -> Bool) -> Array a -> Array a-filter p = \ ary ->- let !n = length ary- in run $ do- mary <- new_ n- go ary mary 0 0 n- where- go ary mary i j n- | i >= n = if i == j- then return mary- else do mary2 <- new_ j- copyM mary 0 mary2 0 j- return mary2- | p el = write mary j el >> go ary mary (i+1) (j+1) n- | otherwise = go ary mary (i+1) j n- where el = index ary i-{-# INLINE filter #-}
− Text/Trifecta/Util/Combinators.hs
@@ -1,52 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Util.Combinators--- Copyright : (C) 2011 Edward Kmett,--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : experimental--- Portability : non-portable---------------------------------------------------------------------------------module Text.Trifecta.Util.Combinators- ( argmin- , argmax- -- * ByteString conversions- , fromLazy- , toLazy- , takeLine- , (<$!>)- ) where--import Data.ByteString.Lazy as Lazy-import Data.ByteString as Strict--argmin :: Ord b => (a -> b) -> a -> a -> a-argmin f a b- | f a <= f b = a- | otherwise = b-{-# INLINE argmin #-}--argmax :: Ord b => (a -> b) -> a -> a -> a-argmax f a b- | f a > f b = a- | otherwise = b-{-# INLINE argmax #-}--fromLazy :: Lazy.ByteString -> Strict.ByteString-fromLazy = Strict.concat . Lazy.toChunks- -toLazy :: Strict.ByteString -> Lazy.ByteString-toLazy = Lazy.fromChunks . return--takeLine :: Lazy.ByteString -> Lazy.ByteString-takeLine s = case Lazy.elemIndex 10 s of- Just i -> Lazy.take (i + 1) s- Nothing -> s--infixl 4 <$!>-(<$!>) :: Monad m => (a -> b) -> m a -> m b-f <$!> m = do- a <- m - return $! f a
+ src/Text/Trifecta.hs view
@@ -0,0 +1,30 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta+ ( module Text.Trifecta.Diagnostic+ , module Text.Trifecta.Highlight+ , module Text.Trifecta.Language+ , module Text.Trifecta.Layout+ , module Text.Trifecta.Literate+ , module Text.Trifecta.Parser+ , module Text.Trifecta.Rope+ , module System.Console.Terminfo.PrettyPrint+ ) where++import Text.Trifecta.Diagnostic+import Text.Trifecta.Highlight+import Text.Trifecta.Language+import Text.Trifecta.Layout+import Text.Trifecta.Literate+import Text.Trifecta.Parser+import Text.Trifecta.Rope+import System.Console.Terminfo.PrettyPrint
+ src/Text/Trifecta/Diagnostic.hs view
@@ -0,0 +1,40 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic + ( + -- * Diagnostics+ Diagnostic(..)+ -- * Rendering+ , Renderable(..)+ , Source+ , rendering+ , renderingCaret+ , Caret(..), Careted(..)+ , Span(..), Spanned(..)+ , Fixit(..), Rendered(..)+ -- * Emitting diagnostics+ , MonadDiagnostic(..)+ , panic, panicAt+ , fatal, fatalAt+ , err, errAt+ , warn, warnAt+ , note, noteAt+ , verbose, verboseAt+ -- * Diagnostic Levels+ , DiagnosticLevel(..)+ ) where++import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Diagnostic.Combinators+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Rendering
+ src/Text/Trifecta/Diagnostic/Class.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies, FlexibleContexts, UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Class+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- Provides a class for logging and throwing expressive diagnostics.+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Class+ ( MonadDiagnostic(..)+ ) where++import Control.Monad.Trans.Class+import Control.Monad.Trans.State.Lazy as Lazy+import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import Data.Monoid+import Text.Trifecta.Diagnostic.Prim++class Monad m => MonadDiagnostic e m | m -> e where+ throwDiagnostic :: Diagnostic e -> m a+ logDiagnostic :: Diagnostic e -> m ()++instance MonadDiagnostic e m => MonadDiagnostic e (Lazy.StateT s m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance MonadDiagnostic e m => MonadDiagnostic e (Strict.StateT s m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance MonadDiagnostic e m => MonadDiagnostic e (ReaderT r m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.WriterT w m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.WriterT w m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Lazy.RWST r w s m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance (MonadDiagnostic e m, Monoid w) => MonadDiagnostic e (Strict.RWST r w s m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance MonadDiagnostic e m => MonadDiagnostic e (IdentityT m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic
+ src/Text/Trifecta/Diagnostic/Combinators.hs view
@@ -0,0 +1,57 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Combinators+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- Combinators for throwing and logging expressive diagnostics+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Combinators+ ( panic, panicAt+ , fatal, fatalAt+ , err, errAt+ , warn, warnAt+ , note, noteAt+ , verbose, verboseAt+ ) where++import Control.Applicative+import Control.Monad.Instances ()+import Text.Trifecta.Parser.Class+import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.Trifecta.Diagnostic.Rendering.Caret+import Text.Trifecta.Rope.Delta++rendCaret :: MonadParser m => m Rendering+rendCaret = (delta >>= addCaret) <$> rend++panicAt, fatalAt, errAt :: MonadDiagnostic e m => [Diagnostic e] -> e -> Rendering -> m a+panicAt es e r = throwDiagnostic $ Diagnostic (Right r) Panic e es+fatalAt es e r = throwDiagnostic $ Diagnostic (Right r) Fatal e es+errAt es e r = throwDiagnostic $ Diagnostic (Right r) Error e es++panic, fatal, err :: (MonadParser m, MonadDiagnostic e m) => [Diagnostic e] -> e -> m a+panic es e = rendCaret >>= panicAt es e+fatal es e = rendCaret >>= fatalAt es e+err es e = rendCaret >>= errAt es e++warnAt, noteAt :: MonadDiagnostic e m => [Diagnostic e] -> e -> Rendering -> m ()+warnAt es e r = logDiagnostic $ Diagnostic (Right r) Warning e es+noteAt es e r = logDiagnostic $ Diagnostic (Right r) Note e es++verboseAt :: MonadDiagnostic e m => Int -> [Diagnostic e] -> e -> Rendering -> m ()+verboseAt l es e r = logDiagnostic $ Diagnostic (Right r) (Verbose l) e es++warn, note :: (MonadParser m, MonadDiagnostic e m) => [Diagnostic e] -> e -> m ()+warn es e = rendCaret >>= warnAt es e+note es e = rendCaret >>= noteAt es e++verbose :: (MonadParser m, MonadDiagnostic e m) => Int -> [Diagnostic e] -> e -> m ()+verbose l es e = rendCaret >>= verboseAt l es e
+ src/Text/Trifecta/Diagnostic/Err.hs view
@@ -0,0 +1,87 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Err+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- The unlocated error type used internally within the parser.+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Err+ ( Err(..)+ , knownErr+ , fatalErr+ ) where++import Control.Applicative+import Data.Foldable+import Data.Traversable+import Data.Semigroup+import Data.Functor.Plus+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Rendering.Prim++data Err e+ = EmptyErr -- no error specified, unlocated+ | FailErr Rendering String -- a recoverable error caused by fail from a known location+ | PanicErr Rendering String -- something is bad with the grammar, fail fast+ | Err !(Diagnostic e) -- a user defined error message+ deriving Show++knownErr :: Err e -> Bool+knownErr EmptyErr = False+knownErr _ = True++fatalErr :: Err e -> Bool+fatalErr (Err (Diagnostic _ Panic _ _)) = True+fatalErr (Err (Diagnostic _ Fatal _ _)) = True+fatalErr (PanicErr _ _) = True+fatalErr _ = False++instance Functor Err where+ fmap _ EmptyErr = EmptyErr+ fmap _ (FailErr r s) = FailErr r s+ fmap _ (PanicErr r s) = PanicErr r s+ fmap f (Err e) = Err (fmap f e)++instance Foldable Err where+ foldMap _ EmptyErr = mempty+ foldMap _ FailErr{} = mempty+ foldMap _ PanicErr{} = mempty+ foldMap f (Err e) = foldMap f e++instance Traversable Err where+ traverse _ EmptyErr = pure EmptyErr+ traverse _ (FailErr r s) = pure $ FailErr r s+ traverse _ (PanicErr r s) = pure $ PanicErr r s+ traverse f (Err e) = Err <$> traverse f e++-- | Merge two errors, selecting the most severe.+instance Alt Err where+ a <!> EmptyErr = a+ _ <!> a@(Err (Diagnostic _ Panic _ _)) = a+ a@(Err (Diagnostic _ Panic _ _)) <!> _ = a+ _ <!> a@PanicErr{} = a+ a@PanicErr{} <!> _ = a+ _ <!> a@(Err (Diagnostic _ Fatal _ _)) = a+ a@(Err (Diagnostic _ Fatal _ _)) <!> _ = a+ _ <!> b = b+ {-# INLINE (<!>) #-}++-- | Merge two errors, selecting the most severe.+instance Plus Err where+ zero = EmptyErr++-- | Merge two errors, selecting the most severe.+instance Semigroup (Err t) where+ (<>) = (<!>)+ times1p _ = id++-- | Merge two errors, selecting the most severe.+instance Monoid (Err t) where+ mempty = EmptyErr+ mappend = (<!>)
+ src/Text/Trifecta/Diagnostic/Err/Log.hs view
@@ -0,0 +1,43 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Err.Log+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Err.Log+ ( ErrLog(..)+ ) where++import Data.Functor.Plus+import Data.Semigroup+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Highlight.Prim+import Data.Semigroup.Union (union, empty)+import Data.Sequence (Seq)++data ErrLog e = ErrLog+ { errLog :: !(Seq (Diagnostic e))+ , errHighlights :: !Highlights+ }++instance Functor ErrLog where+ fmap f (ErrLog a b) = ErrLog (fmap (fmap f) a) b++instance Alt ErrLog where+ ErrLog a b <!> ErrLog a' b' = ErrLog (a <> a') (union b b')+ {-# INLINE (<!>) #-}++instance Plus ErrLog where+ zero = ErrLog mempty empty+ +instance Semigroup (ErrLog e) where+ (<>) = (<!>) ++instance Monoid (ErrLog e) where+ mempty = zero+ mappend = (<!>)
+ src/Text/Trifecta/Diagnostic/Err/State.hs view
@@ -0,0 +1,42 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Err.State+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Err.State+ ( ErrState(..)+ ) where++import Data.Functor.Plus+import Data.Set as Set+import Data.Semigroup+import Text.Trifecta.Diagnostic.Err+import Text.Trifecta.Diagnostic.Rendering.Caret++data ErrState e = ErrState+ { errExpected :: !(Set (Careted String))+ , errMessage :: !(Err e)+ }++instance Functor ErrState where+ fmap f (ErrState a b) = ErrState a (fmap f b)++instance Alt ErrState where+ ErrState a b <!> ErrState a' b' = ErrState (a <> a') (b <> b')+ {-# INLINE (<!>) #-}++instance Plus ErrState where+ zero = ErrState mempty mempty++instance Semigroup (ErrState e) where+ (<>) = (<!>)++instance Monoid (ErrState e) where+ mempty = zero+ mappend = (<!>)
+ src/Text/Trifecta/Diagnostic/Level.hs view
@@ -0,0 +1,66 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Level+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- A fairly straightforward set of common error levels.+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Level+ ( DiagnosticLevel(..)+ ) where++import Control.Applicative+import Data.Semigroup+import Text.PrettyPrint.Free+import System.Console.Terminfo.PrettyPrint++-- | The severity of an error (or message)+data DiagnosticLevel+ = Verbose !Int -- ^ a comment we should only show to the excessively curious+ | Note -- ^ a comment+ | Warning -- ^ a warning, computation continues+ | Error -- ^ a user specified error+ | Fatal -- ^ a user specified fatal error+ | Panic -- ^ a non-maskable death sentence thrown by the parser itself+ deriving (Eq,Show,Read)++instance Ord DiagnosticLevel where+ compare (Verbose n) (Verbose m) = compare m n+ compare (Verbose _) _ = LT+ compare Note (Verbose _) = GT+ compare Note Note = EQ+ compare Note _ = LT+ compare Warning (Verbose _) = GT+ compare Warning Note = GT+ compare Warning Warning = EQ+ compare Warning _ = LT+ compare Error Error = EQ+ compare Error Fatal = LT+ compare Error Panic = LT+ compare Error _ = GT+ compare Fatal Panic = LT+ compare Fatal Fatal = EQ+ compare Fatal _ = GT+ compare Panic Panic = EQ+ compare Panic _ = GT++-- | Compute the maximum of two diagnostic levels+instance Semigroup DiagnosticLevel where+ (<>) = max++instance Pretty DiagnosticLevel where+ pretty p = prettyTerm p *> empty++-- | pretty print as a color coded description+instance PrettyTerm DiagnosticLevel where+ prettyTerm (Verbose n) = blue $ text "verbose (" <> prettyTerm n <> char ')'+ prettyTerm Note = black $ text "note"+ prettyTerm Warning = magenta $ text "warning"+ prettyTerm Error = red $ text "error"+ prettyTerm Fatal = standout $ red $ text "fatal"+ prettyTerm Panic = standout $ red $ text "panic"
+ src/Text/Trifecta/Diagnostic/Prim.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE FlexibleContexts, DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Prim+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- Rich diagnostics+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Prim+ ( Diagnostic(..)+ ) where++import Control.Applicative+import Control.Comonad+import Control.Monad (guard)+import Control.Exception+import Data.Functor.Apply+import Data.Foldable+import Data.Traversable+import Data.List.NonEmpty hiding (map)+import Data.Semigroup+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.Trifecta.Diagnostic.Level+import Text.PrettyPrint.Free+import Text.Trifecta.Highlight.Class+import System.Console.Terminfo.PrettyPrint+import Prelude hiding (log)+import Data.Typeable++data Diagnostic m = Diagnostic !(Either String Rendering) !DiagnosticLevel m [Diagnostic m]+ deriving (Show, Typeable)++instance Highlightable (Diagnostic e) where+ addHighlights h (Diagnostic rs l m xs) = Diagnostic (addHighlights h <$> rs) l m (addHighlights h <$> xs)++instance (Typeable m, Show m) => Exception (Diagnostic m)++instance Renderable (Diagnostic m) where+ render (Diagnostic r _ _ _) = either (const emptyRendering) id r++instance HasDelta (Diagnostic m) where+ delta (Diagnostic r _ _ _) = either (const mempty) delta r++instance HasBytes (Diagnostic m) where+ bytes (Diagnostic r _ _ _) = either (const 0) (bytes . delta) r++instance Comonad Diagnostic where+ extend f d@(Diagnostic r l _ xs) = Diagnostic r l (f d) (map (extend f) xs)+ extract (Diagnostic _ _ m _) = m++instance Pretty m => Pretty (Diagnostic m) where+ pretty (Diagnostic src l m xs) = case src of+ Left p -> vsep $ [pretty p <> msg]+ <|> children+ Right r -> vsep $ [pretty (delta r) <> msg]+ <|> pretty r <$ guard (not (nullRendering r))+ <|> children+ where+ msg = char ':' <+> pretty l <> char ':' <+> nest 4 (pretty m)+ children = indent 2 (prettyList xs) <$ guard (not (null xs))++ prettyList = vsep . Prelude.map pretty++instance PrettyTerm m => PrettyTerm (Diagnostic m) where+ prettyTerm (Diagnostic src l m xs) = case src of+ Left p -> vsep $ [prettyTerm p <> msg]+ <|> children+ Right r -> vsep $ [prettyTerm (delta r) <> msg]+ <|> prettyTerm r <$ guard (not (nullRendering r))+ <|> children+ where+ msg = char ':' <+> prettyTerm l <> char ':' <+> nest 4 (prettyTerm m)+ children = indent 2 (prettyTermList xs) <$ guard (not (null xs))+ prettyTermList = vsep . Prelude.map prettyTerm++instance Functor Diagnostic where+ fmap f (Diagnostic r l m xs) = Diagnostic r l (f m) $ map (fmap f) xs++instance Foldable Diagnostic where+ foldMap f (Diagnostic _ _ m xs) = f m `mappend` foldMap (foldMap f) xs++instance Traversable Diagnostic where+ traverse f (Diagnostic r l m xs) = Diagnostic r l <$> f m <*> traverse (traverse f) xs++instance Foldable1 Diagnostic where+ foldMap1 f (Diagnostic _ _ m []) = f m+ foldMap1 f (Diagnostic _ _ m (x:xs)) = f m <> foldMap1 (foldMap1 f) (x:|xs)++instance Traversable1 Diagnostic where+ traverse1 f (Diagnostic r l m []) = fmap (\fm -> Diagnostic r l fm []) (f m)+ traverse1 f (Diagnostic r l m (x:xs)) = (\fm (y:|ys) -> Diagnostic r l fm (y:ys))+ <$> f m+ <.> traverse1 (traverse1 f) (x:|xs)
+ src/Text/Trifecta/Diagnostic/Rendering.hs view
@@ -0,0 +1,23 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Rendering+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Rendering+ ( Renderable(..)+ , Source, rendering, renderingCaret+ , Caret(..), Careted(..)+ , Span(..), Spanned(..)+ , Fixit(..), Rendered(..)+ ) where++import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.Trifecta.Diagnostic.Rendering.Caret+import Text.Trifecta.Diagnostic.Rendering.Span+import Text.Trifecta.Diagnostic.Rendering.Fixit
+ src/Text/Trifecta/Diagnostic/Rendering/Caret.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Rendering.Caret+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Rendering.Caret+ ( Caret(..)+ , caret+ , Careted(..)+ , careted+ -- * Internals+ , drawCaret+ , addCaret+ , caretEffects+ , renderingCaret+ ) where++import Control.Applicative+import Control.Comonad+import Data.ByteString (ByteString)+import Data.Foldable+import Data.Hashable+import Data.Semigroup+import Data.Semigroup.Reducer+import Data.Traversable+import Prelude hiding (span)+import System.Console.Terminfo.Color+import System.Console.Terminfo.PrettyPrint+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Parser.Class+import Text.Trifecta.Diagnostic.Rendering.Prim++-- |+-- > In file included from baz.c:9+-- > In file included from bar.c:4+-- > foo.c:8:36: note+-- > int main(int argc, char ** argv) { int; }+-- > ^+data Caret = Caret !Delta {-# UNPACK #-} !ByteString deriving (Eq,Ord,Show)++instance Hashable Caret where+ hash (Caret d bs) = hash d `hashWithSalt` bs++caretEffects :: [ScopedEffect]+caretEffects = [soft (Foreground Green), soft Bold]++drawCaret :: Delta -> Delta -> Lines -> Lines+drawCaret p = ifNear p $ draw caretEffects 1 (fromIntegral (column p)) "^"++addCaret :: Delta -> Rendering -> Rendering+addCaret p r = drawCaret p .# r++caret :: MonadParser m => m Caret+caret = Caret <$> position <*> line++careted :: MonadParser m => m a -> m (Careted a)+careted p = do+ m <- position+ l <- line+ a <- p+ return $ a :^ Caret m l++instance HasBytes Caret where+ bytes = bytes . delta++instance HasDelta Caret where+ delta (Caret d _) = d++instance Renderable Caret where+ render (Caret d bs) = addCaret d $ rendering d bs++instance Reducer Caret Rendering where+ unit = render++instance Semigroup Caret where+ a <> _ = a++renderingCaret :: Delta -> ByteString -> Rendering+renderingCaret d bs = addCaret d $ rendering d bs++data Careted a = a :^ Caret deriving (Eq,Ord,Show)++instance Functor Careted where+ fmap f (a :^ s) = f a :^ s++instance HasDelta (Careted a) where+ delta (_ :^ c) = delta c++instance HasBytes (Careted a) where+ bytes (_ :^ c) = bytes c++instance Comonad Careted where+ extend f as@(_ :^ s) = f as :^ s+ extract (a :^ _) = a++instance Foldable Careted where+ foldMap f (a :^ _) = f a++instance Traversable Careted where+ traverse f (a :^ s) = (:^ s) <$> f a++instance Renderable (Careted a) where+ render (_ :^ a) = render a++instance Reducer (Careted a) Rendering where+ unit = render++instance Hashable a => Hashable (Careted a) where+
+ src/Text/Trifecta/Diagnostic/Rendering/Fixit.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Rendering.Fixit+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Rendering.Fixit+ ( Fixit(..)+ , drawFixit+ , addFixit+ , fixit+ ) where++import Data.Functor+import Data.Hashable+import Data.ByteString (ByteString)+import qualified Data.ByteString as Strict+import qualified Data.ByteString.UTF8 as UTF8+import Data.Semigroup.Reducer+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.Trifecta.Diagnostic.Rendering.Span+import Text.Trifecta.Parser.Class+import Text.Trifecta.Util.Combinators+import System.Console.Terminfo.Color+import System.Console.Terminfo.PrettyPrint+import Prelude hiding (span)++-- |+-- > int main(int argc char ** argv) { int; }+-- > ^+-- > ,+drawFixit :: Delta -> Delta -> String -> Delta -> Lines -> Lines+drawFixit s e rpl d a = ifNear l (draw [soft (Foreground Blue)] 2 (fromIntegral (column l)) rpl) d + $ drawSpan s e d a+ where l = argmin bytes s e++addFixit :: Delta -> Delta -> String -> Rendering -> Rendering+addFixit s e rpl r = drawFixit s e rpl .# r++data Fixit = Fixit + { fixitSpan :: {-# UNPACK #-} !Span+ , fixitReplacement :: {-# UNPACK #-} !ByteString + } deriving (Eq,Ord,Show)++instance Hashable Fixit where+ hash (Fixit s b) = hash s `hashWithSalt` b++instance Reducer Fixit Rendering where+ unit = render++instance Renderable Fixit where+ render (Fixit (Span s e bs) r) = addFixit s e (UTF8.toString r) $ rendering s bs++fixit :: MonadParser m => m Strict.ByteString -> m Fixit+fixit p = (\(r :~ s) -> Fixit s r) <$> spanned p
+ src/Text/Trifecta/Diagnostic/Rendering/Prim.hs view
@@ -0,0 +1,241 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}++-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Rendering.Prim+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- The type for Lines will very likely change over time, to enable drawing+-- lit up multi-character versions of control characters for @^Z@, @^[@,+-- @<0xff>@, etc. This will make for much nicer diagnostics when+-- working with protocols.+--+-----------------------------------------------------------------------------++module Text.Trifecta.Diagnostic.Rendering.Prim+ ( Rendering(..)+ , nullRendering+ , emptyRendering+ , Source(..)+ , rendering+ , Renderable(..)+ , Rendered(..)+ -- * Lower level drawing primitives+ , Lines+ , draw+ , ifNear+ , (.#)+ ) where++import Control.Applicative+import Control.Comonad+import Control.Monad.State+import Data.Array+import Data.ByteString as B hiding (groupBy, empty, any)+import Data.Foldable+import Data.Function (on)+import Data.Int (Int64)+import Data.Functor.Bind+import Data.List (groupBy)+import Data.Semigroup+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Data.Traversable+import Text.Trifecta.IntervalMap+import Prelude as P+import Prelude hiding (span)+import System.Console.Terminfo.Color+import System.Console.Terminfo.PrettyPrint+import Text.PrettyPrint.Free hiding (column)+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Highlight.Class+import Text.Trifecta.Highlight.Effects+import qualified Data.ByteString.UTF8 as UTF8++outOfRangeEffects :: [ScopedEffect] -> [ScopedEffect]+outOfRangeEffects xs = soft Bold : xs++type Lines = Array (Int,Int64) ([ScopedEffect], Char)++(///) :: Ix i => Array i e -> [(i, e)] -> Array i e+a /// xs = a // P.filter (inRange (bounds a) . fst) xs++grow :: Int -> Lines -> Lines+grow y a+ | inRange (t,b) y = a+ | otherwise = array new [ (i, if inRange old i then a ! i else ([],' ')) | i <- range new ]+ where old@((t,lo),(b,hi)) = bounds a+ new = ((min t y,lo),(max b y,hi))++draw :: [ScopedEffect] -> Int -> Int64 -> String -> Lines -> Lines+draw e y n xs a0+ | Prelude.null xs = a0+ | otherwise = gt $ lt (a /// out)+ where+ a = grow y a0+ ((_,lo),(_,hi)) = bounds a+ out = P.zipWith (\i c -> ((y,i),(e,c))) [n..] xs+ lt | Prelude.any (\el -> snd (fst el) < lo) out = (// [((y,lo),(outOfRangeEffects e,'<'))])+ | otherwise = id+ gt | Prelude.any (\el -> snd (fst el) > hi) out = (// [((y,hi),(outOfRangeEffects e,'>'))])+ | otherwise = id++-- | fill the interval from [n .. m) with a given effect+recolor :: ([ScopedEffect] -> [ScopedEffect]) -> Maybe Int64 -> Maybe Int64 -> Lines -> Lines+recolor f n0 m0 a0+ | m <= n = a0+ | otherwise = a /// P.map rc [n .. m - 1]+ where+ ((_,lo),(_,hi)) = bounds a+ n = maybe lo id n0+ m = maybe (hi + 1) id m0+ a = grow 0 a0+ rc i = (yi, (f e, c)) -- only if not isSpace?+ where+ yi = (0, i)+ (e,c) = a ! yi++data Rendering = Rendering+ { renderingDelta :: !Delta -- focus, the render will keep this visible+ , renderingLineLen :: {-# UNPACK #-} !Int64 -- actual line length+ , renderingLineBytes :: {-# UNPACK #-} !Int64 -- line length in bytes+ , renderingLine :: Lines -> Lines+ , renderingOverlays :: Delta -> Lines -> Lines+ }++instance Highlightable Rendering where+ addHighlights intervals (Rendering d ll lb l o) = Rendering d ll lb l' o where+ d' = rewind d+ l' = Prelude.foldr (.) l [ recolor (eff tok) (column lo <$ guard (near d lo)) (column hi <$ guard (near d hi))+ | (Interval lo hi, tok) <- intersections d' (d' <> Columns ll lb) intervals ]+ eff t _ = highlightEffects t++instance Show Rendering where+ showsPrec d (Rendering p ll lb _ _) = showParen (d > 10) $+ showString "Rendering " . showsPrec 11 p . showChar ' ' . showsPrec 11 ll . showChar ' ' . showsPrec 11 lb . showString " ... ..."++nullRendering :: Rendering -> Bool+nullRendering (Rendering (Columns 0 0) 0 0 _ _) = True+nullRendering _ = False++emptyRendering :: Rendering+emptyRendering = rendering (Columns 0 0) ""++instance Semigroup Rendering where+ -- an unprincipled hack+ Rendering (Columns 0 0) 0 0 _ f <> Rendering del len lb doc g = Rendering del len lb doc $ \d l -> f d (g d l)+ Rendering del len lb doc f <> Rendering _ _ _ _ g = Rendering del len lb doc $ \d l -> f d (g d l)++instance Monoid Rendering where+ mappend = (<>)+ mempty = emptyRendering++ifNear :: Delta -> (Lines -> Lines) -> Delta -> Lines -> Lines+ifNear d f d' l | near d d' = f l+ | otherwise = l++instance HasDelta Rendering where+ delta = renderingDelta++class Renderable t where+ render :: t -> Rendering++instance Renderable Rendering where+ render = id++class Source t where+ source :: t -> (Int64, Int64, Lines -> Lines) {- the number of (padded) columns, number of bytes, and the the line -}++instance Source String where+ source s+ | Prelude.elem '\n' s = ( ls, bs, draw [] 0 0 s')+ | otherwise = ( ls + fromIntegral (Prelude.length end), bs, draw [soft (Foreground Blue), soft Bold] 0 ls end . draw [] 0 0 s')+ where+ end = "<EOF>"+ s' = go 0 s+ bs = fromIntegral $ B.length $ UTF8.fromString $ Prelude.takeWhile (/='\n') s+ ls = fromIntegral $ Prelude.length s'+ go n ('\t':xs) = let t = 8 - mod n 8 in P.replicate t ' ' ++ go (n + t) xs+ go _ ('\n':_) = []+ go n (x:xs) = x : go (n + 1) xs+ go _ [] = []+++instance Source ByteString where+ source = source . UTF8.toString++-- | create a drawing surface+rendering :: Source s => Delta -> s -> Rendering+rendering del s = case source s of+ (len, lb, doc) -> Rendering del len lb doc (\_ l -> l)++(.#) :: (Delta -> Lines -> Lines) -> Rendering -> Rendering+f .# Rendering d ll lb s g = Rendering d ll lb s $ \e l -> f e $ g e l++instance Pretty Rendering where+ pretty r = prettyTerm r >>= const empty++instance PrettyTerm Rendering where+ prettyTerm (Rendering d ll _ l f) = nesting $ \k -> columns $ \n -> go (fromIntegral (n - k)) where+ go cols = align (vsep (P.map ln [t..b])) where+ (lo, hi) = window (column d) ll (min (max (cols - 2) 30) 200)+ a = f d $ l $ array ((0,lo),(-1,hi)) []+ ((t,_),(b,_)) = bounds a+ ln y = hcat+ $ P.map (\g -> P.foldr with (pretty (P.map snd g)) (fst (P.head g)))+ $ groupBy ((==) `on` fst)+ [ a ! (y,i) | i <- [lo..hi] ]++window :: Int64 -> Int64 -> Int64 -> (Int64, Int64)+window c l w+ | c <= w2 = (0, min w l)+ | c + w2 >= l = if l > w then (l-w, l) else (0, w)+ | otherwise = (c-w2,c + w2)+ where w2 = div w 2++data Rendered a = a :@ Rendering+ deriving Show++instance Functor Rendered where+ fmap f (a :@ s) = f a :@ s++instance HasDelta (Rendered a) where+ delta = delta . render++instance HasBytes (Rendered a) where+ bytes = bytes . delta++instance Comonad Rendered where+ extend f as@(_ :@ s) = f as :@ s+ extract (a :@ _) = a++instance Apply Rendered where+ (f :@ s) <.> (a :@ t) = f a :@ (s <> t)++instance ComonadApply Rendered where+ (f :@ s) <@> (a :@ t) = f a :@ (s <> t)++instance Bind Rendered where+ (a :@ s) >>- f = case f a of+ b :@ t -> b :@ (s <> t)++instance Foldable Rendered where+ foldMap f (a :@ _) = f a++instance Traversable Rendered where+ traverse f (a :@ s) = (:@ s) <$> f a++instance Foldable1 Rendered where+ foldMap1 f (a :@ _) = f a++instance Traversable1 Rendered where+ traverse1 f (a :@ s) = (:@ s) <$> f a++instance Renderable (Rendered a) where+ render (_ :@ s) = s
+ src/Text/Trifecta/Diagnostic/Rendering/Span.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Diagnostic.Rendering.Span+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Diagnostic.Rendering.Span+ ( Span(..)+ , span+ , Spanned(..)+ , spanned+ -- * Internals+ , spanEffects+ , drawSpan+ , addSpan+ ) where++import Control.Applicative+import Data.Hashable+import Data.Semigroup+import Data.Semigroup.Reducer+import Data.Foldable+import Data.Traversable+import Control.Comonad+import Data.ByteString (ByteString)+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.Trifecta.Util.Combinators+import Text.Trifecta.Parser.Class+import Data.Array+import System.Console.Terminfo.Color+import System.Console.Terminfo.PrettyPrint+import Prelude as P hiding (span)++spanEffects :: [ScopedEffect]+spanEffects = [soft (Foreground Green)]++drawSpan :: Delta -> Delta -> Delta -> Lines -> Lines+drawSpan s e d a+ | nl && nh = go (column l) (rep (max (column h - column l) 0) '~') a+ | nl = go (column l) (rep (max (snd (snd (bounds a)) - column l + 1) 0) '~') a+ | nh = go (-1) (rep (max (column h + 1) 0) '~') a+ | otherwise = a+ where+ go = draw spanEffects 1 . fromIntegral+ l = argmin bytes s e+ h = argmax bytes s e+ nl = near l d+ nh = near h d+ rep = P.replicate . fromIntegral++-- |+-- > int main(int argc, char ** argv) { int; }+-- > ^~~+addSpan :: Delta -> Delta -> Rendering -> Rendering+addSpan s e r = drawSpan s e .# r++data Span = Span !Delta !Delta {-# UNPACK #-} !ByteString deriving (Eq,Ord,Show)++instance Renderable Span where+ render (Span s e bs) = addSpan s e $ rendering s bs++instance Semigroup Span where+ Span s _ b <> Span _ e _ = Span s e b++instance Reducer Span Rendering where+ unit = render++data Spanned a = a :~ Span deriving (Eq,Ord,Show)++instance Functor Spanned where+ fmap f (a :~ s) = f a :~ s++instance Comonad Spanned where+ extend f as@(_ :~ s) = f as :~ s+ extract (a :~ _) = a++instance Foldable Spanned where+ foldMap f (a :~ _) = f a++instance Traversable Spanned where+ traverse f (a :~ s) = (:~ s) <$> f a++instance Reducer (Spanned a) Rendering where+ unit = render++instance Renderable (Spanned a) where+ render (_ :~ s) = render s++instance Hashable Span where+ hash (Span s e bs) = hash s `hashWithSalt` e `hashWithSalt` bs++instance Hashable a => Hashable (Spanned a) where+ hash (a :~ s) = hash a `hashWithSalt` s++span :: MonadParser m => m a -> m Span+span p = (\s l e -> Span s e l) <$> position <*> line <*> (p *> position)++spanned :: MonadParser m => m a -> m (Spanned a)+spanned p = (\s l a e -> a :~ Span s e l) <$> position <*> line <*> p <*> position
+ src/Text/Trifecta/Highlight.hs view
@@ -0,0 +1,22 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Highlight+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Highlight + ( + -- * Text.Trifecta.Highlight.Class+ Highlightable(..)+ -- * Text.Trifecta.Highlight.Prim+ , Highlight+ , Highlights+ ) where++import Text.Trifecta.Highlight.Class+import Text.Trifecta.Highlight.Prim
+ src/Text/Trifecta/Highlight/Class.hs view
@@ -0,0 +1,19 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Highlight.Class+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Highlight.Class + ( Highlightable(..)+ ) where++import Text.Trifecta.Highlight.Prim++class Highlightable a where+ addHighlights :: Highlights -> a -> a
+ src/Text/Trifecta/Highlight/Effects.hs view
@@ -0,0 +1,44 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Highlight.Effects+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Highlight.Effects + ( highlightEffects+ , pushToken+ , popToken+ , withHighlight+ ) where++import Control.Applicative+import System.Console.Terminfo.PrettyPrint+import System.Console.Terminfo.Color+import Data.Semigroup+import Text.Trifecta.Highlight.Prim++highlightEffects :: Highlight -> [ScopedEffect]+highlightEffects Comment = [soft $ Foreground Blue]+highlightEffects ReservedIdentifier = [soft $ Foreground Magenta, soft Bold]+highlightEffects ReservedConstructor = [soft $ Foreground Magenta, soft Bold]+highlightEffects EscapeCode = [soft $ Foreground Magenta, soft Bold]+highlightEffects Operator = [soft $ Foreground Yellow]+highlightEffects CharLiteral = [soft $ Foreground Cyan]+highlightEffects StringLiteral = [soft $ Foreground Cyan]+highlightEffects Constructor = [soft Bold]+highlightEffects ReservedOperator = [soft $ Foreground Yellow]+highlightEffects ConstructorOperator = [soft $ Foreground Yellow, soft Bold]+highlightEffects ReservedConstructorOperator = [soft $ Foreground Yellow, soft Bold]+highlightEffects _ = []++pushToken, popToken :: Highlight -> TermDoc+pushToken h = foldr (\a b -> pure (Push a) <> b) mempty (highlightEffects h)+popToken h = foldr (\_ b -> pure Pop <> b) mempty (highlightEffects h)++withHighlight :: Highlight -> TermDoc -> TermDoc+withHighlight h d = pushToken h <> d <> popToken h
+ src/Text/Trifecta/Highlight/Prim.hs view
@@ -0,0 +1,47 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Highlight.Prim+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Highlight.Prim+ ( Highlight(..)+ , Highlights+ ) where++import Data.Ix+import Text.Trifecta.IntervalMap+import Text.Trifecta.Rope.Delta++data Highlight+ = EscapeCode+ | Number + | Comment+ | CharLiteral+ | StringLiteral+ | Constant+ | Statement+ | Special+ | Symbol+ | Identifier+ | ReservedIdentifier+ | Operator+ | ReservedOperator+ | Constructor+ | ReservedConstructor+ | ConstructorOperator+ | ReservedConstructorOperator+ | BadInput+ | Unbound+ | Layout+ | MatchedSymbols+ | LiterateComment+ | LiterateSyntax+ deriving (Eq,Ord,Show,Read,Enum,Ix,Bounded)++type Highlights = IntervalMap Delta Highlight
+ src/Text/Trifecta/Highlight/Rendering/HTML.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Highlight.Rendering.HTML+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Highlight.Rendering.HTML + ( Doc(..)+ , doc+ ) where++import Data.Monoid+import Prelude hiding (head)+import Text.Blaze+import Text.Blaze.Html5 hiding (b,i)+import Text.Blaze.Html5.Attributes hiding (title)+import Text.Trifecta.Highlight.Class+import Text.Trifecta.Rope.Highlighted++-- | Represents a source file like an HsColour rendered document+data Doc = Doc + { docTitle :: String+ , docCss :: String -- href for the css file+ , docContent :: HighlightedRope+ }++-- | +--+-- > renderHtml $ toHtml $ addHighlights highlightedRope $ doc "Foo.hs"+doc :: String -> Doc+doc t = Doc t "trifecta.css" mempty++instance ToHtml Doc where+ toHtml (Doc t css cs) = docTypeHtml $ do+ head $ do+ preEscapedString "<!-- Generated by trifecta, http://github.com/ekmett/trifecta/ -->\n"+ title $ toHtml t+ link ! rel "stylesheet" ! type_ "text/css" ! href (toValue css)+ body $ toHtml cs++instance Highlightable Doc where + addHighlights h (Doc t c r) = Doc t c (addHighlights h r)
+ src/Text/Trifecta/IntervalMap.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.IntervalMap+-- Copyright : (c) Edward Kmett 2011+-- (c) Ross Paterson 2008+-- License : BSD-style+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable (MPTCs, type families, functional dependencies)+--+-- Interval maps implemented using the 'FingerTree' type, following+-- section 4.8 of+--+-- * Ralf Hinze and Ross Paterson,+-- \"Finger trees: a simple general-purpose data structure\",+-- /Journal of Functional Programming/ 16:2 (2006) pp 197-217.+-- <http://www.soi.city.ac.uk/~ross/papers/FingerTree.html>+--+-- An amortized running time is given for each operation, with /n/+-- referring to the size of the priority queue. These bounds hold even+-- in a persistent (shared) setting.+--+-- /Note/: Many of these operations have the same names as similar+-- operations on lists in the "Prelude". The ambiguity may be resolved+-- using either qualification or the @hiding@ clause.+--+-- Unlike "Data.IntervalMap.FingerTree", this version sorts things so+-- that the largest interval from a given point comes first. This way+-- if you have nested intervals, you get the outermost interval before +-- the contained intervals.+-----------------------------------------------------------------------------++module Text.Trifecta.IntervalMap + (+ -- * Intervals+ Interval(..)+ -- * Interval maps+ , IntervalMap(..), singleton, insert+ -- * Searching+ , search, intersections, dominators+ -- * Prepending an offset onto every interval in the map+ , offset+ -- * The result monoid+ , IntInterval(..)+ , fromList+ ) where++import Control.Applicative hiding (empty)+import qualified Data.FingerTree as FT+import Data.FingerTree (FingerTree, Measured(..), ViewL(..), (<|), (><))+import Data.Functor.Plus++import Data.Traversable (Traversable(traverse))+import Data.Foldable (Foldable(foldMap))+import Data.Bifunctor+import Data.Semigroup+import Data.Semigroup.Reducer+import Data.Semigroup.Union+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Data.Key+import Data.Pointed++----------------------------------+-- 4.8 Application: interval trees+----------------------------------++-- | A closed interval. The lower bound should be less than or equal+-- to the higher bound.+data Interval v = Interval { low :: v, high :: v }+ deriving Show++instance Ord v => Semigroup (Interval v) where+ Interval a b <> Interval c d = Interval (min a c) (max b d)++-- assumes the monoid and ordering are compatible.+instance (Ord v, Monoid v) => Reducer v (Interval v) where + unit v = Interval v v+ cons v (Interval a b) = Interval (v `mappend` a) (v `mappend` b)+ snoc (Interval a b) v = Interval (a `mappend` v) (b `mappend` v)++instance Eq v => Eq (Interval v) where+ Interval a b == Interval c d = a == c && d == b++instance Ord v => Ord (Interval v) where+ compare (Interval a b) (Interval c d) = case compare a c of+ LT -> LT+ EQ -> compare d b -- reversed to put larger intervals first+ GT -> GT++instance Functor Interval where+ fmap f (Interval a b) = Interval (f a) (f b)++instance Foldable Interval where+ foldMap f (Interval a b) = f a `mappend` f b++instance Traversable Interval where+ traverse f (Interval a b) = Interval <$> f a <*> f b++instance Foldable1 Interval where+ foldMap1 f (Interval a b) = f a <> f b++instance Traversable1 Interval where+ traverse1 f (Interval a b) = Interval <$> f a <.> f b++instance Pointed Interval where+ point v = Interval v v ++data Node v a = Node (Interval v) a++type instance Key (Node v) = Interval v++instance Functor (Node v) where+ fmap f (Node i x) = Node i (f x)++instance Bifunctor Node where+ bimap f g (Node v a) = Node (fmap f v) (g a)++instance Keyed (Node v) where+ mapWithKey f (Node i x) = Node i (f i x)++instance Foldable (Node v) where+ foldMap f (Node _ x) = f x++instance FoldableWithKey (Node v) where+ foldMapWithKey f (Node k v) = f k v++instance Traversable (Node v) where+ traverse f (Node i x) = Node i <$> f x++instance TraversableWithKey (Node v) where+ traverseWithKey f (Node i x) = Node i <$> f i x++instance Foldable1 (Node v) where+ foldMap1 f (Node _ x) = f x++instance FoldableWithKey1 (Node v) where+ foldMapWithKey1 f (Node k v) = f k v++instance Traversable1 (Node v) where+ traverse1 f (Node i x) = Node i <$> f x++instance TraversableWithKey1 (Node v) where+ traverseWithKey1 f (Node i x) = Node i <$> f i x++-- rightmost interval (including largest lower bound) and largest upper bound.+data IntInterval v = NoInterval | IntInterval (Interval v) v++instance Ord v => Monoid (IntInterval v) where+ mempty = NoInterval+ NoInterval `mappend` i = i+ i `mappend` NoInterval = i+ IntInterval _ hi1 `mappend` IntInterval int2 hi2 =+ IntInterval int2 (max hi1 hi2)++instance Ord v => Measured (IntInterval v) (Node v a) where+ measure (Node i _) = IntInterval i (high i)++-- | Map of closed intervals, possibly with duplicates.+-- The 'Foldable' and 'Traversable' instances process the intervals in+-- lexicographical order.+newtype IntervalMap v a = IntervalMap { runIntervalMap :: FingerTree (IntInterval v) (Node v a) } +-- ordered lexicographically by interval++type instance Key (IntervalMap v) = Interval v++instance Functor (IntervalMap v) where+ fmap f (IntervalMap t) = IntervalMap (FT.unsafeFmap (fmap f) t)++instance Keyed (IntervalMap v) where+ mapWithKey f (IntervalMap t) = IntervalMap (FT.unsafeFmap (mapWithKey f) t)++instance Foldable (IntervalMap v) where+ foldMap f (IntervalMap t) = foldMap (foldMap f) t++instance FoldableWithKey (IntervalMap v) where+ foldMapWithKey f (IntervalMap t) = foldMap (foldMapWithKey f) t ++instance Traversable (IntervalMap v) where+ traverse f (IntervalMap t) =+ IntervalMap <$> FT.unsafeTraverse (traverse f) t++instance TraversableWithKey (IntervalMap v) where+ traverseWithKey f (IntervalMap t) = + IntervalMap <$> FT.unsafeTraverse (traverseWithKey f) t++instance Ord v => Measured (IntInterval v) (IntervalMap v a) where+ measure (IntervalMap m) = measure m++largerError :: a+largerError = error "Text.Trifecta.IntervalMap.larger: the impossible happened"++-- | /O(m log (n/\//m))/. Merge two interval maps.+-- The map may contain duplicate intervals; entries with equal intervals+-- are kept in the original order.+instance Ord v => HasUnion (IntervalMap v a) where+ union (IntervalMap xs) (IntervalMap ys) = IntervalMap (merge1 xs ys) where + merge1 as bs = case FT.viewl as of+ EmptyL -> bs+ a@(Node i _) :< as' -> l >< a <| merge2 as' r+ where + (l, r) = FT.split larger bs+ larger (IntInterval k _) = k >= i+ larger _ = largerError+ merge2 as bs = case FT.viewl bs of+ EmptyL -> as+ b@(Node i _) :< bs' -> l >< b <| merge1 r bs'+ where + (l, r) = FT.split larger as+ larger (IntInterval k _) = k >= i+ larger _ = largerError++instance Ord v => HasUnion0 (IntervalMap v a) where+ empty = IntervalMap FT.empty++instance Ord v => Monoid (IntervalMap v a) where+ mempty = empty+ mappend = union++instance Ord v => Alt (IntervalMap v) where+ (<!>) = union++instance Ord v => Plus (IntervalMap v) where+ zero = empty++-- | /O(n)/. Add a delta to each interval in the map+offset :: (Ord v, Monoid v) => v -> IntervalMap v a -> IntervalMap v a +offset v (IntervalMap m) = IntervalMap $ FT.fmap' (first (mappend v)) m++-- | /O(1)/. Interval map with a single entry.+singleton :: Ord v => Interval v -> a -> IntervalMap v a+singleton i x = IntervalMap (FT.singleton (Node i x))++-- | /O(log n)/. Insert an interval into a map.+-- The map may contain duplicate intervals; the new entry will be inserted+-- before any existing entries for the same interval.+insert :: Ord v => v -> v -> a -> IntervalMap v a -> IntervalMap v a+insert lo hi _ m | lo > hi = m+insert lo hi x (IntervalMap t) = IntervalMap (l >< Node i x <| r) where + i = Interval lo hi+ (l, r) = FT.split larger t+ larger (IntInterval k _) = k >= i+ larger _ = largerError++-- | /O(k log (n/\//k))/. All intervals that contain the given interval,+-- in lexicographical order.+dominators :: Ord v => v -> v -> IntervalMap v a -> [(Interval v, a)]+dominators i j = intersections j i ++-- | /O(k log (n/\//k))/. All intervals that contain the given point,+-- in lexicographical order.+search :: Ord v => v -> IntervalMap v a -> [(Interval v, a)]+search p = intersections p p++-- | /O(k log (n/\//k))/. All intervals that intersect with the given+-- interval, in lexicographical order.+intersections :: Ord v => v -> v -> IntervalMap v a -> [(Interval v, a)]+intersections lo hi (IntervalMap t) = matches (FT.takeUntil (greater hi) t) where + matches xs = case FT.viewl (FT.dropUntil (atleast lo) xs) of+ EmptyL -> []+ Node i x :< xs' -> (i, x) : matches xs'++atleast :: Ord v => v -> IntInterval v -> Bool+atleast k (IntInterval _ hi) = k <= hi+atleast _ _ = False++greater :: Ord v => v -> IntInterval v -> Bool+greater k (IntInterval i _) = low i > k+greater _ _ = False++fromList :: Ord v => [(v, v, a)] -> IntervalMap v a+fromList = foldr ins empty where + ins (lo, hi, n) = insert lo hi n+
+ src/Text/Trifecta/Language.hs view
@@ -0,0 +1,34 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Language+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Language+ ( Language(..)+ , runLanguage+ , LanguageDef(..)+ , MonadLanguage(..)+ , asksLanguage+ , identifier+ , reserved+ , reservedByteString+ , op+ , reservedOp+ , reservedOpByteString+ , emptyLanguageDef+ , haskellLanguageDef+ , haskell98LanguageDef+ ) where++import Text.Trifecta.Language.Class+import Text.Trifecta.Language.Combinators+import Text.Trifecta.Language.Prim+import Text.Trifecta.Language.Monad+import Text.Trifecta.Language.Style+
+ src/Text/Trifecta/Language/Class.hs view
@@ -0,0 +1,59 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Language.Class+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Language.Class+ ( MonadLanguage(..)+ , asksLanguage+ ) where++import Control.Monad (liftM)+import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import qualified Control.Monad.Trans.Writer.Strict as Strict+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.RWS.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.RWS.Lazy as Lazy+import Data.Monoid+import Text.Trifecta.Language.Prim+import Text.Trifecta.Parser.Class++class MonadParser m => MonadLanguage m where+ askLanguage :: m (LanguageDef m)++asksLanguage :: MonadLanguage m => (LanguageDef m -> r) -> m r+asksLanguage f = liftM f askLanguage++instance MonadLanguage m => MonadLanguage (Strict.StateT s m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance MonadLanguage m => MonadLanguage (Lazy.StateT s m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance (Monoid w, MonadLanguage m) => MonadLanguage (Strict.WriterT w m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance (Monoid w, MonadLanguage m) => MonadLanguage (Lazy.WriterT w m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance MonadLanguage m => MonadLanguage (ReaderT s m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance MonadLanguage m => MonadLanguage (IdentityT m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance (Monoid w, MonadLanguage m) => MonadLanguage (Strict.RWST r w s m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance (Monoid w, MonadLanguage m) => MonadLanguage (Lazy.RWST r w s m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage
+ src/Text/Trifecta/Language/Combinators.hs view
@@ -0,0 +1,42 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Language.Combinators+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Language.Combinators+ ( identifier+ , reserved+ , reservedByteString+ , op+ , reservedOp+ , reservedOpByteString+ ) where++import Data.ByteString+import Text.Trifecta.Language.Class+import Text.Trifecta.Language.Prim+import Text.Trifecta.Parser.Identifier++identifier :: MonadLanguage m => m ByteString+identifier = asksLanguage languageIdentifierStyle >>= ident++reserved :: MonadLanguage m => String -> m ()+reserved i = asksLanguage languageIdentifierStyle >>= \style -> reserve style i++reservedByteString :: MonadLanguage m => ByteString -> m ()+reservedByteString i = asksLanguage languageIdentifierStyle >>= \style -> reserveByteString style i++op :: MonadLanguage m => m ByteString+op = asksLanguage languageOperatorStyle >>= ident++reservedOp :: MonadLanguage m => String -> m ()+reservedOp i = asksLanguage languageOperatorStyle >>= \style -> reserve style i++reservedOpByteString :: MonadLanguage m => ByteString -> m ()+reservedOpByteString i = asksLanguage languageOperatorStyle >>= \style -> reserveByteString style i
+ src/Text/Trifecta/Language/Monad.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GeneralizedNewtypeDeriving #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Language.Monad+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Language.Monad+ ( Language(..)+ , runLanguage+ ) where++import Control.Applicative+import Control.Monad ()+import Control.Monad.Trans.Class+import Control.Monad.Reader+import Control.Monad.Writer.Class+import Control.Monad.State.Class+import Control.Monad.Cont.Class+import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Mark+import Text.Trifecta.Parser.Token.Style+import Text.Trifecta.Language.Prim+import Text.Trifecta.Language.Class++newtype Language m a = Language { unlanguage :: ReaderT (LanguageDef (Language m)) m a }+ deriving (Functor,Applicative,Alternative,Monad,MonadPlus,MonadCont)++runLanguage :: Language m a -> LanguageDef (Language m) -> m a+runLanguage = runReaderT . unlanguage++instance MonadParser m => MonadLanguage (Language m) where+ askLanguage = Language ask++instance MonadTrans Language where+ lift = Language . lift++instance MonadParser m => MonadParser (Language m) where+ highlightInterval h s e = lift $ highlightInterval h s e+ someSpace = asksLanguage languageCommentStyle >>= buildSomeSpaceParser (lift someSpace)+ nesting (Language (ReaderT m)) = Language $ ReaderT $ nesting . m+ semi = lift semi+ try (Language m) = Language $ try m+ labels (Language m) ss = Language $ labels m ss+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ skipping = lift . skipping+ unexpected = lift . unexpected+ position = lift position+ line = lift line+ lookAhead (Language m) = Language (lookAhead m)+ slicedWith f (Language m) = Language $ ReaderT $ slicedWith f . runReaderT m++instance MonadMark d m => MonadMark d (Language m) where+ mark = lift mark+ release = lift . release++instance MonadDiagnostic e m => MonadDiagnostic e (Language m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance MonadState s m => MonadState s (Language m) where+ get = Language $ lift get+ put s = Language $ lift $ put s++instance MonadWriter w m => MonadWriter w (Language m) where+ tell = Language . lift . tell+ pass = Language . pass . unlanguage+ listen = Language . listen . unlanguage++instance MonadReader e m => MonadReader e (Language m) where+ ask = Language $ lift ask+ local f (Language m) = Language $ ReaderT $ \e -> local f (runReaderT m e)
+ src/Text/Trifecta/Language/Prim.hs view
@@ -0,0 +1,28 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Language.Prim+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Language.Prim+ ( LanguageDef(..)+ , liftLanguageDef+ ) where++import Control.Monad.Trans.Class+import Text.Trifecta.Parser.Token.Style+import Text.Trifecta.Parser.Identifier++data LanguageDef m = LanguageDef+ { languageCommentStyle :: CommentStyle+ , languageIdentifierStyle :: IdentifierStyle m+ , languageOperatorStyle :: IdentifierStyle m+ }++liftLanguageDef :: (MonadTrans t, Monad m) => LanguageDef m -> LanguageDef (t m)+liftLanguageDef (LanguageDef c i o) = LanguageDef c (liftIdentifierStyle i) (liftIdentifierStyle o)
+ src/Text/Trifecta/Language/Style.hs view
@@ -0,0 +1,26 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Language.Style+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+-- +-----------------------------------------------------------------------------+module Text.Trifecta.Language.Style+ ( emptyLanguageDef+ , haskellLanguageDef+ , haskell98LanguageDef+ ) where++import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Token.Style+import Text.Trifecta.Parser.Identifier.Style+import Text.Trifecta.Language.Prim++emptyLanguageDef, haskellLanguageDef, haskell98LanguageDef :: MonadParser m => LanguageDef m+emptyLanguageDef = LanguageDef emptyCommentStyle emptyIdents emptyOps+haskellLanguageDef = LanguageDef haskellCommentStyle haskellIdents haskellOps+haskell98LanguageDef = LanguageDef haskellCommentStyle haskell98Idents haskell98Ops
+ src/Text/Trifecta/Layout.hs view
@@ -0,0 +1,23 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Layout+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Layout+ ( Layout(..)+ , LayoutMark(..)+ , MonadLayout(..)+ , LayoutState(..)+ , runLayout+ , defaultLayoutState+ ) where++import Text.Trifecta.Layout.Monad+import Text.Trifecta.Layout.Class+import Text.Trifecta.Layout.Prim
+ src/Text/Trifecta/Layout/Class.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Layout.Class+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Layout.Class+ ( MonadLayout(..)+ ) where++import Data.Monoid+import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict+import qualified Control.Monad.Trans.RWS.Lazy as Lazy+import qualified Control.Monad.Trans.RWS.Strict as Strict+import Text.Trifecta.Layout.Prim+import Text.Trifecta.Parser.Class++class MonadParser m => MonadLayout m where+ layout :: m LayoutToken+ layoutState :: (LayoutState -> (a, LayoutState)) -> m a++instance MonadLayout m => MonadLayout (Strict.StateT s m) where+ layout = lift layout+ layoutState = lift . layoutState++instance MonadLayout m => MonadLayout (Lazy.StateT s m) where+ layout = lift layout+ layoutState = lift . layoutState++instance MonadLayout m => MonadLayout (ReaderT e m) where+ layout = lift layout+ layoutState = lift . layoutState++instance (Monoid w, MonadLayout m) => MonadLayout (Strict.WriterT w m) where+ layout = lift layout+ layoutState = lift . layoutState++instance (Monoid w, MonadLayout m) => MonadLayout (Lazy.WriterT w m) where+ layout = lift layout+ layoutState = lift . layoutState++instance (Monoid w, MonadLayout m) => MonadLayout (Strict.RWST r w s m) where+ layout = lift layout+ layoutState = lift . layoutState++instance (Monoid w, MonadLayout m) => MonadLayout (Lazy.RWST r w s m) where+ layout = lift layout+ layoutState = lift . layoutState++instance MonadLayout m => MonadLayout (IdentityT m) where+ layout = lift layout+ layoutState = lift . layoutState
+ src/Text/Trifecta/Layout/Combinators.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Layout.Combinators+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Layout.Combinators+ ( layoutEq+ , getLayout+ , setLayout+ , modLayout+ , disableLayout+ , enableLayout+ , laidout+ ) where++import Control.Applicative+import Control.Monad (guard)+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Token.Combinators+import qualified Text.Trifecta.Highlight.Prim as Highlight+import Text.Trifecta.Layout.Class+import Text.Trifecta.Layout.Prim+import Data.Functor.Identity++-- getLayout :: MonadLayout m => Lens LayoutState t -> m t+getLayout :: MonadLayout m => ((t -> Const t t') -> LayoutState -> Const t LayoutState) -> m t+getLayout l = layoutState $ \s -> (getConst (l Const s), s)++setLayout :: MonadLayout m => ((t -> Identity t) -> LayoutState -> Identity LayoutState) -> t -> m ()+setLayout l t = modLayout l (const t)++modLayout :: MonadLayout m => ((t -> Identity t) -> LayoutState -> Identity LayoutState) -> (t -> t) -> m ()+modLayout l f = layoutState $ \s -> ((), runIdentity $ l (Identity . f) s)++disableLayout :: MonadLayout m => m a -> m a+disableLayout p = do+ r <- rend+ modLayout layoutStack (DisabledLayout r:)+ result <- p+ stk <- getLayout layoutStack+ case stk of+ DisabledLayout r':xs | delta r == delta r' -> result <$ setLayout layoutStack xs+ _ -> unexpected "layout"++enableLayout :: MonadLayout m => m a -> m a+enableLayout p = do+ result <- highlight Highlight.Layout $ do+ r <- rend+ modLayout layoutStack (IndentedLayout r:)+ p+ result <$ layout <?> "virtual right brace"++laidout :: MonadLayout m => m a -> m a+laidout p = braces p <|> enableLayout p++layoutEq :: MonadLayout m => LayoutToken -> m ()+layoutEq s = try $ do+ r <- layout+ guard (s == r)+
+ src/Text/Trifecta/Layout/Monad.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE MultiParamTypeClasses, GeneralizedNewtypeDeriving, FlexibleInstances, UndecidableInstances #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Layout.Monad+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Layout.Monad+ ( Layout(..)+ , runLayout+ ) where++import Control.Applicative+import Control.Category+import Control.Monad+import Control.Monad.State.Class+import Control.Monad.Trans.State.Strict (StateT(..))+import Control.Monad.Writer.Class+import Control.Monad.Reader.Class+import Control.Monad.Cont.Class+import Control.Monad.Trans.Class+import Prelude hiding ((.), id)+import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Mark+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Layout.Prim+import Text.Trifecta.Layout.Class+import Text.Trifecta.Layout.Combinators+import Text.Trifecta.Rope.Delta++-- | Adds Haskell-style "layout" to base parser+newtype Layout m a = Layout { unlayout :: StateT LayoutState m a }+ deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadTrans, MonadCont)++runLayout :: Monad m => Layout m a -> LayoutState -> m (a, LayoutState)+runLayout = runStateT . unlayout++instance MonadParser m => MonadParser (Layout m) where+ satisfy p = try $ layoutEq Other *> lift (satisfy p)+ satisfy8 p = try $ layoutEq Other *> lift (satisfy8 p)+ line = lift line+ unexpected = lift . unexpected+ try = Layout . try . unlayout+ labels m s = Layout $ labels (unlayout m) s+ skipMany = Layout . skipMany . unlayout+ highlightInterval h s e = lift $ highlightInterval h s e+ someSpace = try $ (layoutEq WhiteSpace <?> "")+ nesting (Layout m) = disableLayout $ Layout (nesting m)+ semi = getLayout layoutStack >>= \ stk -> case stk of+ (DisabledLayout _:_) -> lift semi+ _ -> try (';' <$ layoutEq VirtualSemi <?> "virtual semi-colon")+ <|> lift semi+ skipping = lift . skipping+ position = lift position+ slicedWith f (Layout m) = Layout $ slicedWith f m+ lookAhead (Layout m) = Layout $ lookAhead m++instance MonadMark d m => MonadMark (LayoutMark d) (Layout m) where+ mark = LayoutMark <$> getLayout id <*> lift mark+ release (LayoutMark s m) = lift (release m) *> setLayout id s++instance MonadDiagnostic e m => MonadDiagnostic e (Layout m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance MonadParser m => MonadLayout (Layout m) where+ layout = buildLayoutParser (lift whiteSpace)+ layoutState f = Layout . StateT $ return . f++buildLayoutParser :: MonadLayout m => m () -> m LayoutToken+buildLayoutParser realWhiteSpace = do+ bol <- getLayout layoutBol+ m <- position+ realWhiteSpace+ r <- position+ if near m r && not bol+ then onside m r+ else getLayout layoutStack >>= \stk -> case compare (column r) (depth stk) of+ GT -> onside m r+ EQ -> return VirtualSemi+ LT -> case stk of+ (IndentedLayout _:xs) -> VirtualRightBrace <$ setLayout layoutStack xs <* setLayout layoutBol True+ _ -> unexpected "layout context"+ where+ onside m r+ | r /= m = pure WhiteSpace+ | otherwise = setLayout layoutBol False *> option Other (VirtualRightBrace <$ eof <* trailing)+ trailing = getLayout layoutStack >>= \ stk -> case stk of+ (IndentedLayout _:xs) -> setLayout layoutStack xs+ _ -> empty+ depth [] = 0+ depth (IndentedLayout r:_) = column r+ depth (DisabledLayout _:_) = -1++instance MonadState s m => MonadState s (Layout m) where+ get = Layout $ lift get+ put = Layout . lift . put++instance MonadReader e m => MonadReader e (Layout m) where+ ask = Layout $ lift ask+ local f (Layout m) = Layout $ local f m++instance MonadWriter w m => MonadWriter w (Layout m) where+ tell = Layout . lift . tell+ listen (Layout m) = Layout $ listen m+ pass (Layout m) = Layout $ pass m
+ src/Text/Trifecta/Layout/Prim.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Layout.Prim+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Layout.Prim+ ( LayoutToken(..)+ , LayoutState(..)+ , LayoutContext(..)+ , LayoutMark(..)+ , defaultLayoutState+ , layoutBol+ , layoutStack+ ) where++import Data.Functor+import Data.Foldable+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Data.Traversable+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Diagnostic.Rendering.Prim++data LayoutToken+ = VirtualSemi+ | VirtualRightBrace+ | WhiteSpace+ | Other+ deriving (Eq,Ord,Show,Read)++data LayoutContext+ = IndentedLayout Rendering+ | DisabledLayout Rendering++instance HasDelta LayoutContext where+ delta (IndentedLayout r) = delta r+ delta (DisabledLayout r) = delta r++instance HasBytes LayoutContext where+ bytes = bytes . delta++data LayoutState = LayoutState+ { _layoutBol :: Bool+ , _layoutStack :: [LayoutContext]+ }++defaultLayoutState :: LayoutState+defaultLayoutState = LayoutState False []++layoutBol :: Functor f => (Bool -> f Bool) -> LayoutState -> f LayoutState+layoutBol f (LayoutState b s) = (`LayoutState` s) <$> f b+{-# INLINE layoutBol #-}++layoutStack :: Functor f => ([LayoutContext] -> f [LayoutContext]) -> LayoutState -> f LayoutState+layoutStack f (LayoutState b s) = LayoutState b <$> f s+{-# INLINE layoutStack #-}++data LayoutMark d = LayoutMark LayoutState d++instance Functor LayoutMark where+ fmap f (LayoutMark s a) = LayoutMark s (f a)++instance Foldable LayoutMark where+ foldMap f (LayoutMark _ a) = f a++instance Traversable LayoutMark where+ traverse f (LayoutMark s a) = LayoutMark s <$> f a++instance Foldable1 LayoutMark where+ foldMap1 f (LayoutMark _ a) = f a++instance Traversable1 LayoutMark where+ traverse1 f (LayoutMark s a) = LayoutMark s <$> f a++instance HasDelta d => HasDelta (LayoutMark d) where+ delta (LayoutMark _ d) = delta d++instance HasBytes d => HasBytes (LayoutMark d) where+ bytes (LayoutMark _ d) = bytes d
+ src/Text/Trifecta/Literate.hs view
@@ -0,0 +1,23 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Literate+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Literate+ ( Literate(..)+ , LiterateMark(..)+ , MonadLiterate(..)+ , LiterateState(..)+ , runLiterate+ , defaultLiterateState+ ) where++import Text.Trifecta.Literate.Monad+import Text.Trifecta.Literate.Class+import Text.Trifecta.Literate.Prim
+ src/Text/Trifecta/Literate/Class.hs view
@@ -0,0 +1,54 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Literate.Class+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Literate.Class+ ( MonadLiterate(..)+ ) where++import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.RWS.Strict as Strict+import qualified Control.Monad.Trans.RWS.Lazy as Lazy+import Data.Monoid+import Text.Trifecta.Parser.Class+import Text.Trifecta.Literate.Prim++class MonadParser m => MonadLiterate m where+ literateState :: (LiterateState -> (a, LiterateState)) -> m a++instance MonadLiterate m => MonadLiterate (Strict.StateT s m) where+ literateState = lift . literateState++instance MonadLiterate m => MonadLiterate (Lazy.StateT s m) where+ literateState = lift . literateState++instance (Monoid w, MonadLiterate m) => MonadLiterate (Strict.WriterT w m) where+ literateState = lift . literateState++instance (Monoid w, MonadLiterate m) => MonadLiterate (Lazy.WriterT w m) where+ literateState = lift . literateState++instance (Monoid w, MonadLiterate m) => MonadLiterate (Strict.RWST r w s m) where+ literateState = lift . literateState++instance (Monoid w, MonadLiterate m) => MonadLiterate (Lazy.RWST r w s m) where+ literateState = lift . literateState++instance MonadLiterate m => MonadLiterate (IdentityT m) where+ literateState = lift . literateState++instance MonadLiterate m => MonadLiterate (ReaderT e m) where+ literateState = lift . literateState
+ src/Text/Trifecta/Literate/Combinators.hs view
@@ -0,0 +1,85 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Literate.Combinators+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Literate.Combinators+ ( someLiterateSpace+ , getLiterate+ , putLiterate+ ) where++import Data.Char (isSpace)+import Control.Applicative+import Control.Monad+import Text.Trifecta.Rope.Delta+import qualified Text.Trifecta.Highlight.Prim as Highlight+import Text.Trifecta.Literate.Prim+import Text.Trifecta.Literate.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Combinators++getLiterate :: MonadLiterate m => m LiterateState+getLiterate = literateState $ \s -> (s, s)++putLiterate :: MonadLiterate m => LiterateState -> m ()+putLiterate s = literateState $ \_ -> ((), s)++skipLine :: MonadParser m => m ()+skipLine = do+ r <- restOfLine+ skipping (delta r)++someLiterateSpace :: MonadLiterate m => m ()+someLiterateSpace = do+ s <- getLiterate+ case s of+ IlliterateStart -> skipSome $ satisfy isSpace+ LiterateStart -> position >>= \m -> track m <|> begin m <|> blank m <|> other m+ LiterateCode -> do+ skipSome $ satisfy isSpace+ option () $ position >>= \m -> when (column m == 0) $ do+ highlight Highlight.LiterateSyntax (string "\\end{code}") *> skipLine+ begin m <|> blank m <|> other m+ LiterateTrack -> skipSome horizontalSpace >> skipOptional bird+ <|> bird+ where+ bird = newline *> position >>= \m -> track m <|> blank m++-- parse space excluding newlines+horizontalSpace :: MonadLiterate m => m Char+horizontalSpace = satisfy $ \s -> s /= '\n' && isSpace s++track, begin, blank, other :: MonadLiterate m => Delta -> m ()+track s = do+ e <- position+ try $ highlight Highlight.LiterateSyntax (char '>')+ *> highlightInterval Highlight.LiterateComment s e+ *> skipSome horizontalSpace+ tracks <|> putLiterate LiterateTrack where+ tracks = do+ s' <- newline *> position+ track s' <|> blank s'++begin s = do+ try $ highlight Highlight.LiterateSyntax (string "\begin{code}") *> skipLine+ position >>= highlightInterval Highlight.LiterateComment s+ putLiterate LiterateCode+ whiteSpace++other s = do+ notChar '>' *> skipLine+ begin s <|> blank s <|> other s++blank s = do+ k <- try $ do+ skipMany horizontalSpace+ True <$ newline <|> False <$ eof+ when k $ track s <|> begin s <|> blank s <|> other s
+ src/Text/Trifecta/Literate/Monad.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, GeneralizedNewtypeDeriving #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Literate.Monad+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Literate.Monad+ ( Literate(..)+ , runLiterate+ ) where++import Control.Applicative+import Control.Monad+import Control.Monad.Trans.State.Strict (StateT(..))+import Control.Monad.Trans.Class+import Control.Monad.State.Class+import Control.Monad.Cont.Class+import Control.Monad.Reader.Class+import Control.Monad.Writer.Class+import Data.Semigroup+import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Language.Prim+import Text.Trifecta.Language.Class+import Text.Trifecta.Literate.Prim+import Text.Trifecta.Literate.Class+import Text.Trifecta.Literate.Combinators+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Parser.Mark+import Text.Trifecta.Rope.Delta++newtype Literate m a = Literate { unliterate :: StateT LiterateState m a }+ deriving (Functor,Applicative,Alternative,Monad,MonadPlus,MonadTrans,MonadCont)++runLiterate :: Monad m => Literate m a -> LiterateState -> m (a, LiterateState)+runLiterate = runStateT . unliterate++instance MonadParser m => MonadParser (Literate m) where+ someSpace = someLiterateSpace+ highlightInterval h s e = lift $ highlightInterval h s e+ try (Literate m) = Literate $ try m+ nesting (Literate m) = Literate $ nesting m+ skipMany (Literate m) = Literate $ skipMany m+ slicedWith f (Literate m) = Literate $ slicedWith f m+ labels (Literate m) p = Literate $ labels m p+ semi = lift semi+ line = lift line+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ unexpected = lift . unexpected+ position = lift position+ skipping d+ | near (Columns 0 0) d = lift $ skipping d -- we don't change literate states within a line+ | otherwise = do+ s <- position+ let e = s <> d+ () <$ (manyTill (someSpace <|> () <$ anyChar) $ position >>= \p -> guard (e <= p))+ lookAhead (Literate (StateT p)) = Literate $ StateT $ \s -> do+ as' <- lookAhead $ p s+ return (fst as', s)++instance MonadParser m => MonadLiterate (Literate m) where+ literateState f = Literate $ StateT $ return . f++instance MonadMark d m => MonadMark (LiterateMark d) (Literate m) where+ mark = LiterateMark <$> getLiterate <*> lift mark+ release (LiterateMark s d) = lift (release d) *> putLiterate s++instance MonadLanguage m => MonadLanguage (Literate m) where+ askLanguage = liftM liftLanguageDef $ lift askLanguage++instance MonadDiagnostic e m => MonadDiagnostic e (Literate m) where+ throwDiagnostic = lift . throwDiagnostic+ logDiagnostic = lift . logDiagnostic++instance MonadState s m => MonadState s (Literate m) where+ get = lift get+ put = lift . put++instance MonadReader e m => MonadReader e (Literate m) where+ ask = lift ask+ local f (Literate m) = Literate $ local f m++instance MonadWriter w m => MonadWriter w (Literate m) where+ tell = lift . tell+ listen (Literate m) = Literate $ listen m+ pass (Literate m) = Literate $ pass m
+ src/Text/Trifecta/Literate/Prim.hs view
@@ -0,0 +1,60 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Literate.Prim+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Literate.Prim+ ( LiterateState(..)+ , defaultLiterateState+ , LiterateMark(..)+ ) where++import Data.Functor+import Data.Foldable+import Data.Traversable+import Data.Semigroup+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta++data LiterateState+ = LiterateStart -- ^ Parsing literate syntax+ | IlliterateStart -- ^ Disable literate parsing+ | LiterateCode -- ^ In the midst of a @\begin{code} ... \end{code}@ block+ | LiterateTrack -- ^ In the midst of a @> ...@ block++defaultLiterateState :: LiterateState+defaultLiterateState = LiterateStart++data LiterateMark d = LiterateMark LiterateState d++instance Functor LiterateMark where+ fmap f (LiterateMark s a) = LiterateMark s (f a)++instance Foldable LiterateMark where+ foldMap f (LiterateMark _ a) = f a++instance Traversable LiterateMark where+ traverse f (LiterateMark s a) = LiterateMark s <$> f a++instance Foldable1 LiterateMark where+ foldMap1 f (LiterateMark _ a) = f a++instance Traversable1 LiterateMark where+ traverse1 f (LiterateMark s a) = LiterateMark s <$> f a++instance HasDelta d => HasDelta (LiterateMark d) where+ delta (LiterateMark _ d) = delta d++instance HasBytes d => HasBytes (LiterateMark d) where+ bytes (LiterateMark _ d) = bytes d++instance Semigroup d => Semigroup (LiterateMark d) where+ LiterateMark _ d <> LiterateMark s e = LiterateMark s (d <> e)
+ src/Text/Trifecta/Parser.hs view
@@ -0,0 +1,47 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Parser+ ( module Text.Trifecta.Parser.ByteString+ , module Text.Trifecta.Parser.Char+ , module Text.Trifecta.Parser.Class+ , module Text.Trifecta.Parser.Combinators+ , module Text.Trifecta.Parser.Identifier+ , module Text.Trifecta.Parser.Prim+ , module Text.Trifecta.Parser.Result+ , module Text.Trifecta.Parser.Rich+ , module Text.Trifecta.Parser.Token+ -- * Expressive Diagnostics+ -- ** Text.Trifecta.Diagnostic.Rendering.Caret+ , caret+ , careted+ -- ** Text.Trifecta.Diagnostic.Rendering.Span+ , span+ , spanned+ -- ** Text.Trifecta.Diagnostic.Rendering.Fixit+ , fixit++ ) where++import Text.Trifecta.Diagnostic.Rendering.Caret (caret, careted)+import Text.Trifecta.Diagnostic.Rendering.Span (span, spanned)+import Text.Trifecta.Diagnostic.Rendering.Fixit (fixit)+import Text.Trifecta.Parser.ByteString+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Parser.Identifier+import Text.Trifecta.Parser.Prim+import Text.Trifecta.Parser.Result+import Text.Trifecta.Parser.Rich+import Text.Trifecta.Parser.Token++import Prelude ()
+ src/Text/Trifecta/Parser/ByteString.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, Rank2Types #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.ByteString+-- Copyright : (c) Edward Kmett 2011+-- License : BSD-style (see the LICENSE file)+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable (mptcs, fundeps)+--+-- Loading a file as a strict bytestring in one step.+--+-----------------------------------------------------------------------------+++module Text.Trifecta.Parser.ByteString+ ( parseFromFile+ , parseFromFileEx+ , parseByteString+ , parseTest+ ) where++import Control.Applicative+import Control.Monad (unless)+import Data.Semigroup+import Data.Foldable+import qualified Data.ByteString as B+import System.Console.Terminfo.PrettyPrint+import Text.Trifecta.Parser.Mark+import Text.Trifecta.Parser.Prim+import Text.Trifecta.Parser.Step+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Parser.Result+import Data.Sequence as Seq+import qualified Data.ByteString.UTF8 as UTF8+++-- | @parseFromFile p filePath@ runs a parser @p@ on the+-- input read from @filePath@ using 'ByteString.readFile'. All diagnostic messages+-- emitted over the course of the parse attempt are shown to the user on the console.+--+-- > main = do+-- > result <- parseFromFile numbers "digits.txt"+-- > case result of+-- > Nothing -> return ()+-- > Just a -> print $ sum a++parseFromFile :: Show a => (forall r. Parser r String a) -> String -> IO (Maybe a)+parseFromFile p fn = do+ result <- parseFromFileEx p fn+ case result of+ Success xs a -> Just a <$ unless (Seq.null xs) (displayLn (toList xs))+ Failure xs -> Nothing <$ unless (Seq.null xs) (displayLn (toList xs))++-- | @parseFromFileEx p filePath@ runs a parser @p@ on the+-- input read from @filePath@ using 'ByteString.readFile'. Returns all diagnostic messages+-- emitted over the course of the parse and the answer if the parse was successful.+--+-- > main = do+-- > result <- parseFromFileEx (many number) "digits.txt"+-- > case result of+-- > Failure xs -> unless (Seq.null xs) $ displayLn xs+-- > Success xs a ->+-- > unless (Seq.null xs) $ displayLn xs+-- > print $ sum a+-- >++parseFromFileEx :: Show a => (forall r. Parser r String a) -> String -> IO (Result TermDoc a)+parseFromFileEx p fn = parseByteString p (Directed (UTF8.fromString fn) 0 0 0 0) <$> B.readFile fn++-- | @parseByteString p delta i@ runs a parser @p@ on @i@.++parseByteString :: Show a => (forall r. Parser r String a) -> Delta -> UTF8.ByteString -> Result TermDoc a+parseByteString p d inp = starve+ $ feed inp+ $ stepParser (fmap prettyTerm)+ (why prettyTerm)+ (release d *> p)+ mempty+ True+ mempty+ mempty+++parseTest :: Show a => (forall r. Parser r String a) -> String -> IO ()+parseTest p s = case parseByteString p mempty (UTF8.fromString s) of+ Failure xs -> displayLn $ toList xs+ Success xs a -> do+ unless (Seq.null xs) $ displayLn $ toList xs+ print a+
+ src/Text/Trifecta/Parser/Char.hs view
@@ -0,0 +1,204 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts, PatternGuards #-}+{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Char+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Parser.Char+ ( oneOf -- :: MonadParser m => [Char] -> m Char+ , noneOf -- :: MonadParser m => [Char] -> m Char+ , oneOfSet -- :: MonadParser m => CharSet -> m Char+ , noneOfSet -- :: MonadParser m => CharSet -> m Char+ , spaces -- :: MonadParser m => m ()+ , space -- :: MonadParser m => m Char+ , newline -- :: MonadParser m => m Char+ , tab -- :: MonadParser m => m Char+ , upper -- :: MonadParser m => m Char+ , lower -- :: MonadParser m => m Char+ , alphaNum -- :: MonadParser m => m Char+ , letter -- :: MonadParser m => m Char+ , digit -- :: MonadParser m => m Char+ , hexDigit -- :: MonadParser m => m Char+ , octDigit -- :: MonadParser m => m Char+ , char -- :: MonadParser m => Char -> m Char+ , notChar -- :: MonadParser m => Char -> m Char+ , anyChar -- :: MonadParser m => m Char+ , string -- :: MonadParser m => String -> m String+ , byteString -- :: MonadParser m => ByteString -> m ByteString+ ) where++import Data.Char+import Control.Applicative+import Control.Monad (guard)+import Text.Trifecta.Parser.Class+import Text.Trifecta.Rope.Delta+import qualified Data.IntSet as IntSet+import Data.CharSet (CharSet(..))+import qualified Data.CharSet as CharSet+import qualified Data.CharSet.ByteSet as ByteSet+import qualified Data.ByteString as Strict+import Data.ByteString.Internal (w2c,c2w)+import Data.ByteString.UTF8 as UTF8++-- | @oneOf cs@ succeeds if the current character is in the supplied+-- list of characters @cs@. Returns the parsed character. See also+-- 'satisfy'.+-- +-- > vowel = oneOf "aeiou"+oneOf :: MonadParser m => [Char] -> m Char+oneOf xs = oneOfSet (CharSet.fromList xs)+{-# INLINE oneOf #-}++-- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current+-- character /not/ in the supplied list of characters @cs@. Returns the+-- parsed character.+--+-- > consonant = noneOf "aeiou"+noneOf :: MonadParser m => [Char] -> m Char+noneOf xs = noneOfSet (CharSet.fromList xs)+{-# INLINE noneOf #-}++-- | @oneOfSet cs@ succeeds if the current character is in the supplied+-- set of characters @cs@. Returns the parsed character. See also+-- 'satisfy'.+-- +-- > vowel = oneOf "aeiou"+oneOfSet :: MonadParser m => CharSet -> m Char+oneOfSet (CharSet True bs is)+ | (_,r) <- IntSet.split 0x80 is, IntSet.null r = w2c <$> satisfy8 (\w -> ByteSet.member w bs)+ | otherwise = satisfy (\c -> IntSet.member (fromEnum c) is)+oneOfSet (CharSet False bs is) + | (_,r) <- IntSet.split 0x80 is, not (IntSet.null r) = satisfy (\c -> not (IntSet.member (fromEnum c) is))+ | otherwise = satisfyAscii (\c -> not (ByteSet.member (c2w c) bs))+{-# INLINE oneOfSet #-}+ +-- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current+-- character /not/ in the supplied list of characters @cs@. Returns the+-- parsed character.+--+-- > consonant = noneOf "aeiou"+noneOfSet :: MonadParser m => CharSet -> m Char+noneOfSet s = oneOfSet (CharSet.complement s)+{-# INLINE noneOfSet #-}++-- | Skips /zero/ or more white space characters. See also 'skipMany' and+-- 'whiteSpace'.+spaces :: MonadParser m => m ()+spaces = skipMany space <?> "white space"++-- | Parses a white space character (any character which satisfies 'isSpace')+-- Returns the parsed character. +space :: MonadParser m => m Char+space = satisfy isSpace <?> "space"+{-# INLINE space #-}++-- | Parses a newline character (\'\\n\'). Returns a newline character. +newline :: MonadParser m => m Char+newline = char '\n' <?> "new-line"+{-# INLINE newline #-}++-- | Parses a tab character (\'\\t\'). Returns a tab character. +tab :: MonadParser m => m Char+tab = char '\t' <?> "tab"+{-# INLINE tab #-}++-- | Parses an upper case letter (a character between \'A\' and \'Z\').+-- Returns the parsed character. +upper :: MonadParser m => m Char+upper = satisfy isUpper <?> "uppercase letter"+{-# INLINE upper #-}++-- | Parses a lower case character (a character between \'a\' and \'z\').+-- Returns the parsed character. +lower :: MonadParser m => m Char+lower = satisfy isLower <?> "lowercase letter"+{-# INLINE lower #-}++-- | Parses a letter or digit (a character between \'0\' and \'9\').+-- Returns the parsed character. ++alphaNum :: MonadParser m => m Char+alphaNum = satisfy isAlphaNum <?> "letter or digit"+{-# INLINE alphaNum #-}++-- | Parses a letter (an upper case or lower case character). Returns the+-- parsed character. ++letter :: MonadParser m => m Char+letter = satisfy isAlpha <?> "letter"+{-# INLINE letter #-}++-- | Parses a digit. Returns the parsed character. ++digit :: MonadParser m => m Char+digit = satisfy isDigit <?> "digit"+{-# INLINE digit #-}++-- | Parses a hexadecimal digit (a digit or a letter between \'a\' and+-- \'f\' or \'A\' and \'F\'). Returns the parsed character. +hexDigit :: MonadParser m => m Char+hexDigit = satisfy isHexDigit <?> "hexadecimal digit"+{-# INLINE hexDigit #-}++-- | Parses an octal digit (a character between \'0\' and \'7\'). Returns+-- the parsed character. +octDigit :: MonadParser m => m Char+octDigit = satisfy isOctDigit <?> "octal digit"+{-# INLINE octDigit #-}++-- | @char c@ parses a single character @c@. Returns the parsed+-- character (i.e. @c@).+--+-- > semiColon = char ';'+char :: MonadParser m => Char -> m Char+char c + | c <= w2c 0x7f, w <- c2w c = w2c <$> satisfy8 (w ==) <?> show [c]+ | otherwise = satisfy (c ==) <?> show [c]+{-# INLINE char #-}++-- | @notChar c@ parses any single character other than @c@. Returns the parsed+-- character.+--+-- > semiColon = char ';'+notChar :: MonadParser m => Char -> m Char+notChar c + | fromEnum c <= 0x7f = satisfyAscii (c /=)+ | otherwise = satisfy (c /=)+{-# INLINE notChar #-}++-- | This parser succeeds for any character. Returns the parsed character. +anyChar :: MonadParser m => m Char+anyChar = satisfy (const True)++-- | @string s@ parses a sequence of characters given by @s@. Returns+-- the parsed string (i.e. @s@).+--+-- > divOrMod = string "div" +-- > <|> string "mod"+string :: MonadParser m => String -> m String+string s = s <$ byteString (UTF8.fromString s) <?> show s++-- | @byteString s@ parses a sequence of bytes given by @s@. Returns+-- the parsed byteString (i.e. @s@).+--+-- > divOrMod = string "div" +-- > <|> string "mod"+byteString :: MonadParser m => Strict.ByteString -> m Strict.ByteString+byteString bs = do+ r <- restOfLine+ let lr = Strict.length r+ lbs = Strict.length bs+ guard $ lr > 0+ case compare lbs lr of+ LT | bs `Strict.isPrefixOf` r -> bs <$ skipping (delta bs)+ EQ | bs == r -> bs <$ skipping (delta bs)+ GT | r `Strict.isPrefixOf` bs -> bs <$ skipping (delta r) *> byteString (Strict.drop lr bs)+ _ -> empty + <?> show (UTF8.toString bs)
+ src/Text/Trifecta/Parser/Char8.hs view
@@ -0,0 +1,213 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts, PatternGuards #-}+{-# OPTIONS_GHC -fspec-constr -fspec-constr-count=8 #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Char8+-- Copyright : (c) Edward Kmett 2011+-- License : BSD-style (see the LICENSE file)+-- +-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable (mptcs, fundeps)+-- +-- This provides a thin backwards compatibility layer for folks who+-- want to write parsers for languages where characters are bytes+-- and don't need to deal with unicode issues. Diagnostics will still+-- report the correct column number in the absence of high ascii characters+-- but if you have those in your source file, you probably aren't going to+-- want to draw those to the screen anyways.+--+-----------------------------------------------------------------------------+++module Text.Trifecta.Parser.Char8+ ( satisfy -- :: MonadParser m => (Char -> Bool) -> m Char+ , oneOf -- :: MonadParser m => [Char] -> m Char+ , noneOf -- :: MonadParser m => [Char] -> m Char+ , oneOfSet -- :: MonadParser m => ByteSet -> m Char+ , noneOfSet -- :: MonadParser m => ByteSet -> m Char+ , spaces -- :: MonadParser m => m ()+ , space -- :: MonadParser m => m Char+ , newline -- :: MonadParser m => m Char+ , tab -- :: MonadParser m => m Char+ , upper -- :: MonadParser m => m Char+ , lower -- :: MonadParser m => m Char+ , alphaNum -- :: MonadParser m => m Char+ , letter -- :: MonadParser m => m Char+ , digit -- :: MonadParser m => m Char+ , hexDigit -- :: MonadParser m => m Char+ , octDigit -- :: MonadParser m => m Char+ , char -- :: MonadParser m => Char -> m Char+ , notChar -- :: MonadParser m => Char -> m Char+ , anyChar -- :: MonadParser m => m Char+ , string -- :: MonadParser m => String -> m String+ , byteString -- :: MonadParser m => ByteString -> m ByteString+ ) where++import Data.Char+import Control.Applicative+import Control.Monad (guard)+import Text.Trifecta.Parser.Class hiding (satisfy)+import Text.Trifecta.Rope.Delta+import Data.CharSet.ByteSet (ByteSet(..))+import qualified Data.CharSet.ByteSet as ByteSet+import qualified Data.ByteString as Strict+import Data.ByteString.Internal (w2c,c2w)+import qualified Data.ByteString.Char8 as Char8++-- | Using this instead of 'Text.Trifecta.Parser.Class.satisfy'+-- you too can time travel back to when men were men and characters+-- fit into 8 bits like God intended. It might also be useful+-- when writing lots of fiddly protocol code, where the UTF8 decoding+-- is probably a very bad idea.+satisfy :: MonadParser m => (Char -> Bool) -> m Char+satisfy f = w2c <$> satisfy8 (\w -> f (w2c w))++-- | @oneOf cs@ succeeds if the current character is in the supplied+-- list of characters @cs@. Returns the parsed character. See also+-- 'satisfy'.+-- +-- > vowel = oneOf "aeiou"+oneOf :: MonadParser m => [Char] -> m Char+oneOf xs = oneOfSet (ByteSet.fromList (map c2w xs))+{-# INLINE oneOf #-}++-- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current+-- character /not/ in the supplied list of characters @cs@. Returns the+-- parsed character.+--+-- > consonant = noneOf "aeiou"+noneOf :: MonadParser m => [Char] -> m Char+noneOf xs = noneOfSet (ByteSet.fromList (map c2w xs))+{-# INLINE noneOf #-}++-- | @oneOfSet cs@ succeeds if the current character is in the supplied+-- set of characters @cs@. Returns the parsed character. See also+-- 'satisfy'.+-- +-- > vowel = oneOf "aeiou"+oneOfSet :: MonadParser m => ByteSet -> m Char+oneOfSet bs = w2c <$> satisfy8 (\w -> ByteSet.member w bs)+{-# INLINE oneOfSet #-}+ +-- | As the dual of 'oneOf', @noneOf cs@ succeeds if the current+-- character /not/ in the supplied list of characters @cs@. Returns the+-- parsed character.+--+-- > consonant = noneOf "aeiou"+noneOfSet :: MonadParser m => ByteSet -> m Char+noneOfSet s = w2c <$> satisfy8 (\w -> not (ByteSet.member w s))+{-# INLINE noneOfSet #-}++-- | Skips /zero/ or more white space characters. See also 'skipMany' and+-- 'whiteSpace'.+spaces :: MonadParser m => m ()+spaces = skipMany space <?> "white space"++-- | Parses a white space character (any character which satisfies 'isSpace')+-- Returns the parsed character. +space :: MonadParser m => m Char+space = satisfy isSpace <?> "space"+{-# INLINE space #-}++-- | Parses a newline character (\'\\n\'). Returns a newline character. +newline :: MonadParser m => m Char+newline = char '\n' <?> "new-line"+{-# INLINE newline #-}++-- | Parses a tab character (\'\\t\'). Returns a tab character. +tab :: MonadParser m => m Char+tab = char '\t' <?> "tab"+{-# INLINE tab #-}++-- | Parses an upper case letter (a character between \'A\' and \'Z\').+-- Returns the parsed character. +upper :: MonadParser m => m Char+upper = satisfy isUpper <?> "uppercase letter"+{-# INLINE upper #-}++-- | Parses a lower case character (a character between \'a\' and \'z\').+-- Returns the parsed character. +lower :: MonadParser m => m Char+lower = satisfy isLower <?> "lowercase letter"+{-# INLINE lower #-}++-- | Parses a letter or digit (a character between \'0\' and \'9\').+-- Returns the parsed character. ++alphaNum :: MonadParser m => m Char+alphaNum = satisfy isAlphaNum <?> "letter or digit"+{-# INLINE alphaNum #-}++-- | Parses a letter (an upper case or lower case character). Returns the+-- parsed character. ++letter :: MonadParser m => m Char+letter = satisfy isAlpha <?> "letter"+{-# INLINE letter #-}++-- | Parses a digit. Returns the parsed character. ++digit :: MonadParser m => m Char+digit = satisfy isDigit <?> "digit"+{-# INLINE digit #-}++-- | Parses a hexadecimal digit (a digit or a letter between \'a\' and+-- \'f\' or \'A\' and \'F\'). Returns the parsed character. +hexDigit :: MonadParser m => m Char+hexDigit = satisfy isHexDigit <?> "hexadecimal digit"+{-# INLINE hexDigit #-}++-- | Parses an octal digit (a character between \'0\' and \'7\'). Returns+-- the parsed character. +octDigit :: MonadParser m => m Char+octDigit = satisfy isOctDigit <?> "octal digit"+{-# INLINE octDigit #-}++-- | @char c@ parses a single character @c@. Returns the parsed+-- character (i.e. @c@).+--+-- > semiColon = char ';'+char :: MonadParser m => Char -> m Char+char c = satisfy (c ==) <?> show [c]+{-# INLINE char #-}++-- | @char c@ parses a single character @c@. Returns the parsed+-- character (i.e. @c@).+--+-- > semiColon = char ';'+notChar :: MonadParser m => Char -> m Char+notChar c = satisfy (c /=)+{-# INLINE notChar #-}++-- | This parser succeeds for any character. Returns the parsed character. +anyChar :: MonadParser m => m Char+anyChar = satisfy (const True)++-- | @string s@ parses a sequence of characters given by @s@. Returns+-- the parsed string (i.e. @s@).+--+-- > divOrMod = string "div" +-- > <|> string "mod"+string :: MonadParser m => String -> m String+string s = s <$ byteString (Char8.pack s) <?> show s++-- | @byteString s@ parses a sequence of bytes given by @s@. Returns+-- the parsed byteString (i.e. @s@).+--+-- > divOrMod = string "div" +-- > <|> string "mod"+byteString :: MonadParser m => Strict.ByteString -> m Strict.ByteString+byteString bs = do+ r <- restOfLine+ let lr = Strict.length r+ lbs = Strict.length bs+ guard $ lr > 0+ case compare lbs lr of+ LT | bs `Strict.isPrefixOf` r -> bs <$ skipping (delta bs)+ | otherwise -> empty+ EQ | bs == r -> bs <$ skipping (delta bs)+ | otherwise -> empty+ GT | r `Strict.isPrefixOf` bs -> bs <$ skipping (delta r) *> byteString (Strict.drop lr bs)+ | otherwise -> empty+ <?> show (Char8.unpack bs)
+ src/Text/Trifecta/Parser/Class.hs view
@@ -0,0 +1,271 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Class+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Class+ ( MonadParser(..)+ , satisfyAscii+ , restOfLine+ , (<?>)+ , sliced+ , rend+ , whiteSpace+ , highlight+ ) where++import Control.Applicative+import Control.Monad (MonadPlus(..))+import Control.Monad.Trans.Class+import Control.Monad.Trans.State.Lazy as Lazy+import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import Data.Word+import Data.ByteString as Strict+import Data.Char (isSpace)+import Data.ByteString.Internal (w2c)+import Data.Semigroup+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Highlight.Prim+import Text.Trifecta.Diagnostic.Rendering.Prim++infix 0 <?>++class (Alternative m, MonadPlus m) => MonadParser m where+ -- | Take a parser that may consume input, and on failure, go back to where we started and fail as if we didn't consume input.+ try :: m a -> m a++ -- Used to implement (<?>), runs the parser then sets the 'expected' tokens to the list supplied+ labels :: m a -> [String] -> m a++ -- | A version of many that discards its input. Specialized because it can often be implemented more cheaply.+ skipMany :: m a -> m ()+ skipMany p = () <$ many p++ -- | Parse a single character of the input, with UTF-8 decoding+ satisfy :: (Char -> Bool) -> m Char++ -- | Parse a single byte of the input, without UTF-8 decoding+ satisfy8 :: (Word8 -> Bool) -> m Word8++ -- | Usually, someSpace consists of /one/ or more occurrences of a 'space'.+ -- Some parsers may choose to recognize line comments or block (multi line)+ -- comments as white space as well.+ someSpace :: m ()+ someSpace = space *> skipMany space+ where space = satisfy isSpace++ -- | Called when we enter a nested pair of symbols.+ -- Overloadable to disable layout or highlight nested contexts.+ nesting :: m a -> m a+ nesting = id++ -- | Lexeme parser |semi| parses the character \';\' and skips any+ -- trailing white space. Returns the character \';\'.+ semi :: m Char+ semi = (satisfyAscii (';'==) <?> ";") <* (someSpace <|> pure ())++ -- | Used to emit an error on an unexpected token+ unexpected :: String -> m a++ -- | Retrieve the contents of the current line (from the beginning of the line)+ line :: m ByteString++ skipping :: Delta -> m ()++ -- | @highlightInterval@ is called internally in the token parsers.+ -- It delimits ranges of the input recognized by certain parsers that+ -- are useful for syntax highlighting. An interested monad could+ -- choose to listen to these events and construct an interval tree+ -- for later pretty printing purposes.+ highlightInterval :: Highlight -> Delta -> Delta -> m ()+ highlightInterval _ _ _ = pure ()++ position :: m Delta++ -- | run a parser, grabbing all of the text between its start and end points+ slicedWith :: (a -> Strict.ByteString -> r) -> m a -> m r++ -- | @lookAhead p@ parses @p@ without consuming any input.+ lookAhead :: m a -> m a+++instance MonadParser m => MonadParser (Lazy.StateT s m) where+ try (Lazy.StateT m) = Lazy.StateT $ try . m+ labels (Lazy.StateT m) ss = Lazy.StateT $ \s -> labels (m s) ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (Lazy.StateT m) = Lazy.StateT $ nesting . m+ skipping = lift . skipping+ position = lift position+ slicedWith f (Lazy.StateT m) = Lazy.StateT $ \s -> slicedWith (\(a,s') b -> (f a b, s')) $ m s+ lookAhead (Lazy.StateT m) = Lazy.StateT $ lookAhead . m++instance MonadParser m => MonadParser (Strict.StateT s m) where+ try (Strict.StateT m) = Strict.StateT $ try . m+ labels (Strict.StateT m) ss = Strict.StateT $ \s -> labels (m s) ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (Strict.StateT m) = Strict.StateT $ nesting . m+ skipping = lift . skipping+ position = lift position+ slicedWith f (Strict.StateT m) = Strict.StateT $ \s -> slicedWith (\(a,s') b -> (f a b, s')) $ m s+ lookAhead (Strict.StateT m) = Strict.StateT $ lookAhead . m++instance MonadParser m => MonadParser (ReaderT e m) where+ try (ReaderT m) = ReaderT $ try . m+ labels (ReaderT m) ss = ReaderT $ \s -> labels (m s) ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (ReaderT m) = ReaderT $ nesting . m+ skipping = lift . skipping+ position = lift position+ slicedWith f (ReaderT m) = ReaderT $ slicedWith f . m+ lookAhead (ReaderT m) = ReaderT $ lookAhead . m++instance (MonadParser m, Monoid w) => MonadParser (Strict.WriterT w m) where+ try (Strict.WriterT m) = Strict.WriterT $ try m+ labels (Strict.WriterT m) ss = Strict.WriterT $ labels m ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (Strict.WriterT m) = Strict.WriterT $ nesting m+ skipping = lift . skipping+ position = lift position+ slicedWith f (Strict.WriterT m) = Strict.WriterT $ slicedWith (\(a,s') b -> (f a b, s')) m+ lookAhead (Strict.WriterT m) = Strict.WriterT $ lookAhead m++instance (MonadParser m, Monoid w) => MonadParser (Lazy.WriterT w m) where+ try (Lazy.WriterT m) = Lazy.WriterT $ try m+ labels (Lazy.WriterT m) ss = Lazy.WriterT $ labels m ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (Lazy.WriterT m) = Lazy.WriterT $ nesting m+ skipping = lift . skipping+ position = lift position+ slicedWith f (Lazy.WriterT m) = Lazy.WriterT $ slicedWith (\(a,s') b -> (f a b, s')) m+ lookAhead (Lazy.WriterT m) = Lazy.WriterT $ lookAhead m++instance (MonadParser m, Monoid w) => MonadParser (Lazy.RWST r w s m) where+ try (Lazy.RWST m) = Lazy.RWST $ \r s -> try (m r s)+ labels (Lazy.RWST m) ss = Lazy.RWST $ \r s -> labels (m r s) ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (Lazy.RWST m) = Lazy.RWST $ \r s -> nesting (m r s)+ skipping = lift . skipping+ position = lift position+ slicedWith f (Lazy.RWST m) = Lazy.RWST $ \r s -> slicedWith (\(a,s',w) b -> (f a b, s',w)) $ m r s+ lookAhead (Lazy.RWST m) = Lazy.RWST $ \r s -> lookAhead $ m r s++instance (MonadParser m, Monoid w) => MonadParser (Strict.RWST r w s m) where+ try (Strict.RWST m) = Strict.RWST $ \r s -> try (m r s)+ labels (Strict.RWST m) ss = Strict.RWST $ \r s -> labels (m r s) ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (Strict.RWST m) = Strict.RWST $ \r s -> nesting (m r s)+ skipping = lift . skipping+ position = lift position+ slicedWith f (Strict.RWST m) = Strict.RWST $ \r s -> slicedWith (\(a,s',w) b -> (f a b, s',w)) $ m r s+ lookAhead (Strict.RWST m) = Strict.RWST $ \r s -> lookAhead $ m r s++instance MonadParser m => MonadParser (IdentityT m) where+ try = IdentityT . try . runIdentityT+ labels (IdentityT m) ss = IdentityT $ labels m ss+ line = lift line+ unexpected = lift . unexpected+ satisfy = lift . satisfy+ satisfy8 = lift . satisfy8+ someSpace = lift someSpace+ semi = lift semi+ highlightInterval h s e = lift $ highlightInterval h s e+ nesting (IdentityT m) = IdentityT $ nesting m+ skipping = lift . skipping+ position = lift position+ slicedWith f (IdentityT m) = IdentityT $ slicedWith f m+ lookAhead (IdentityT m) = IdentityT $ lookAhead m++-- | Skip zero or more bytes worth of white space. More complex parsers are +-- free to consider comments as white space.+whiteSpace :: MonadParser m => m ()+whiteSpace = someSpace <|> return ()+{-# INLINE whiteSpace #-}++satisfyAscii :: MonadParser m => (Char -> Bool) -> m Char+satisfyAscii p = w2c <$> satisfy8 (\w -> w <= 0x7f && p (w2c w))+{-# INLINE satisfyAscii #-}++-- | grab the remainder of the current line+restOfLine :: MonadParser m => m ByteString+restOfLine = do+ m <- position+ Strict.drop (fromIntegral (columnByte m)) <$> line+{-# INLINE restOfLine #-}++-- | label a parser with a name+(<?>) :: MonadParser m => m a -> String -> m a+p <?> msg = labels p [msg]+{-# INLINE (<?>) #-}++-- | run a parser, grabbing all of the text between its start and end points and discarding the original result+sliced :: MonadParser m => m a -> m ByteString+sliced = slicedWith (\_ bs -> bs)+{-# INLINE sliced #-}++rend :: MonadParser m => m Rendering+rend = rendering <$> position <*> line+{-# INLINE rend #-}++-- | run a parser, highlighting all of the text between its start and end points.+highlight :: MonadParser m => Highlight -> m a -> m a+highlight h p = do+ m <- position+ x <- p+ r <- position+ x <$ highlightInterval h m r+{-# INLINE highlight #-}
+ src/Text/Trifecta/Parser/Combinators.hs view
@@ -0,0 +1,207 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Combinators+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+--+-- Commonly used generic combinators+--+-----------------------------------------------------------------------------++module Text.Trifecta.Parser.Combinators+ ( choice+ , option+ , optional -- from Control.Applicative, parsec optionMaybe+ , skipOptional -- parsec optional+ , between+ , skipSome -- parsec skipMany1+ , some -- from Control.Applicative, parsec many1+ , many -- from Control.Applicative+ , sepBy+ , sepBy1+ , sepEndBy1+ , sepEndBy+ , endBy1+ , endBy+ , count+ , chainl+ , chainr+ , chainl1+ , chainr1+ , eof+ , manyTill+ , notFollowedBy+ ) where++import Data.Traversable+import Control.Applicative+import Control.Monad+import qualified Data.ByteString as B+import Text.Trifecta.Parser.Class++-- | @choice ps@ tries to apply the parsers in the list @ps@ in order,+-- until one of them succeeds. Returns the value of the succeeding+-- parser.+choice :: Alternative m => [m a] -> m a+choice = foldr (<|>) empty++-- | @option x p@ tries to apply parser @p@. If @p@ fails without+-- consuming input, it returns the value @x@, otherwise the value+-- returned by @p@.+--+-- > priority = option 0 (do{ d <- digit+-- > ; return (digitToInt d)+-- > })+option :: Alternative m => a -> m a -> m a+option x p = p <|> pure x++-- | @skipOptional p@ tries to apply parser @p@. It will parse @p@ or nothing.+-- It only fails if @p@ fails after consuming input. It discards the result+-- of @p@. (Plays the role of parsec's optional, which conflicts with Applicative's optional)+skipOptional :: Alternative m => m a -> m ()+skipOptional p = (() <$ p) <|> pure ()++-- | @between open close p@ parses @open@, followed by @p@ and @close@.+-- Returns the value returned by @p@.+--+-- > braces = between (symbol "{") (symbol "}")+between :: Applicative m => m bra -> m ket -> m a -> m a+between bra ket p = bra *> p <* ket++-- | @skipSome p@ applies the parser @p@ /one/ or more times, skipping+-- its result. (aka skipMany1 in parsec)+skipSome :: MonadParser m => m a -> m ()+skipSome p = p *> skipMany p++-- | @sepBy p sep@ parses /zero/ or more occurrences of @p@, separated+-- by @sep@. Returns a list of values returned by @p@.+--+-- > commaSep p = p `sepBy` (symbol ",")+sepBy :: Alternative m => m a -> m sep -> m [a]+sepBy p sep = sepBy1 p sep <|> pure []++-- | @sepBy1 p sep@ parses /one/ or more occurrences of @p@, separated+-- by @sep@. Returns a list of values returned by @p@.+sepBy1 :: Alternative m => m a -> m sep -> m [a]+sepBy1 p sep = (:) <$> p <*> many (sep *> p)++-- | @sepEndBy1 p sep@ parses /one/ or more occurrences of @p@,+-- separated and optionally ended by @sep@. Returns a list of values+-- returned by @p@.+sepEndBy1 :: Alternative m => m a -> m sep -> m [a]+sepEndBy1 p sep = flip id <$> p <*> ((flip (:) <$> (sep *> sepEndBy p sep)) <|> pure pure)++-- | @sepEndBy p sep@ parses /zero/ or more occurrences of @p@,+-- separated and optionally ended by @sep@, ie. haskell style+-- statements. Returns a list of values returned by @p@.+--+-- > haskellStatements = haskellStatement `sepEndBy` semi+sepEndBy :: Alternative m => m a -> m sep -> m [a]+sepEndBy p sep = sepEndBy1 p sep <|> pure []++-- | @endBy1 p sep@ parses /one/ or more occurrences of @p@, seperated+-- and ended by @sep@. Returns a list of values returned by @p@.+endBy1 :: Alternative m => m a -> m sep -> m [a]+endBy1 p sep = some (p <* sep)++-- | @endBy p sep@ parses /zero/ or more occurrences of @p@, seperated+-- and ended by @sep@. Returns a list of values returned by @p@.+--+-- > cStatements = cStatement `endBy` semi+endBy :: Alternative m => m a -> m sep -> m [a]+endBy p sep = many (p <* sep)++-- | @count n p@ parses @n@ occurrences of @p@. If @n@ is smaller or+-- equal to zero, the parser equals to @return []@. Returns a list of+-- @n@ values returned by @p@.+count :: Applicative m => Int -> m a -> m [a]+count n p | n <= 0 = pure []+ | otherwise = sequenceA (replicate n p)++-- | @chainr p op x@ parser /zero/ or more occurrences of @p@,+-- separated by @op@ Returns a value obtained by a /right/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@. If there are no occurrences of @p@, the value @x@ is+-- returned.+chainr :: Alternative m => m a -> m (a -> a -> a) -> a -> m a+chainr p op x = chainr1 p op <|> pure x++-- | @chainl p op x@ parser /zero/ or more occurrences of @p@,+-- separated by @op@. Returns a value obtained by a /left/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@. If there are zero occurrences of @p@, the value @x@ is+-- returned.+chainl :: Alternative m => m a -> m (a -> a -> a) -> a -> m a+chainl p op x = chainl1 p op <|> pure x++-- | @chainl1 p op x@ parser /one/ or more occurrences of @p@,+-- separated by @op@ Returns a value obtained by a /left/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@. . This parser can for example be used to eliminate left+-- recursion which typically occurs in expression grammars.+--+-- > expr = term `chainl1` addop+-- > term = factor `chainl1` mulop+-- > factor = parens expr <|> integer+-- >+-- > mulop = do{ symbol "*"; return (*) }+-- > <|> do{ symbol "/"; return (div) }+-- >+-- > addop = do{ symbol "+"; return (+) }+-- > <|> do{ symbol "-"; return (-) }+chainl1 :: Alternative m => m a -> m (a -> a -> a) -> m a+chainl1 p op = scan where+ scan = flip id <$> p <*> rst+ rst = (\f y g x -> g (f x y)) <$> op <*> p <*> rst <|> pure id++-- | @chainr1 p op x@ parser /one/ or more occurrences of |p|,+-- separated by @op@ Returns a value obtained by a /right/ associative+-- application of all functions returned by @op@ to the values returned+-- by @p@.+chainr1 :: Alternative m => m a -> m (a -> a -> a) -> m a+chainr1 p op = scan where+ scan = flip id <$> p <*> rst+ rst = (flip <$> op <*> scan) <|> pure id++-- | @manyTill p end@ applies parser @p@ /zero/ or more times until+-- parser @end@ succeeds. Returns the list of values returned by @p@.+-- This parser can be used to scan comments:+--+-- > simpleComment = do{ string "<!--"+-- > ; manyTill anyChar (try (string "-->"))+-- > }+--+-- Note the overlapping parsers @anyChar@ and @string \"-->\"@, and+-- therefore the use of the 'try' combinator.+manyTill :: Alternative m => m a -> m end -> m [a]+manyTill p end = go where go = ([] <$ end) <|> ((:) <$> p <*> go)++-- * MonadParsers++-- | This parser only succeeds at the end of the input. This is not a+-- primitive parser but it is defined using 'notFollowedBy'.+--+-- > eof = notFollowedBy anyChar <?> "end of input"+eof :: MonadParser m => m ()+eof = do+ l <- restOfLine+ guard $ B.null l+ <?> "end of input"++-- | @notFollowedBy p@ only succeeds when parser @p@ fails. This parser+-- does not consume any input. This parser can be used to implement the+-- \'longest match\' rule. For example, when recognizing keywords (for+-- example @let@), we want to make sure that a keyword is not followed+-- by a legal identifier character, in which case the keyword is+-- actually an identifier (for example @lets@). We can program this+-- behaviour as follows:+--+-- > keywordLet = try (do{ string "let"+-- > ; notFollowedBy alphaNum+-- > })+notFollowedBy :: (MonadParser m, Show a) => m a -> m ()+notFollowedBy p = try ((try p >>= unexpected . show) <|> pure ())
+ src/Text/Trifecta/Parser/Expr.hs view
@@ -0,0 +1,167 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Expr+-- Copyright : (c) Edward Kmett+-- (c) Paolo Martini 2007+-- (c) Daan Leijen 1999-2001, +-- License : BSD-style (see the LICENSE file)+-- +-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+-- +-- A helper module to parse \"expressions\".+-- Builds a parser given a table of operators and associativities.+-- +-----------------------------------------------------------------------------++module Text.Trifecta.Parser.Expr+ ( Assoc(..), Operator(..), OperatorTable+ , buildExpressionParser+ ) where++import Control.Applicative+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Combinators++-----------------------------------------------------------+-- Assoc and OperatorTable+-----------------------------------------------------------++-- | This data type specifies the associativity of operators: left, right+-- or none.++data Assoc + = AssocNone+ | AssocLeft+ | AssocRight++-- | This data type specifies operators that work on values of type @a@.+-- An operator is either binary infix or unary prefix or postfix. A+-- binary operator has also an associated associativity.++data Operator m a + = Infix (m (a -> a -> a)) Assoc+ | Prefix (m (a -> a))+ | Postfix (m (a -> a))++-- | An @OperatorTable m a@ is a list of @Operator m a@+-- lists. The list is ordered in descending+-- precedence. All operators in one list have the same precedence (but+-- may have a different associativity).++type OperatorTable m a = [[Operator m a]]++-----------------------------------------------------------+-- Convert an OperatorTable and basic term parser into+-- a full fledged expression parser+-----------------------------------------------------------++-- | @buildExpressionParser table term@ builds an expression parser for+-- terms @term@ with operators from @table@, taking the associativity+-- and precedence specified in @table@ into account. Prefix and postfix+-- operators of the same precedence can only occur once (i.e. @--2@ is+-- not allowed if @-@ is prefix negate). Prefix and postfix operators+-- of the same precedence associate to the left (i.e. if @++@ is+-- postfix increment, than @-2++@ equals @-1@, not @-3@).+--+-- The @buildExpressionParser@ takes care of all the complexity+-- involved in building expression parser. Here is an example of an+-- expression parser that handles prefix signs, postfix increment and+-- basic arithmetic.+--+-- > expr = buildExpressionParser table term+-- > <?> "expression"+-- >+-- > term = parens expr +-- > <|> natural+-- > <?> "simple expression"+-- >+-- > table = [ [prefix "-" negate, prefix "+" id ]+-- > , [postfix "++" (+1)]+-- > , [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]+-- > , [binary "+" (+) AssocLeft, binary "-" (-) AssocLeft ]+-- > ]+-- > +-- > binary name fun assoc = Infix (do{ reservedOp name; return fun }) assoc+-- > prefix name fun = Prefix (do{ reservedOp name; return fun })+-- > postfix name fun = Postfix (do{ reservedOp name; return fun })++buildExpressionParser :: MonadParser m+ => OperatorTable m a+ -> m a+ -> m a+buildExpressionParser operators simpleExpr+ = foldl (makeParser) simpleExpr operators+ where+ makeParser term ops+ = let (rassoc,lassoc,nassoc,prefix,postfix) = foldr splitOp ([],[],[],[],[]) ops++ rassocOp = choice rassoc+ lassocOp = choice lassoc+ nassocOp = choice nassoc+ prefixOp = choice prefix <?> ""+ postfixOp = choice postfix <?> ""++ ambigious assoc op= try $ op *> fail ("ambiguous use of a " ++ assoc ++ " associative operator")++ ambigiousRight = ambigious "right" rassocOp+ ambigiousLeft = ambigious "left" lassocOp+ ambigiousNon = ambigious "non" nassocOp++ termP = do{ pre <- prefixP+ ; x <- term+ ; post <- postfixP+ ; return (post (pre x))+ }++ postfixP = postfixOp <|> return id++ prefixP = prefixOp <|> return id++ rassocP x = do{ f <- rassocOp+ ; y <- termP >>= rassocP1+ ; return (f x y)+ }+ <|> ambigiousLeft+ <|> ambigiousNon+ -- <|> return x++ rassocP1 x = rassocP x <|> return x++ lassocP x = do{ f <- lassocOp+ ; y <- termP+ ; lassocP1 (f x y)+ }+ <|> ambigiousRight+ <|> ambigiousNon+ -- <|> return x++ lassocP1 x = lassocP x <|> return x++ nassocP x = do{ f <- nassocOp+ ; y <- termP+ ; ambigiousRight+ <|> ambigiousLeft+ <|> ambigiousNon+ <|> return (f x y)+ }+ -- <|> return x++ in do{ x <- termP+ ; rassocP x <|> lassocP x <|> nassocP x <|> return x+ <?> "operator"+ }+++ splitOp (Infix op assoc) (rassoc,lassoc,nassoc,prefix,postfix)+ = case assoc of+ AssocNone -> (rassoc,lassoc,op:nassoc,prefix,postfix)+ AssocLeft -> (rassoc,op:lassoc,nassoc,prefix,postfix)+ AssocRight -> (op:rassoc,lassoc,nassoc,prefix,postfix)++ splitOp (Prefix op) (rassoc,lassoc,nassoc,prefix,postfix)+ = (rassoc,lassoc,nassoc,op:prefix,postfix)++ splitOp (Postfix op) (rassoc,lassoc,nassoc,prefix,postfix)+ = (rassoc,lassoc,nassoc,prefix,op:postfix)
+ src/Text/Trifecta/Parser/Identifier.hs view
@@ -0,0 +1,67 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Identifier+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+--+-- > idStyle = haskellIdentifierStyle { styleReserved = ... }+-- > identifier = ident haskellIdentifierStyle+-- > reserved = reserve haskellIdentifierStyle+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Identifier+ ( IdentifierStyle(..)+ , liftIdentifierStyle+ , ident+ , reserve+ , reserveByteString+ ) where++import Data.ByteString as Strict hiding (map, zip, foldl, foldr)+import Data.ByteString.UTF8 as UTF8+import Data.HashSet as HashSet+import Control.Applicative+import Control.Monad (when)+import Control.Monad.Trans.Class+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Parser.Token.Combinators+import Text.Trifecta.Highlight.Prim++data IdentifierStyle m = IdentifierStyle+ { styleName :: String+ , styleStart :: m ()+ , styleLetter :: m ()+ , styleReserved :: HashSet ByteString+ , styleHighlight :: Highlight+ , styleReservedHighlight :: Highlight+ }++-- | Lift an identifier style into a monad transformer+liftIdentifierStyle :: (MonadTrans t, Monad m) => IdentifierStyle m -> IdentifierStyle (t m)+liftIdentifierStyle s =+ s { styleStart = lift (styleStart s)+ , styleLetter = lift (styleLetter s)+ }++-- | parse a reserved operator or identifier using a given style+reserve :: MonadParser m => IdentifierStyle m -> String -> m ()+reserve s name = reserveByteString s $! UTF8.fromString name++-- | parse a reserved operator or identifier using a given style specified by bytestring+reserveByteString :: MonadParser m => IdentifierStyle m -> ByteString -> m ()+reserveByteString s name = lexeme $ try $ do+ _ <- highlight (styleReservedHighlight s) $ byteString name+ notFollowedBy (styleLetter s) <?> "end of " ++ show name++-- | parse an non-reserved identifier or symbol+ident :: MonadParser m => IdentifierStyle m -> m ByteString+ident s = lexeme $ try $ do+ name <- highlight (styleHighlight s) (sliced (styleStart s *> skipMany (styleLetter s))) <?> styleName s+ when (member name (styleReserved s)) $ unexpected $ "reserved " ++ styleName s ++ " " ++ show name+ return name
+ src/Text/Trifecta/Parser/Identifier/Style.hs view
@@ -0,0 +1,70 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Identifier.Style+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Identifier.Style+ (+ -- identifier styles+ emptyIdents, haskellIdents, haskell98Idents+ -- operator styles+ , emptyOps, haskellOps, haskell98Ops+ ) where++import Data.ByteString as Strict hiding (map, zip, foldl, foldr)+import Data.ByteString.UTF8 as UTF8+import Data.HashSet as HashSet+import Data.Monoid+import Control.Applicative+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Identifier+import Text.Trifecta.Highlight.Prim++set :: [String] -> HashSet ByteString+set = HashSet.fromList . fmap UTF8.fromString++emptyOps, haskell98Ops, haskellOps :: MonadParser m => IdentifierStyle m+emptyOps = IdentifierStyle+ { styleName = "operator"+ , styleStart = styleLetter emptyOps+ , styleLetter = () <$ oneOf ":!#$%&*+./<=>?@\\^|-~"+ , styleReserved = mempty+ , styleHighlight = Operator+ , styleReservedHighlight = ReservedOperator+ }+haskell98Ops = emptyOps+ { styleReserved = set ["::","..","=","\\","|","<-","->","@","~","=>"]+ }+haskellOps = haskell98Ops++emptyIdents, haskell98Idents, haskellIdents :: MonadParser m => IdentifierStyle m+emptyIdents = IdentifierStyle+ { styleName = "identifier"+ , styleStart = () <$ (letter <|> char '_')+ , styleLetter = () <$ (alphaNum <|> oneOf "_'")+ , styleReserved = set []+ , styleHighlight = Identifier+ , styleReservedHighlight = ReservedIdentifier }++haskell98Idents = emptyIdents+ { styleReserved = set haskell98ReservedIdents }+haskellIdents = haskell98Idents+ { styleLetter = styleLetter haskell98Idents <|> () <$ char '#'+ , styleReserved = set $ haskell98ReservedIdents +++ ["foreign","import","export","primitive","_ccall_","_casm_" ,"forall"]+ }++haskell98ReservedIdents :: [String]+haskell98ReservedIdents =+ ["let","in","case","of","if","then","else","data","type"+ ,"class","default","deriving","do","import","infix"+ ,"infixl","infixr","instance","module","newtype"+ ,"where","primitive" -- "as","qualified","hiding"+ ]
+ src/Text/Trifecta/Parser/It.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE MultiParamTypeClasses, BangPatterns, MagicHash, UnboxedTuples, TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.It+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+-- harder, better, faster, stronger...+----------------------------------------------------------------------------+module Text.Trifecta.Parser.It + ( It(Pure, It)+ , needIt+ , wantIt+ , simplifyIt+ , runIt+ , fillIt+ , rewindIt+ , sliceIt+ , stepIt+ ) where++import Control.Applicative+import Control.Comonad+import Control.Monad+import Data.Semigroup+import Data.ByteString as Strict+import Data.ByteString.Lazy as Lazy+import Data.Functor.Bind+import Data.Profunctor+import Data.Key as Key+import Text.Trifecta.Rope.Prim as Rope+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Parser.Step+import Text.Trifecta.Util.Combinators as Util++data It r a+ = Pure a + | It a (r -> It r a)++instance Show a => Show (It r a) where+ showsPrec d (Pure a) = showParen (d > 10) $ showString "Pure " . showsPrec 11 a+ showsPrec d (It a _) = showParen (d > 10) $ showString "It " . showsPrec 11 a . showString " ..."++instance Functor (It r) where+ fmap f (Pure a) = Pure $ f a+ fmap f (It a k) = It (f a) $ fmap f . k++type instance Key (It r) = r++instance Profunctor It where+ lmap _ (Pure a) = Pure a+ lmap f (It a k) = It a (lmap f . k . f)++ rmap g (Pure a) = Pure (g a)+ rmap g (It a k) = It (g a) (rmap g . k)++instance Applicative (It r) where+ pure = Pure+ Pure f <*> Pure a = Pure $ f a+ Pure f <*> It a ka = It (f a) $ fmap f . ka+ It f kf <*> Pure a = It (f a) $ fmap ($a) . kf+ It f kf <*> It a ka = It (f a) $ \r -> kf r <*> ka r++instance Indexable (It r) where+ index (Pure a) _ = a+ index (It _ k) r = extract (k r)++instance Lookup (It r) where+ lookup = lookupDefault++instance Zip (It r) where+ zipWith = liftA2++simplifyIt :: It r a -> r -> It r a+simplifyIt (It _ k) r = k r+simplifyIt pa _ = pa++instance Monad (It r) where+ return = Pure+ Pure a >>= f = f a+ It a k >>= f = It (extract (f a)) $ \r -> case k r of + It a' k' -> It (Key.index (f a') r) $ k' >=> f+ Pure a' -> simplifyIt (f a') r++instance Apply (It r) where (<.>) = (<*>) +instance Bind (It r) where (>>-) = (>>=) ++-- | It is a cofree comonad+instance Comonad (It r) where+ duplicate p@Pure{} = Pure p+ duplicate p@(It _ k) = It p (duplicate . k)+ extend f p@Pure{} = Pure (f p)+ extend f p@(It _ k) = It (f p) (extend f . k)+ extract (Pure a) = a+ extract (It a _) = a++needIt :: a -> (r -> Maybe a) -> It r a+needIt z f = k where + k = It z $ \r -> case f r of + Just a -> Pure a+ Nothing -> k++wantIt :: a -> (r -> (# Bool, a #)) -> It r a+wantIt z f = It z k where + k r = case f r of+ (# False, a #) -> It a k+ (# True, a #) -> Pure a++-- scott decoding+runIt :: (a -> o) -> (a -> (r -> It r a) -> o) -> It r a -> o+runIt p _ (Pure a) = p a+runIt _ i (It a k) = i a k++-- * Rope specifics++-- | Given a position, go there, and grab the text forward from that point+fillIt :: r -> (Delta -> Strict.ByteString -> r) -> Delta -> It Rope r+fillIt kf ks n = wantIt kf $ \r -> + (# bytes n < bytes (rewind (delta r))+ , grabLine n r kf ks #) ++stepIt :: It Rope a -> Step e a+stepIt = go mempty where+ go r (Pure a) = StepDone r mempty a+ go r (It a k) = StepCont r (pure a) $ \s -> go s (k s)+ +-- | Return the text of the line that contains a given position+rewindIt :: Delta -> It Rope (Maybe Strict.ByteString)+rewindIt n = wantIt Nothing $ \r -> + (# bytes n < bytes (rewind (delta r))+ , grabLine (rewind n) r Nothing $ const Just #)++sliceIt :: Delta -> Delta -> It Rope Strict.ByteString+sliceIt !i !j = wantIt mempty $ \r -> + (# bj < bytes (rewind (delta r))+ , grabRest i r mempty $ const $ Util.fromLazy . Lazy.take (fromIntegral (bj - bi)) #)+ where+ bi = bytes i+ bj = bytes j
+ src/Text/Trifecta/Parser/Mark.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances, FlexibleInstances, FlexibleContexts #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Mark+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Mark+ ( MonadMark(..)+ ) where++import Control.Monad.Trans.Class+import Control.Monad.Trans.State.Lazy as Lazy+import Control.Monad.Trans.State.Strict as Strict+import Control.Monad.Trans.Writer.Lazy as Lazy+import Control.Monad.Trans.Writer.Strict as Strict+import Control.Monad.Trans.RWS.Lazy as Lazy+import Control.Monad.Trans.RWS.Strict as Strict+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Identity+import Data.Monoid+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Parser.Class++class (MonadParser m, HasDelta d) => MonadMark d m | m -> d where+ -- | mark the current location so it can be used in constructing a span, or for later seeking+ mark :: m d+ -- | Seek a previously marked location+ release :: d -> m ()++instance MonadMark d m => MonadMark d (Lazy.StateT s m) where+ mark = lift mark+ release = lift . release++instance MonadMark d m => MonadMark d (Strict.StateT s m) where+ mark = lift mark+ release = lift . release++instance MonadMark d m => MonadMark d (ReaderT e m) where+ mark = lift mark+ release = lift . release++instance (MonadMark d m, Monoid w) => MonadMark d (Strict.WriterT w m) where+ mark = lift mark+ release = lift . release++instance (MonadMark d m, Monoid w) => MonadMark d (Lazy.WriterT w m) where+ mark = lift mark+ release = lift . release++instance (MonadMark d m, Monoid w) => MonadMark d (Lazy.RWST r w s m) where+ mark = lift mark+ release = lift . release++instance (MonadMark d m, Monoid w) => MonadMark d (Strict.RWST r w s m) where+ mark = lift mark+ release = lift . release++instance MonadMark d m => MonadMark d (IdentityT m) where+ mark = lift mark+ release = lift . release+
+ src/Text/Trifecta/Parser/Perm.hs view
@@ -0,0 +1,141 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Perm+-- Copyright : (c) Edward Kmett 2011+-- (c) Paolo Martini 2007+-- (c) Daan Leijen 1999-2001+-- License : BSD-style+-- +-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+-- +-- This module implements permutation parsers. The algorithm is described in:+-- +-- /Parsing Permutation Phrases,/+-- by Arthur Baars, Andres Loh and Doaitse Swierstra.+-- Published as a functional pearl at the Haskell Workshop 2001.+-- +-----------------------------------------------------------------------------++{-# LANGUAGE ExistentialQuantification #-}++module Text.Trifecta.Parser.Perm+ ( Perm+ , permute+ , (<||>), (<$$>)+ , (<|?>), (<$?>)+ ) where++import Control.Applicative+import Text.Trifecta.Parser.Combinators (choice)++infixl 1 <||>, <|?>+infixl 2 <$$>, <$?>++{---------------------------------------------------------------+ Building a permutation parser+---------------------------------------------------------------}++-- | The expression @perm \<||> p@ adds parser @p@ to the permutation+-- parser @perm@. The parser @p@ is not allowed to accept empty input -+-- use the optional combinator ('<|?>') instead. Returns a+-- new permutation parser that includes @p@. ++(<||>) :: Functor m => Perm m (a -> b) -> m a -> Perm m b+(<||>) perm p = add perm p++-- | The expression @f \<$$> p@ creates a fresh permutation parser+-- consisting of parser @p@. The the final result of the permutation+-- parser is the function @f@ applied to the return value of @p@. The+-- parser @p@ is not allowed to accept empty input - use the optional+-- combinator ('<$?>') instead.+--+-- If the function @f@ takes more than one parameter, the type variable+-- @b@ is instantiated to a functional type which combines nicely with+-- the adds parser @p@ to the ('<||>') combinator. This+-- results in stylized code where a permutation parser starts with a+-- combining function @f@ followed by the parsers. The function @f@+-- gets its parameters in the order in which the parsers are specified,+-- but actual input can be in any order.++(<$$>) :: Functor m => (a -> b) -> m a -> Perm m b+(<$$>) f p = newPerm f <||> p++-- | The expression @perm \<||> (x,p)@ adds parser @p@ to the+-- permutation parser @perm@. The parser @p@ is optional - if it can+-- not be applied, the default value @x@ will be used instead. Returns+-- a new permutation parser that includes the optional parser @p@. ++(<|?>) :: Functor m => Perm m (a -> b) -> (a, m a) -> Perm m b+(<|?>) perm (x,p) = addOpt perm x p++-- | The expression @f \<$?> (x,p)@ creates a fresh permutation parser+-- consisting of parser @p@. The the final result of the permutation+-- parser is the function @f@ applied to the return value of @p@. The+-- parser @p@ is optional - if it can not be applied, the default value+-- @x@ will be used instead. ++(<$?>) :: Functor m => (a -> b) -> (a, m a) -> Perm m b+(<$?>) f (x,p) = newPerm f <|?> (x,p)++{---------------------------------------------------------------+ The permutation tree+---------------------------------------------------------------}++-- | The type @Perm m a@ denotes a permutation parser that,+-- when converted by the 'permute' function, parses +-- using the base parsing monad @m@ and returns a value of+-- type @a@ on success.+--+-- Normally, a permutation parser is first build with special operators+-- like ('<||>') and than transformed into a normal parser+-- using 'permute'.++data Perm m a = Perm (Maybe a) [Branch m a]++instance Functor m => Functor (Perm m) where+ fmap f (Perm x xs) = Perm (fmap f x) (fmap f <$> xs)++data Branch m a = forall b. Branch (Perm m (b -> a)) (m b)++instance Functor m => Functor (Branch m) where+ fmap f (Branch perm p) = Branch (fmap (f.) perm) p++-- | The parser @permute perm@ parses a permutation of parser described+-- by @perm@. For example, suppose we want to parse a permutation of:+-- an optional string of @a@'s, the character @b@ and an optional @c@.+-- This can be described by:+--+-- > test = permute (tuple <$?> ("",some (char 'a'))+-- > <||> char 'b' +-- > <|?> ('_',char 'c'))+-- > where+-- > tuple a b c = (a,b,c)++-- transform a permutation tree into a normal parser+permute :: Alternative m => Perm m a -> m a+permute (Perm def xs)+ = choice (map branch xs ++ e)+ where+ e = maybe [] (pure . pure) def+ branch (Branch perm p) = flip id <$> p <*> permute perm+ +-- build permutation trees+newPerm :: (a -> b) -> Perm m (a -> b)+newPerm f = Perm (Just f) []++add :: Functor m => Perm m (a -> b) -> m a -> Perm m b+add perm@(Perm _mf fs) p+ = Perm Nothing (first:map insert fs)+ where+ first = Branch perm p+ insert (Branch perm' p')+ = Branch (add (fmap flip perm') p) p'++addOpt :: Functor m => Perm m (a -> b) -> a -> m a -> Perm m b+addOpt perm@(Perm mf fs) x p+ = Perm (fmap ($ x) mf) (first:map insert fs)+ where+ first = Branch perm p+ insert (Branch perm' p') = Branch (addOpt (fmap flip perm') x p) p'
+ src/Text/Trifecta/Parser/Prim.hs view
@@ -0,0 +1,322 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts, Rank2Types, FlexibleInstances, BangPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Prim+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Prim+ ( Parser(..)+ , why+ , stepParser+ , manyAccum+ ) where+++import Control.Applicative+import Control.Monad.Error.Class+import Control.Monad.Writer.Class+import Control.Monad.Cont.Class+import Control.Monad+import Control.Comonad+import qualified Data.Functor.Plus as Plus+import Data.Functor.Plus hiding (some, many)+import Data.Function+import Data.Semigroup+import Data.Foldable+import qualified Data.List as List+import Data.Functor.Bind (Bind((>>-)))+import qualified Text.Trifecta.IntervalMap as IntervalMap+import Data.Set as Set hiding (empty, toList)+import Data.ByteString as Strict hiding (empty)+import Data.Sequence as Seq hiding (empty)+import Data.ByteString.UTF8 as UTF8+import Text.PrettyPrint.Free hiding (line)+import Text.Trifecta.Diagnostic.Class+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Err+import Text.Trifecta.Diagnostic.Err.State+import Text.Trifecta.Diagnostic.Err.Log+import Text.Trifecta.Diagnostic.Rendering.Caret+import Text.Trifecta.Highlight.Class+import Text.Trifecta.Highlight.Prim+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.It+import Text.Trifecta.Parser.Mark+import Text.Trifecta.Parser.Step+import Text.Trifecta.Parser.Result+import Text.Trifecta.Rope.Delta as Delta+import Text.Trifecta.Rope.Prim+import Text.Trifecta.Rope.Bytes++data Parser r e a = Parser+ { unparser ::+ (a -> ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- uncommitted ok+ ( ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- uncommitted err+ (a -> ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- committed ok+ ( ErrState e -> ErrLog e -> Bool -> Delta -> ByteString -> It Rope r) -> -- committed err+ ErrLog e -> Bool -> Delta -> ByteString -> It Rope r+ }++instance Functor (Parser r e) where+ fmap f (Parser m) = Parser $ \ eo ee co -> m (eo . f) ee (co . f)+ {-# INLINE fmap #-}+ a <$ Parser m = Parser $ \ eo ee co -> m (\_ -> eo a) ee (\_ -> co a)+ {-# INLINE (<$) #-}++instance Apply (Parser r e) where (<.>) = (<*>)+instance Applicative (Parser r e) where+ pure a = Parser $ \ eo _ _ _ -> eo a mempty+ {-# INLINE pure #-}+ (<*>) = ap+ {-# INLINE (<*>) #-}+{-+ Parser m <*> Parser n = Parser $ \ eo ee co ce ->+ m (\f e -> n (\a e' -> eo (f a) (e <> e')) ee (\a e' -> co (f a) (e <> e')) ce) ee+ (\f e -> n (\a e' -> co (f a) (e <> e')) ce (\a e' -> co (f a) (e <> e')) ce) ce+ {-# INLINE (<*>) #-}+ Parser m <* Parser n = Parser $ \ eo ee co ce ->+ m (\a e -> n (\_ e' -> eo a (e <> e')) ee (\_ e' -> co a (e <> e')) ce) ee+ (\a e -> n (\_ e' -> co a (e <> e')) ce (\_ e' -> co a (e <> e')) ce) ce+ {-# INLINE (<*) #-}+ Parser m *> Parser n = Parser $ \ eo ee co ce ->+ m (\_ e -> n (\a e' -> eo a (e <> e')) ee (\a e' -> co a (e <> e')) ce) ee+ (\_ e -> n (\a e' -> co a (e <> e')) ce (\a e' -> co a (e <> e')) ce) ce+ {-# INLINE (*>) #-}+-}++instance Alt (Parser r e) where+ (<!>) = (<|>)+ many p = Prelude.reverse <$> manyAccum (:) p+ some p = p *> many p+instance Plus (Parser r e) where zero = empty+instance Alternative (Parser r e) where+ empty = Parser $ \_ ee _ _ -> ee mempty+ {-# INLINE empty #-}+ Parser m <|> Parser n = Parser $ \ eo ee co ce ->+ m eo (\e -> n (\a e'-> eo a (e <> e')) (\e' -> ee (e <> e')) co ce)+ co ce+ {-# INLINE (<|>) #-}+ many p = Prelude.reverse <$> manyAccum (:) p+ {-# INLINE many #-}+ some p = (:) <$> p <*> many p++instance Semigroup (Parser r e a) where+ (<>) = (<|>)++instance Monoid (Parser r e a) where+ mappend = (<|>)+ mempty = empty++instance Bind (Parser r e) where (>>-) = (>>=)+instance Monad (Parser r e) where+ return a = Parser $ \ eo _ _ _ -> eo a mempty+ {-# INLINE return #-}+ Parser m >>= k = Parser $ \ eo ee co ce ->+ m (\a e -> unparser (k a) (\b e' -> eo b (e <> e')) (\e' -> ee (e <> e')) co ce) ee+ (\a e -> unparser (k a) (\b e' -> co b (e <> e')) (\e' -> ce (e <> e')) co ce) ce+ {-# INLINE (>>=) #-}+ (>>) = (*>)+ {-# INLINE (>>) #-}+ fail s = Parser $ \ _ ee _ _ l b8 d bs -> ee mempty { errMessage = FailErr (renderingCaret d bs) s } l b8 d bs+ {-# INLINE fail #-}+++instance MonadPlus (Parser r e) where+ mzero = empty+ mplus = (<|>)++instance MonadWriter (ErrLog e) (Parser r e) where+ tell w = Parser $ \eo _ _ _ l -> eo () mempty (l <> w)+ {-# INLINE tell #-}+ listen (Parser m) = Parser $ \eo ee co ce l ->+ m (\ a e' l' -> eo (a,l') e' (l <> l'))+ (\ e' l' -> ee e' (l <> l'))+ (\ a e' l' -> co (a,l') e' (l <> l'))+ (\ e' l' -> ce e' (l <> l'))+ mempty+ {-# INLINE listen #-}+ pass (Parser m) = Parser $ \eo ee co ce l ->+ m (\(a,p) e' l' -> eo a e' (l <> p l'))+ (\ e' l' -> ee e' (l <> l'))+ (\(a,p) e' l' -> co a e' (l <> p l'))+ (\ e' l' -> ce e' (l <> l'))+ mempty+ {-# INLINE pass #-}++manyAccum :: (a -> [a] -> [a]) -> Parser r e a -> Parser r e [a]+manyAccum acc (Parser p) = Parser $ \eo _ co ce ->+ let walk xs x _ = p manyErr (\_ -> co (acc x xs) mempty) (walk (acc x xs)) ce+ manyErr _ e l b8 d bs = ce e { errMessage = PanicErr (renderingCaret d bs) "'many' applied to a parser that accepted an empty string" } l b8 d bs+ in p manyErr (eo []) (walk []) ce++instance MonadDiagnostic e (Parser r e) where+ throwDiagnostic e@(Diagnostic _ l _ _)+ | l == Fatal || l == Panic = Parser $ \_ _ _ ce -> ce mempty { errMessage = Err e }+ | otherwise = Parser $ \_ ee _ _ -> ee mempty { errMessage = Err e }+ logDiagnostic d = Parser $ \eo _ _ _ l -> eo () mempty l { errLog = errLog l |> d }++instance MonadError (ErrState e) (Parser r e) where+ throwError m = Parser $ \_ ee _ _ -> ee m+ {-# INLINE throwError #-}+ catchError (Parser m) k = Parser $ \ eo ee co ce ->+ m eo (\e -> unparser (k e) eo ee co ce) co ce+ {-# INLINE catchError #-}++ascii :: ByteString -> Bool+ascii = Strict.all (<=0x7f)++liftIt :: It Rope a -> Parser r e a+liftIt m = Parser $ \ eo _ _ _ l b8 d bs -> do+ a <- m+ eo a mempty l b8 d bs+{-# INLINE liftIt #-}++instance MonadParser (Parser r e) where+ try (Parser m) = Parser $ \ eo ee co ce l b8 d bs -> m eo ee co (\e l' _ _ _ ->+ if fatalErr (errMessage e)+ then ce e (l <> l') b8 d bs+ else ee e (l <> l') b8 d bs+ ) l b8 d bs+ {-# INLINE try #-}+ highlightInterval h s e = Parser $ \eo _ _ _ l -> eo () mempty l { errHighlights = IntervalMap.insert s e h (errHighlights l) }+ {-# INLINE highlightInterval #-}++ skipping d = do+ m <- mark+ release $ m <> d+ {-# INLINE skipping #-}++ unexpected s = Parser $ \ _ ee _ _ l b8 d bs -> ee mempty { errMessage = FailErr (renderingCaret d bs) $ "unexpected " ++ s } l b8 d bs+ {-# INLINE unexpected #-}++ labels (Parser p) msgs = Parser $ \ eo ee -> p+ (\a e l b8 d bs ->+ eo a (if knownErr (errMessage e)+ then e { errExpected = Set.fromList (Prelude.map (:^ Caret d bs) msgs) `union` errExpected e }+ else e) l b8 d bs)+ (\e l b8 d bs -> ee e { errExpected = Set.fromList $ Prelude.map (:^ Caret d bs) msgs } l b8 d bs)+ {-# INLINE labels #-}+ line = Parser $ \eo _ _ _ l b8 d bs -> eo bs mempty l b8 d bs+ {-# INLINE line #-}+ skipMany p = () <$ manyAccum (\_ _ -> []) p+ {-# INLINE skipMany #-}+ satisfy f = Parser $ \ _ ee co _ l b8 d bs ->+ if b8 -- fast path+ then let b = columnByte d in (+ if b >= 0 && b < fromIntegral (Strict.length bs)+ then case toEnum $ fromEnum $ Strict.index bs (fromIntegral b) of+ c | not (f c) -> ee mempty l b8 d bs+ | b == fromIntegral (Strict.length bs) - 1 -> let !ddc = d <> delta c+ in join $ fillIt ( if c == '\n'+ then co c mempty l True ddc mempty+ else co c mempty l b8 ddc bs )+ (\d' bs' -> co c mempty l (ascii bs') d' bs')+ ddc+ | otherwise -> co c mempty l b8 (d <> delta c) bs+ else ee mempty { errMessage = FailErr (renderingCaret d bs) "unexpected EOF" } l b8 d bs)+ else case UTF8.uncons $ Strict.drop (fromIntegral (columnByte d)) bs of+ Nothing -> ee mempty { errMessage = FailErr (renderingCaret d bs) "unexpected EOF" } l b8 d bs+ Just (c, xs)+ | not (f c) -> ee mempty l b8 d bs+ | Strict.null xs -> let !ddc = d <> delta c+ in join $ fillIt ( if c == '\n'+ then co c mempty l True ddc mempty+ else co c mempty l b8 ddc bs)+ (\d' bs' -> co c mempty l (ascii bs') d' bs')+ ddc+ | otherwise -> co c mempty l b8 (d <> delta c) bs+ satisfy8 f = Parser $ \ _ ee co _ l b8 d bs ->+ let b = columnByte d in+ if b >= 0 && b < fromIntegral (Strict.length bs)+ then case toEnum $ fromEnum $ Strict.index bs (fromIntegral b) of+ c | not (f c) -> ee mempty l b8 d bs+ | b == fromIntegral (Strict.length bs - 1) -> let !ddc = d <> delta c+ in join $ fillIt ( if c == 10+ then co c mempty l True ddc mempty+ else co c mempty l b8 ddc bs )+ (\d' bs' -> co c mempty l (ascii bs') d' bs')+ ddc+ | otherwise -> co c mempty l b8 (d <> delta c) bs+ else ee mempty { errMessage = FailErr (renderingCaret d bs) "unexpected EOF" } l b8 d bs+ position = Parser $ \eo _ _ _ l b8 d -> eo d mempty l b8 d+ {-# INLINE position #-}+ slicedWith f p = do+ m <- position+ a <- p+ r <- position+ f a <$> liftIt (sliceIt m r)+ {-# INLINE slicedWith #-}+ lookAhead (Parser m) = Parser $ \eo ee _ ce l b8 d bs ->+ m eo ee (\a e l' _ _ _ -> eo a e (l <> l') b8 d bs) ce l b8 d bs+ {-# INLINE lookAhead #-}++instance MonadCont (Parser r e) where+ callCC f = Parser $ \ eo ee co ce l b8 d bs -> unparser (f (\a -> Parser $ \_ _ _ _ l' _ _ _ -> eo a mempty l' b8 d bs)) eo ee co ce l b8 d bs++instance MonadMark Delta (Parser r e) where+ mark = position+ {-# INLINE mark #-}+ release d' = Parser $ \_ ee co _ l b8 d bs -> do+ mbs <- rewindIt d'+ case mbs of+ Just bs' -> co () mempty l (ascii bs') d' bs'+ Nothing+ | bytes d' == bytes (rewind d) + fromIntegral (Strict.length bs) -> if near d d'+ then co () mempty l (ascii bs) d' bs+ else co () mempty l True d' mempty+ | otherwise -> ee mempty l b8 d bs++data St e a = JuSt a !(ErrState e) !(ErrLog e) !Bool !Delta !ByteString+ | NoSt !(ErrState e) !(ErrLog e) !Bool !Delta !ByteString++stepParser :: (Diagnostic e -> Diagnostic t) ->+ (ErrState e -> Highlights -> Bool -> Delta -> ByteString -> Diagnostic t) ->+ (forall r. Parser r e a) -> ErrLog e -> Bool -> Delta -> ByteString -> Step t a+stepParser yl y (Parser p) l0 b80 d0 bs0 =+ go mempty $ p ju no ju no l0 b80 d0 bs0+ where+ ju a e l b8 d bs = Pure (JuSt a e l b8 d bs)+ no e l b8 d bs = Pure (NoSt e l b8 d bs)+ go r (Pure (JuSt a _ l _ _ _)) = StepDone r (yl . addHighlights (errHighlights l) <$> errLog l) a+ go r (Pure (NoSt e l b8 d bs)) = StepFail r ((yl . addHighlights (errHighlights l) <$> errLog l) |> y e (errHighlights l) b8 d bs)+ go r (It ma k) = StepCont r (case ma of+ JuSt a _ l _ _ _ -> Success (yl . addHighlights (errHighlights l) <$> errLog l) a+ NoSt e l b8 d bs -> Failure ((yl . addHighlights (errHighlights l) <$> errLog l) |> y e (errHighlights l) b8 d bs))+ (go <*> k)++why :: Pretty e => (e -> Doc t) -> ErrState e -> Highlights -> Bool -> Delta -> ByteString -> Diagnostic (Doc t)+why pp (ErrState ss m) hs _ d bs+ | Prelude.null now = explicateWith empty m+ | knownErr m = explicateWith (char ',' <+> ex) m+ | otherwise = Diagnostic rightHere Error ex notes+ where+ ex = expect now+ ignoreBlanks = go . List.nub . List.sort where+ go [] = []+ go [""] = ["space"]+ go xs = List.filter (/= "") xs+ expect xs = text "expected:" <+> fillSep (punctuate (char ',') (Prelude.map text $ ignoreBlanks $ Prelude.map extract xs))+ (now,later) = List.partition (\x -> errLoc m == Just (delta x)) $ toList ss+ clusters = List.groupBy ((==) `on` delta) $ List.sortBy (compare `on` delta) later+ diagnoseCluster c = Diagnostic (Right $ addHighlights hs $ renderingCaret dc bsc) Note (expect c) [] where+ _ :^ Caret dc bsc = Prelude.head c+ notes = Prelude.map diagnoseCluster clusters+ rightHere = Right $ addHighlights hs $ renderingCaret d bs++ explicateWith x EmptyErr = Diagnostic rightHere Error ((text "unspecified error") <> x) notes+ explicateWith x (FailErr r s) = Diagnostic (Right $ addHighlights hs r) Error ((fillSep $ text <$> words s) <> x) notes+ explicateWith x (PanicErr r s) = Diagnostic (Right $ addHighlights hs r) Panic ((fillSep $ text <$> words s) <> x) notes+ explicateWith x (Err (Diagnostic r l e es)) = Diagnostic (addHighlights hs <$> r) l (pp e <> x) (notes ++ fmap (addHighlights hs . fmap pp) es)++ errLoc EmptyErr = Just d+ errLoc (FailErr r _) = Just $ delta r+ errLoc (PanicErr r _) = Just $ delta r+ errLoc (Err (Diagnostic (Left _) _ _ _)) = Nothing+ errLoc (Err (Diagnostic (Right r) _ _ _)) = Just $ delta r
+ src/Text/Trifecta/Parser/Result.hs view
@@ -0,0 +1,82 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Result+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Parser.Result + ( Result(..)+ ) where++import Control.Applicative+import Data.Semigroup+import Data.Foldable+import Data.Functor.Apply+import Data.Functor.Plus+import Data.Traversable+import Data.Bifunctor+import Data.Sequence as Seq+import Text.Trifecta.Diagnostic.Prim+import Text.PrettyPrint.Free+import System.Console.Terminfo.PrettyPrint++data Result e a+ = Success !(Seq (Diagnostic e)) a+ | Failure !(Seq (Diagnostic e))+ deriving Show++instance (Pretty e, Show a) => Pretty (Result e a) where+ pretty (Success xs a) + | Seq.null xs = pretty (show a)+ | otherwise = prettyList (toList xs) `above` pretty (show a)+ pretty (Failure xs) = prettyList $ toList xs++instance (PrettyTerm e, Show a) => PrettyTerm (Result e a) where+ prettyTerm (Success xs a)+ | Seq.null xs = pretty (show a)+ | otherwise = prettyTermList (toList xs) `above` pretty (show a)+ prettyTerm (Failure xs) = prettyTermList $ toList xs++instance Functor (Result e) where+ fmap f (Success xs a) = Success xs (f a)+ fmap _ (Failure xs) = Failure xs++instance Bifunctor Result where+ bimap f g (Success xs a) = Success (fmap (fmap f) xs) (g a)+ bimap f _ (Failure xs) = Failure (fmap (fmap f) xs)++instance Foldable (Result e) where+ foldMap f (Success _ a) = f a+ foldMap _ (Failure _) = mempty++instance Traversable (Result e) where+ traverse f (Success xs a) = Success xs <$> f a+ traverse _ (Failure xs) = pure $ Failure xs++instance Applicative (Result e) where+ pure = Success mempty+ Success xs f <*> Success ys a = Success (xs <> ys) (f a)+ Success xs _ <*> Failure ys = Failure (xs <> ys)+ Failure xs <*> Success ys _ = Failure (xs <> ys)+ Failure xs <*> Failure ys = Failure (xs <> ys)++instance Apply (Result e) where+ (<.>) = (<*>)++instance Alt (Result e) where+ Failure xs <!> Failure ys = Failure (xs <> ys)+ Success xs a <!> Success ys _ = Success (xs <> ys) a+ Success xs a <!> Failure ys = Success (xs <> ys) a+ Failure xs <!> Success ys a = Success (xs <> ys) a++instance Plus (Result e) where+ zero = Failure mempty++instance Alternative (Result e) where + (<|>) = (<!>)+ empty = zero
+ src/Text/Trifecta/Parser/Rich.hs view
@@ -0,0 +1,26 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Rich+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Parser.Rich+ ( Rich+ , rich+ ) where++import Control.Monad (liftM)+import Text.Trifecta.Layout+import Text.Trifecta.Language+import Text.Trifecta.Language.Prim+import Text.Trifecta.Literate++type Rich m = Layout (Language (Literate m))++rich :: Monad m => LiterateState -> LanguageDef m -> Rich m a -> m (a, LiterateState)+rich lit def p = runLiterate (runLanguage (fst `liftM` runLayout p defaultLayoutState) (liftLanguageDef (liftLanguageDef def))) lit
+ src/Text/Trifecta/Parser/Step.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE FlexibleContexts #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Step+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Parser.Step + ( Step(..)+ , feed+ , starve+ , stepResult+ ) where++import Data.Bifunctor+import Data.Semigroup.Reducer+import Data.Sequence+import Text.Trifecta.Rope.Prim+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Parser.Result++data Step e a+ = StepDone !Rope !(Seq (Diagnostic e)) a+ | StepFail !Rope !(Seq (Diagnostic e))+ | StepCont !Rope (Result e a) (Rope -> Step e a)++instance (Show e, Show a) => Show (Step e a) where+ showsPrec d (StepDone r xs a) = showParen (d > 10) $ + showString "StepDone " . showsPrec 11 r . showChar ' ' . showsPrec 11 xs . showChar ' ' . showsPrec 11 a+ showsPrec d (StepFail r xs) = showParen (d > 10) $ + showString "StepFail " . showsPrec 11 r . showChar ' ' . showsPrec 11 xs+ showsPrec d (StepCont r fin _) = showParen (d > 10) $ + showString "StepCont " . showsPrec 11 r . showChar ' ' . showsPrec 11 fin . showString " ..."+ +instance Functor (Step e) where+ fmap f (StepDone r xs a) = StepDone r xs (f a)+ fmap _ (StepFail r xs) = StepFail r xs+ fmap f (StepCont r z k) = StepCont r (fmap f z) (fmap f . k)++instance Bifunctor Step where+ bimap f g (StepDone r xs a) = StepDone r (fmap (fmap f) xs) (g a)+ bimap f _ (StepFail r xs) = StepFail r (fmap (fmap f) xs)+ bimap f g (StepCont r z k) = StepCont r (bimap f g z) (bimap f g . k)++feed :: Reducer t Rope => t -> Step e r -> Step e r+feed t (StepDone r xs a) = StepDone (snoc r t) xs a+feed t (StepFail r xs) = StepFail (snoc r t) xs+feed t (StepCont r _ k) = k (snoc r t)++starve :: Step e a -> Result e a+starve (StepDone _ xs a) = Success xs a+starve (StepFail _ xs) = Failure xs+starve (StepCont _ z _) = z++stepResult :: Rope -> Result e a -> Step e a+stepResult r (Success xs a) = StepDone r xs a+stepResult r (Failure xs) = StepFail r xs+
+ src/Text/Trifecta/Parser/Token.hs view
@@ -0,0 +1,24 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Token+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Parser.Token+ ( module Text.Trifecta.Parser.Token.Combinators+ -- * Text.Trifecta.Parser.Token.Prim+ , decimal+ , hexadecimal+ , octal+ ) where++import Text.Trifecta.Parser.Token.Prim+import Text.Trifecta.Parser.Token.Combinators++-- expected to be imported manually+-- import Text.Trifecta.Parser.Token.Style
+ src/Text/Trifecta/Parser/Token/Combinators.hs view
@@ -0,0 +1,197 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Token.Combinators+-- Copyright : (c) Edward Kmett 2011,+-- (c) Daan Leijen 1999-2001+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+-- +-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Token.Combinators+ ( lexeme+ , charLiteral+ , stringLiteral+ , natural+ , integer+ , double+ , naturalOrDouble+ , symbol+ , symbolic+ , parens+ , braces+ , angles+ , brackets+ , comma+ , colon+ , dot+ , semiSep+ , semiSep1+ , commaSep+ , commaSep1+ ) where++import Data.ByteString as Strict hiding (map, zip, foldl, foldr)+import Control.Applicative+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Parser.Token.Prim+import Text.Trifecta.Highlight.Prim++-- | @lexeme p@ first applies parser @p@ and then the 'whiteSpace'+-- parser, returning the value of @p@. Every lexical+-- token (lexeme) is defined using @lexeme@, this way every parse+-- starts at a point without white space. Parsers that use @lexeme@ are+-- called /lexeme/ parsers in this document.+--+-- The only point where the 'whiteSpace' parser should be+-- called explicitly is the start of the main parser in order to skip+-- any leading white space.+--+-- > mainParser = do { whiteSpace+-- > ; ds <- many (lexeme digit)+-- > ; eof+-- > ; return (sum ds)+-- > }+lexeme :: MonadParser m => m a -> m a+lexeme p = p <* whiteSpace++-- | This lexeme parser parses a single literal character. Returns the+-- literal character value. This parsers deals correctly with escape+-- sequences. The literal character is parsed according to the grammar+-- rules defined in the Haskell report (which matches most programming+-- languages quite closely). +charLiteral :: MonadParser m => m Char+charLiteral = lexeme charLiteral'++-- | This lexeme parser parses a literal string. Returns the literal+-- string value. This parsers deals correctly with escape sequences and+-- gaps. The literal string is parsed according to the grammar rules+-- defined in the Haskell report (which matches most programming+-- languages quite closely). ++stringLiteral :: MonadParser m => m String+stringLiteral = lexeme stringLiteral'++-- | This lexeme parser parses a natural number (a positive whole+-- number). Returns the value of the number. The number can be+-- specified in 'decimal', 'hexadecimal' or+-- 'octal'. The number is parsed according to the grammar+-- rules in the Haskell report. ++natural :: MonadParser m => m Integer+natural = lexeme natural'++-- | This lexeme parser parses an integer (a whole number). This parser+-- is like 'natural' except that it can be prefixed with+-- sign (i.e. \'-\' or \'+\'). Returns the value of the number. The+-- number can be specified in 'decimal', 'hexadecimal'+-- or 'octal'. The number is parsed according+-- to the grammar rules in the Haskell report. ++integer :: MonadParser m => m Integer+integer = lexeme int <?> "integer"+ where+ sign = negate <$ char '-'+ <|> id <$ char '+'+ <|> pure id+ int = lexeme (highlight Operator sign) <*> natural'++-- | This lexeme parser parses a floating point value. Returns the value+-- of the number. The number is parsed according to the grammar rules+-- defined in the Haskell report. ++double :: MonadParser m => m Double+double = lexeme double'++-- | This lexeme parser parses either 'natural' or a 'float'.+-- Returns the value of the number. This parsers deals with+-- any overlap in the grammar rules for naturals and floats. The number+-- is parsed according to the grammar rules defined in the Haskell report. ++naturalOrDouble :: MonadParser m => m (Either Integer Double)+naturalOrDouble = lexeme naturalOrDouble'++-- | Lexeme parser @symbol s@ parses 'string' @s@ and skips+-- trailing white space. ++symbol :: MonadParser m => ByteString -> m ByteString+symbol name = lexeme (highlight Symbol (byteString name))++-- | Lexeme parser @symbolic s@ parses 'char' @s@ and skips+-- trailing white space. ++symbolic :: MonadParser m => Char -> m Char+symbolic name = lexeme (highlight Symbol (char name))++-- | Lexeme parser @parens p@ parses @p@ enclosed in parenthesis,+-- returning the value of @p@.++parens :: MonadParser m => m a -> m a+parens = nesting . between (symbolic '(') (symbolic ')')++-- | Lexeme parser @braces p@ parses @p@ enclosed in braces (\'{\' and+-- \'}\'), returning the value of @p@. ++braces :: MonadParser m => m a -> m a+braces = nesting . between (symbolic '{') (symbolic '}')++-- | Lexeme parser @angles p@ parses @p@ enclosed in angle brackets (\'\<\'+-- and \'>\'), returning the value of @p@. ++angles :: MonadParser m => m a -> m a+angles = nesting . between (symbolic '<') (symbolic '>')++-- | Lexeme parser @brackets p@ parses @p@ enclosed in brackets (\'[\'+-- and \']\'), returning the value of @p@. ++brackets :: MonadParser m => m a -> m a+brackets = nesting . between (symbolic '[') (symbolic ']')++-- | Lexeme parser @comma@ parses the character \',\' and skips any+-- trailing white space. Returns the string \",\". ++comma :: MonadParser m => m Char+comma = symbolic ','++-- | Lexeme parser @colon@ parses the character \':\' and skips any+-- trailing white space. Returns the string \":\". ++colon :: MonadParser m => m Char+colon = symbolic ':'++-- | Lexeme parser @dot@ parses the character \'.\' and skips any+-- trailing white space. Returns the string \".\". ++dot :: MonadParser m => m Char+dot = symbolic '.'++-- | Lexeme parser @semiSep p@ parses /zero/ or more occurrences of @p@+-- separated by 'semi'. Returns a list of values returned by+-- @p@.++semiSep :: MonadParser m => m a -> m [a]+semiSep p = sepBy p semi++-- | Lexeme parser @semiSep1 p@ parses /one/ or more occurrences of @p@+-- separated by 'semi'. Returns a list of values returned by @p@. ++semiSep1 :: MonadParser m => m a -> m [a]+semiSep1 p = sepBy1 p semi++-- | Lexeme parser @commaSep p@ parses /zero/ or more occurrences of+-- @p@ separated by 'comma'. Returns a list of values returned+-- by @p@. ++commaSep :: MonadParser m => m a -> m [a]+commaSep p = sepBy p comma++-- | Lexeme parser @commaSep1 p@ parses /one/ or more occurrences of+-- @p@ separated by 'comma'. Returns a list of values returned+-- by @p@. ++commaSep1 :: MonadParser m => m a -> m [a]+commaSep1 p = sepBy p comma
+ src/Text/Trifecta/Parser/Token/Prim.hs view
@@ -0,0 +1,217 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Token.Prim+-- Copyright : (c) Edward Kmett 2011,+-- (c) Daan Leijen 1999-2001+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Token.Prim+ ( charLiteral'+ , characterChar+ , stringLiteral'+ , natural'+ , integer'+ , double'+ , naturalOrDouble'+ , decimal+ , hexadecimal+ , octal+ ) where++import Data.Char (digitToInt)+import Data.Foldable+import Control.Applicative+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Highlight.Prim++-- | This parser parses a single literal character. Returns the+-- literal character value. This parsers deals correctly with escape+-- sequences. The literal character is parsed according to the grammar+-- rules defined in the Haskell report (which matches most programming+-- languages quite closely).+--+-- This parser does NOT swallow trailing whitespace.+charLiteral' :: MonadParser m => m Char+charLiteral' = highlight CharLiteral (between (char '\'') (char '\'' <?> "end of character") characterChar)+ <?> "character"++characterChar, charEscape, charLetter :: MonadParser m => m Char+characterChar = charLetter <|> charEscape+ <?> "literal character"+charEscape = highlight EscapeCode $ char '\\' *> escapeCode+charLetter = satisfy (\c -> (c /= '\'') && (c /= '\\') && (c > '\026'))++-- | This parser parses a literal string. Returns the literal+-- string value. This parsers deals correctly with escape sequences and+-- gaps. The literal string is parsed according to the grammar rules+-- defined in the Haskell report (which matches most programming+-- languages quite closely).+--+-- This parser does NOT swallow trailing whitespace+stringLiteral' :: MonadParser m => m String+stringLiteral' = highlight StringLiteral lit where+ lit = Prelude.foldr (maybe id (:)) "" <$> between (char '"') (char '"' <?> "end of string") (many stringChar)+ <?> "literal string"+ stringChar = Just <$> stringLetter+ <|> stringEscape+ <?> "string character"+ stringLetter = satisfy (\c -> (c /= '"') && (c /= '\\') && (c > '\026'))++ stringEscape = highlight EscapeCode $ char '\\' *> esc where+ esc = Nothing <$ escapeGap+ <|> Nothing <$ escapeEmpty+ <|> Just <$> escapeCode+ escapeEmpty = char '&'+ escapeGap = do skipSome space+ char '\\' <?> "end of string gap"++escapeCode :: MonadParser m => m Char+escapeCode = (charEsc <|> charNum <|> charAscii <|> charControl) <?> "escape code"+ where+ charControl = (\c -> toEnum (fromEnum c - fromEnum 'A')) <$> (char '^' *> upper)+ charNum = toEnum . fromInteger <$> num where+ num = decimal+ <|> (char 'o' *> number 8 octDigit)+ <|> (char 'x' *> number 16 hexDigit)+ charEsc = choice $ parseEsc <$> escMap+ parseEsc (c,code) = code <$ char c+ escMap = zip ("abfnrtv\\\"\'") ("\a\b\f\n\r\t\v\\\"\'")+ charAscii = choice $ parseAscii <$> asciiMap+ parseAscii (asc,code) = try $ code <$ string asc+ asciiMap = zip (ascii3codes ++ ascii2codes) (ascii3 ++ ascii2)+ ascii2codes, ascii3codes :: [String]+ ascii2codes = [ "BS","HT","LF","VT","FF","CR","SO"+ , "SI","EM","FS","GS","RS","US","SP"]+ ascii3codes = ["NUL","SOH","STX","ETX","EOT","ENQ","ACK"+ ,"BEL","DLE","DC1","DC2","DC3","DC4","NAK"+ ,"SYN","ETB","CAN","SUB","ESC","DEL"]+ ascii2, ascii3 :: [Char]+ ascii2 = ['\BS','\HT','\LF','\VT','\FF','\CR','\SO','\SI'+ ,'\EM','\FS','\GS','\RS','\US','\SP']+ ascii3 = ['\NUL','\SOH','\STX','\ETX','\EOT','\ENQ','\ACK'+ ,'\BEL','\DLE','\DC1','\DC2','\DC3','\DC4','\NAK'+ ,'\SYN','\ETB','\CAN','\SUB','\ESC','\DEL']+++-- | This parser parses a natural number (a positive whole+-- number). Returns the value of the number. The number can be+-- specified in 'decimal', 'hexadecimal' or+-- 'octal'. The number is parsed according to the grammar+-- rules in the Haskell report.+--+-- This parser does NOT swallow trailing whitespace.+natural' :: MonadParser m => m Integer+natural' = highlight Number nat <?> "natural"++number :: MonadParser m => Integer -> m Char -> m Integer+number base baseDigit = do+ digits <- some baseDigit+ return $! foldl' (\x d -> base*x + toInteger (digitToInt d)) 0 digits++-- | This parser parses an integer (a whole number). This parser+-- is like 'natural' except that it can be prefixed with+-- sign (i.e. \'-\' or \'+\'). Returns the value of the number. The+-- number can be specified in 'decimal', 'hexadecimal'+-- or 'octal'. The number is parsed according+-- to the grammar rules in the Haskell report.+--+-- This parser does NOT swallow trailing whitespace.+--+-- Also, unlike the 'integer' parser, this parser does not admit spaces+-- between the sign and the number.++integer' :: MonadParser m => m Integer+integer' = int <?> "integer"++sign :: MonadParser m => m (Integer -> Integer)+sign = highlight Operator+ $ negate <$ char '-'+ <|> id <$ char '+'+ <|> pure id++int :: MonadParser m => m Integer+int = {-lexeme-} sign <*> highlight Number nat+nat, zeroNumber :: MonadParser m => m Integer+nat = zeroNumber <|> decimal+zeroNumber = char '0' *> (hexadecimal <|> octal <|> decimal <|> return 0) <?> ""++-- | This parser parses a floating point value. Returns the value+-- of the number. The number is parsed according to the grammar rules+-- defined in the Haskell report.+--+-- This parser does NOT swallow trailing whitespace.++double' :: MonadParser m => m Double+double' = highlight Number floating <?> "double"++floating :: MonadParser m => m Double+floating = decimal >>= fractExponent++fractExponent :: MonadParser m => Integer -> m Double+fractExponent n = (\fract expo -> (fromInteger n + fract) * expo) <$> fraction <*> option 1.0 exponent'+ <|> (fromInteger n *) <$> exponent' where+ fraction = Prelude.foldr op 0.0 <$> (char '.' *> (some digit <?> "fraction"))+ op d f = (f + fromIntegral (digitToInt d))/10.0+ exponent' = do+ _ <- oneOf "eE"+ f <- sign+ e <- decimal <?> "exponent"+ return (power (f e))+ <?> "exponent"+ power e+ | e < 0 = 1.0/power(-e)+ | otherwise = fromInteger (10^e)+++-- | This parser parses either 'natural' or a 'double'.+-- Returns the value of the number. This parsers deals with+-- any overlap in the grammar rules for naturals and floats. The number+-- is parsed according to the grammar rules defined in the Haskell report.+--+-- This parser does NOT swallow trailing whitespace.++naturalOrDouble' :: MonadParser m => m (Either Integer Double)+naturalOrDouble' = highlight Number natDouble <?> "number"++natDouble, zeroNumFloat, decimalFloat :: MonadParser m => m (Either Integer Double)+natDouble+ = char '0' *> zeroNumFloat+ <|> decimalFloat+zeroNumFloat+ = Left <$> (hexadecimal <|> octal)+ <|> decimalFloat+ <|> fractFloat 0+ <|> return (Left 0)+decimalFloat = do+ n <- decimal+ option (Left n) (fractFloat n)++fractFloat :: MonadParser m => Integer -> m (Either Integer Double)+fractFloat n = Right <$> fractExponent n++-- | Parses a positive whole number in the decimal system. Returns the+-- value of the number.++decimal :: MonadParser m => m Integer+decimal = number 10 digit++-- | Parses a positive whole number in the hexadecimal system. The number+-- should be prefixed with \"x\" or \"X\". Returns the value of the+-- number.++hexadecimal :: MonadParser m => m Integer+hexadecimal = oneOf "xX" *> number 16 hexDigit++-- | Parses a positive whole number in the octal system. The number+-- should be prefixed with \"o\" or \"O\". Returns the value of the+-- number.++octal :: MonadParser m => m Integer+octal = oneOf "oO" *> number 8 octDigit
+ src/Text/Trifecta/Parser/Token/Style.hs view
@@ -0,0 +1,74 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Token.Style+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+--+-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Token.Style+ ( CommentStyle(..)+ , emptyCommentStyle+ , javaCommentStyle+ , haskellCommentStyle+ , buildSomeSpaceParser+ ) where++import Control.Applicative+import Data.List (nub)+import qualified Data.ByteString.Char8 as B+import Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Highlight.Prim++data CommentStyle = CommentStyle+ { commentStart :: String+ , commentEnd :: String+ , commentLine :: String+ , commentNesting :: Bool+ }++emptyCommentStyle, javaCommentStyle, haskellCommentStyle :: CommentStyle+emptyCommentStyle = CommentStyle "" "" "" True+javaCommentStyle = CommentStyle "/*" "*/" "//" True+haskellCommentStyle = CommentStyle "{-" "-}" "--" True++-- | Use this to easily build the definition of whiteSpace for your MonadParser+-- given a comment style and an underlying someWhiteSpace parser+buildSomeSpaceParser :: MonadParser m => m () -> CommentStyle -> m ()+buildSomeSpaceParser simpleSpace (CommentStyle startStyle endStyle lineStyle nestingStyle)+ | noLine && noMulti = skipSome (simpleSpace <?> "")+ | noLine = skipSome (simpleSpace <|> multiLineComment <?> "")+ | noMulti = skipSome (simpleSpace <|> oneLineComment <?> "")+ | otherwise = skipSome (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")+ where+ noLine = null lineStyle+ noMulti = null startStyle+ oneLineComment = highlight Comment $ do+ _ <- try $ string lineStyle+ r <- restOfLine+ let b = B.length r+ skipping $ if b /= 0 && B.last r == '\n' then Lines 1 0 (fromIntegral b) 0 else delta r+ multiLineComment = highlight Comment $ do+ _ <- try $ string startStyle+ inComment+ inComment+ | nestingStyle = inCommentMulti+ | otherwise = inCommentSingle+ inCommentMulti+ = () <$ try (string endStyle)+ <|> multiLineComment *> inCommentMulti+ <|> skipSome (noneOf startEnd) *> inCommentMulti+ <|> oneOf startEnd *> inCommentMulti+ <?> "end of comment"+ startEnd = nub (endStyle ++ startStyle)+ inCommentSingle+ = () <$ try (string endStyle)+ <|> skipSome (noneOf startEnd) *> inCommentSingle+ <|> oneOf startEnd *> inCommentSingle+ <?> "end of comment"
+ src/Text/Trifecta/Rope.hs view
@@ -0,0 +1,26 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Rope+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Rope + ( Rope, rope, strands+ -- * Strands of a rope+ , Strand(..), strand+ -- * Properties+ , Delta(..)+ , HasDelta(..)+ , HasBytes(..)+ , HighlightedRope(..)+ ) where++import Text.Trifecta.Rope.Prim+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Highlighted
+ src/Text/Trifecta/Rope/Bytes.hs view
@@ -0,0 +1,27 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Rope.Bytes+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Rope.Bytes+ ( HasBytes(..)+ ) where++import Data.ByteString as Strict+import Data.FingerTree+import Data.Int (Int64)++class HasBytes t where+ bytes :: t -> Int64++instance HasBytes ByteString where+ bytes = fromIntegral . Strict.length++instance (Measured v a, HasBytes v) => HasBytes (FingerTree v a) where+ bytes = bytes . measure
+ src/Text/Trifecta/Rope/Delta.hs view
@@ -0,0 +1,169 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Rope.Delta+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Rope.Delta+ ( Delta(..)+ , HasDelta(..)+ , nextTab+ , rewind+ , near+ , column+ , columnByte+ ) where++import Control.Applicative+import Data.Semigroup+import Data.Hashable+import Data.Int+import Data.Word+import Data.Foldable+import Data.Function (on)+import Data.FingerTree hiding (empty)+import Data.ByteString hiding (empty)+import qualified Data.ByteString.UTF8 as UTF8+import Text.Trifecta.Rope.Bytes+import Text.PrettyPrint.Free hiding (column)+import System.Console.Terminfo.PrettyPrint++data Delta+ = Columns {-# UNPACK #-} !Int64 -- the number of characters+ {-# UNPACK #-} !Int64 -- the number of bytes+ | Tab {-# UNPACK #-} !Int64 -- the number of characters before the tab+ {-# UNPACK #-} !Int64 -- the number of characters after the tab+ {-# UNPACK #-} !Int64 -- the number of bytes+ | Lines {-# UNPACK #-} !Int64 -- the number of newlines contained+ {-# UNPACK #-} !Int64 -- the number of characters since the last newline+ {-# UNPACK #-} !Int64 -- number of bytes+ {-# UNPACK #-} !Int64 -- the number of bytes since the last newline+ | Directed !ByteString -- current file name+ {-# UNPACK #-} !Int64 -- the number of lines since the last line directive+ {-# UNPACK #-} !Int64 -- the number of characters since the last newline+ {-# UNPACK #-} !Int64 -- number of bytes+ {-# UNPACK #-} !Int64 -- the number of bytes since the last newline+ deriving Show++instance Eq Delta where+ (==) = (==) `on` bytes++instance Ord Delta where+ compare = compare `on` bytes++instance (HasDelta l, HasDelta r) => HasDelta (Either l r) where+ delta = either delta delta++instance Pretty Delta where+ pretty p = prettyTerm p *> empty++instance PrettyTerm Delta where+ prettyTerm d = case d of+ Columns c _ -> k f 0 c+ Tab x y _ -> k f 0 (nextTab x + y)+ Lines l c _ _ -> k f l c+ Directed fn l c _ _ -> k (UTF8.toString fn) l c+ where+ k fn ln cn = bold (pretty fn) <> char ':' <> bold (int64 (ln+1)) <> char ':' <> bold (int64 (cn+1))+ f = "(interactive)"++int64 :: Int64 -> Doc e+int64 = pretty . show++column :: HasDelta t => t -> Int64+column t = case delta t of+ Columns c _ -> c+ Tab b a _ -> nextTab b + a+ Lines _ c _ _ -> c+ Directed _ _ c _ _ -> c+{-# INLINE column #-}++columnByte :: Delta -> Int64+columnByte (Columns _ b) = b+columnByte (Tab _ _ b) = b+columnByte (Lines _ _ _ b) = b+columnByte (Directed _ _ _ _ b) = b+{-# INLINE columnByte #-}++instance HasBytes Delta where+ bytes (Columns _ b) = b+ bytes (Tab _ _ b) = b+ bytes (Lines _ _ b _) = b+ bytes (Directed _ _ _ b _) = b++instance Hashable Delta where+ hash (Columns c a) = 0 `hashWithSalt` c `hashWithSalt` a+ hash (Tab x y a) = 1 `hashWithSalt` x `hashWithSalt` y `hashWithSalt` a+ hash (Lines l c b a) = 2 `hashWithSalt` l `hashWithSalt` c `hashWithSalt` b `hashWithSalt` a+ hash (Directed p l c b a) = 3 `hashWithSalt` p `hashWithSalt` l `hashWithSalt` c `hashWithSalt` b `hashWithSalt` a++instance Monoid Delta where+ mempty = Columns 0 0+ mappend = (<>)++instance Semigroup Delta where+ Columns c a <> Columns d b = Columns (c + d) (a + b)+ Columns c a <> Tab x y b = Tab (c + x) y (a + b)+ Columns _ a <> Lines l c t a' = Lines l c (t + a) a'+ Columns _ a <> Directed p l c t a' = Directed p l c (t + a) a'+ Lines l c t a <> Columns d b = Lines l (c + d) (t + b) (a + b)+ Lines l c t a <> Tab x y b = Lines l (nextTab (c + x) + y) (t + b) (a + b)+ Lines l _ t _ <> Lines m d t' b = Lines (l + m) d (t + t') b+ Lines _ _ t _ <> Directed p l c t' a = Directed p l c (t + t') a+ Tab x y a <> Columns d b = Tab x (y + d) (a + b)+ Tab x y a <> Tab x' y' b = Tab x (nextTab (y + x') + y') (a + b)+ Tab _ _ a <> Lines l c t a' = Lines l c (t + a ) a'+ Tab _ _ a <> Directed p l c t a' = Directed p l c (t + a ) a'+ Directed p l c t a <> Columns d b = Directed p l (c + d) (t + b ) (a + b)+ Directed p l c t a <> Tab x y b = Directed p l (nextTab (c + x) + y) (t + b ) (a + b)+ Directed p l _ t _ <> Lines m d t' b = Directed p (l + m) d (t + t') b+ Directed _ _ _ t _ <> Directed p l c t' b = Directed p l c (t + t') b+ +nextTab :: Int64 -> Int64+nextTab x = x + (8 - mod x 8)+{-# INLINE nextTab #-}++rewind :: Delta -> Delta+rewind (Lines n _ b d) = Lines n 0 (b - d) 0+rewind (Directed p n _ b d) = Directed p n 0 (b - d) 0+rewind _ = Columns 0 0+{-# INLINE rewind #-}++near :: (HasDelta s, HasDelta t) => s -> t -> Bool+near s t = rewind (delta s) == rewind (delta t)+{-# INLINE near #-}++class HasDelta t where+ delta :: t -> Delta++instance HasDelta Delta where+ delta = id++instance HasDelta Char where+ delta '\t' = Tab 0 0 1+ delta '\n' = Lines 1 0 1 0+ delta c+ | o <= 0x7f = Columns 1 1+ | o <= 0x7ff = Columns 1 2+ | o <= 0xffff = Columns 1 3+ | otherwise = Columns 1 4+ where o = fromEnum c++instance HasDelta Word8 where+ delta 9 = Tab 0 0 1+ delta 10 = Lines 1 0 1 0+ delta n+ | n <= 0x7f = Columns 1 1+ | n >= 0xc0 && n <= 0xf4 = Columns 1 1+ | otherwise = Columns 0 1++instance HasDelta ByteString where+ delta = foldMap delta . unpack++instance (Measured v a, HasDelta v) => HasDelta (FingerTree v a) where+ delta = delta . measure
+ src/Text/Trifecta/Rope/Highlighted.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Rope.Highlighted+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Rope.Highlighted+ ( HighlightedRope(..)+ ) where++import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.ByteString.Lazy.UTF8 as LazyUTF8+import Data.Foldable as F+import Data.Int (Int64)+import Text.Trifecta.IntervalMap as IM+import Data.Key hiding ((!))+import Data.List (sort)+import Data.Semigroup+import Data.Semigroup.Union+import Prelude hiding (head)+import System.Console.Terminfo.PrettyPrint+import Text.Blaze+import Text.Blaze.Internal+import Text.Blaze.Html5 hiding (b,i)+import Text.Blaze.Html5.Attributes hiding (title)+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Prim+import Text.Trifecta.Highlight.Class+import Text.Trifecta.Highlight.Effects+import Text.Trifecta.Highlight.Prim+import Text.PrettyPrint.Free++data HighlightedRope = HighlightedRope + { ropeHighlights :: !Highlights+ , ropeContent :: {-# UNPACK #-} !Rope + }++instance HasDelta HighlightedRope where+ delta = delta . ropeContent++instance HasBytes HighlightedRope where+ bytes = bytes . ropeContent++instance Semigroup HighlightedRope where+ HighlightedRope h bs <> HighlightedRope h' bs' = HighlightedRope (h `union` IM.offset (delta bs) h') (bs <> bs')++instance Monoid HighlightedRope where+ mappend = (<>) + mempty = HighlightedRope mempty mempty++instance Highlightable HighlightedRope where+ addHighlights h (HighlightedRope h' r) = HighlightedRope (h `union` h') r++data Located a = a :@ {-# UNPACK #-} !Int64+infix 5 :@+instance Eq (Located a) where+ _ :@ m == _ :@ n = m == n+instance Ord (Located a) where+ compare (_ :@ m) (_ :@ n) = compare m n++instance ToHtml HighlightedRope where+ toHtml (HighlightedRope intervals r) = pre $ go 0 lbs effects where + lbs = L.fromChunks [bs | Strand bs _ <- F.toList (strands r)]+ ln no = a ! name (toValue $ "line-" ++ show no) $ Empty+ effects = sort $ [ i | (Interval lo hi, tok) <- intersections mempty (delta r) intervals+ , i <- [ (Leaf "span" "<span" ">" ! class_ (toValue $ show tok)) :@ bytes lo+ , preEscapedString "</span>" :@ bytes hi+ ]+ ] ++ mapWithKey (\k i -> ln k :@ i) (L.elemIndices '\n' lbs)+ go _ cs [] = unsafeLazyByteString cs+ go b cs ((eff :@ eb) : es) + | eb <= b = eff >> go b cs es + | otherwise = unsafeLazyByteString om >> go eb nom es+ where (om,nom) = L.splitAt (fromIntegral (eb - b)) cs++instance Pretty HighlightedRope where+ pretty (HighlightedRope _ r) = hsep $ [ pretty bs | Strand bs _ <- F.toList (strands r)]++instance PrettyTerm HighlightedRope where+ prettyTerm (HighlightedRope intervals r) = go 0 lbs effects where+ lbs = L.fromChunks [bs | Strand bs _ <- F.toList (strands r)]+ effects = sort $ [ i | (Interval lo hi, tok) <- intersections mempty (delta r) intervals+ , i <- [ pushToken tok :@ bytes lo+ , popToken tok :@ bytes hi+ ]+ ]+ go _ cs [] = prettyTerm (LazyUTF8.toString cs)+ go b cs ((eff :@ eb) : es) + | eb <= b = eff <> go b cs es + | otherwise = prettyTerm (LazyUTF8.toString om) <> go eb nom es+ where (om,nom) = L.splitAt (fromIntegral (eb - b)) cs
+ src/Text/Trifecta/Rope/Prim.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, BangPatterns, PatternGuards #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Rope.Prim+-- Copyright : (C) 2011 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Rope.Prim+ ( Rope(..)+ , rope+ , Strand(..)+ , strand+ , strands+ , grabRest+ , grabLine+ ) where++import Data.Semigroup+import Data.Semigroup.Reducer+import Data.ByteString (ByteString)+import qualified Data.ByteString as Strict+import qualified Data.ByteString.Lazy as Lazy+import qualified Data.ByteString.UTF8 as UTF8+import Data.FingerTree as FingerTree+import Data.Foldable (toList)+import Data.Hashable+import Data.Int (Int64)+import Text.Trifecta.Util.Combinators as Util+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta++data Strand+ = Strand {-# UNPACK #-} !ByteString !Delta+ | LineDirective {-# UNPACK #-} !ByteString {-# UNPACK #-} !Int64+ deriving Show++strand :: ByteString -> Strand+strand bs = Strand bs (delta bs)++instance Measured Delta Strand where+ measure (Strand _ s) = delta s+ measure (LineDirective p l) = delta (Directed p l 0 0 0)++instance Hashable Strand where+ hash (Strand h _) = hashWithSalt 0 h+ hash (LineDirective p l) = hash l `hashWithSalt` p++instance HasDelta Strand where+ delta = measure++instance HasBytes Strand where+ bytes (Strand _ d) = bytes d+ bytes _ = 0++data Rope = Rope !Delta !(FingerTree Delta Strand) deriving Show++rope :: FingerTree Delta Strand -> Rope+rope r = Rope (measure r) r++strands :: Rope -> FingerTree Delta Strand+strands (Rope _ r) = r++-- | grab a the contents of a rope from a given location up to a newline+grabRest :: Delta -> Rope -> r -> (Delta -> Lazy.ByteString -> r) -> r+grabRest i t kf ks = trim (delta l) (bytes i - bytes l) (toList r) where+ trim j 0 (Strand h _ : xs) = go j h xs+ trim _ k (Strand h _ : xs) = go i (Strict.drop (fromIntegral k) h) xs+ trim j k (p : xs) = trim (j <> delta p) k xs + trim _ _ [] = kf+ go j h s = ks j $ Lazy.fromChunks $ h : [ a | Strand a _ <- s ]+ (l, r) = FingerTree.split (\b -> bytes b > bytes i) $ strands t++-- | grab a the contents of a rope from a given location up to a newline+grabLine :: Delta -> Rope -> r -> (Delta -> Strict.ByteString -> r) -> r+grabLine i t kf ks = grabRest i t kf $ \c -> ks c . Util.fromLazy . Util.takeLine++instance HasBytes Rope where+ bytes = bytes . measure++instance HasDelta Rope where+ delta = measure++instance Measured Delta Rope where+ measure (Rope s _) = s++instance Monoid Rope where+ mempty = Rope mempty mempty+ mappend = (<>)++instance Semigroup Rope where+ Rope mx x <> Rope my y = Rope (mx <> my) (x `mappend` y)++instance Reducer Rope Rope where+ unit = id++instance Reducer Strand Rope where+ unit s = rope (FingerTree.singleton s)+ cons s (Rope mt t) = Rope (delta s `mappend` mt) (s <| t)+ snoc (Rope mt t) !s = Rope (mt `mappend` delta s) (t |> s)++instance Reducer Strict.ByteString Rope where+ unit = unit . strand+ cons = cons . strand+ snoc r = snoc r . strand++instance Reducer [Char] Rope where+ unit = unit . strand . UTF8.fromString+ cons = cons . strand . UTF8.fromString+ snoc r = snoc r . strand . UTF8.fromString
+ src/Text/Trifecta/Util/Array.hs view
@@ -0,0 +1,378 @@+{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Util.Array+-- Copyright : Edward Kmett 2011+-- Johan Tibell 2011+-- License : BSD3+--+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : unknown+--+-- Fast zero based arrays, based on the implementation in the HAMT-branch of+-- unordered-containers+-----------------------------------------------------------------------------+module Text.Trifecta.Util.Array+ ( Array+ , MArray++ -- * Creation+ , new+ , new_+ , empty+ , singleton++ -- * Basic interface+ , length+ , lengthM+ , read+ , write+ , index+ , index_+ , indexM_+ , update+ , insert+ , delete++ , unsafeFreeze+ , run+ , run2+ , copy+ , copyM++ -- * Folds+ , foldl'+ , foldr++ , thaw+ , map+ , map'+ , traverse+ , filter+ ) where++import qualified Data.Traversable as Traversable+import Control.Applicative (Applicative)+import Control.DeepSeq+import Control.Monad.ST+import GHC.Exts+import GHC.ST (ST(..))+import Prelude hiding (filter, foldr, length, map, read)++------------------------------------------------------------------------++#if defined(ASSERTS)+-- This fugly hack is brought by GHC's apparent reluctance to deal+-- with MagicHash and UnboxedTuples when inferring types. Eek!+# define CHECK_BOUNDS(_func_,_len_,_k_) \+if (_k_) < 0 || (_k_) >= (_len_) then error ("Data.HashMap.Array." ++ (_func_) ++ ": bounds error, offset " ++ show (_k_) ++ ", length " ++ show (_len_)) else+# define CHECK_OP(_func_,_op_,_lhs_,_rhs_) \+if not ((_lhs_) _op_ (_rhs_)) then error ("Data.HashMap.Array." ++ (_func_) ++ ": Check failed: _lhs_ _op_ _rhs_ (" ++ show (_lhs_) ++ " vs. " ++ show (_rhs_) ++ ")") else+# define CHECK_GT(_func_,_lhs_,_rhs_) CHECK_OP(_func_,>,_lhs_,_rhs_)+# define CHECK_LE(_func_,_lhs_,_rhs_) CHECK_OP(_func_,<=,_lhs_,_rhs_)+#else+# define CHECK_BOUNDS(_func_,_len_,_k_)+# define CHECK_OP(_func_,_op_,_lhs_,_rhs_)+# define CHECK_GT(_func_,_lhs_,_rhs_)+# define CHECK_LE(_func_,_lhs_,_rhs_)+#endif++data Array a = Array {+ unArray :: !(Array# a)+#if __GLASGOW_HASKELL__ < 702+ , length :: {-# UNPACK #-} !Int+#endif+ }++#if __GLASGOW_HASKELL__ >= 702+length :: Array a -> Int+length ary = I# (sizeofArray# (unArray ary))+{-# INLINE length #-}+#endif++-- | Smart constructor+array :: Array# a -> Int -> Array a+#if __GLASGOW_HASKELL__ >= 702+array ary _n = Array ary+#else+array = Array+#endif+{-# INLINE array #-}++data MArray s a = MArray {+ unMArray :: !(MutableArray# s a)+#if __GLASGOW_HASKELL__ < 702+ , lengthM :: {-# UNPACK #-} !Int+#endif+ }++#if __GLASGOW_HASKELL__ >= 702+lengthM :: MArray s a -> Int+lengthM mary = I# (sizeofMutableArray# (unMArray mary))+{-# INLINE lengthM #-}+#endif++-- | Smart constructor+marray :: MutableArray# s a -> Int -> MArray s a+#if __GLASGOW_HASKELL__ >= 702+marray mary _n = MArray mary+#else+marray = MArray+#endif+{-# INLINE marray #-}++------------------------------------------------------------------------++instance NFData a => NFData (Array a) where+ rnf = rnfArray++rnfArray :: NFData a => Array a -> ()+rnfArray ary0 = go ary0 n0 0 where+ n0 = length ary0+ go !ary !n !i+ | i >= n = ()+ | otherwise = rnf (index ary i) `seq` go ary n (i+1)+{-# INLINE rnfArray #-}++-- | Create a new mutable array of specified size, in the specified+-- state thread, with each element containing the specified initial+-- value.+new :: Int -> a -> ST s (MArray s a)+new n@(I# n#) b =+ CHECK_GT("new",n,(0 :: Int))+ ST $ \s -> case newArray# n# b s of+ (# s', ary #) -> (# s', marray ary n #)+{-# INLINE new #-}++new_ :: Int -> ST s (MArray s a)+new_ n = new n undefinedElem++empty :: Array a+empty = run (new_ 0)++singleton :: a -> Array a+singleton x = run (new 1 x)+{-# INLINE singleton #-}++read :: MArray s a -> Int -> ST s a+read ary _i@(I# i#) = ST $ \ s ->+ CHECK_BOUNDS("read", lengthM ary, _i)+ readArray# (unMArray ary) i# s+{-# INLINE read #-}++write :: MArray s a -> Int -> a -> ST s ()+write ary _i@(I# i#) b = ST $ \ s ->+ CHECK_BOUNDS("write", lengthM ary, _i)+ case writeArray# (unMArray ary) i# b s of+ s' -> (# s' , () #)+{-# INLINE write #-}++index :: Array a -> Int -> a+index ary _i@(I# i#) =+ CHECK_BOUNDS("index", length ary, _i)+ case indexArray# (unArray ary) i# of (# b #) -> b+{-# INLINE index #-}++index_ :: Array a -> Int -> ST s a+index_ ary _i@(I# i#) =+ CHECK_BOUNDS("index_", length ary, _i)+ case indexArray# (unArray ary) i# of (# b #) -> return b+{-# INLINE index_ #-}++indexM_ :: MArray s a -> Int -> ST s a+indexM_ ary _i@(I# i#) =+ CHECK_BOUNDS("index_", lengthM ary, _i)+ ST $ \ s# -> readArray# (unMArray ary) i# s#+{-# INLINE indexM_ #-}++unsafeFreeze :: MArray s a -> ST s (Array a)+unsafeFreeze mary = + ST $ \s -> case unsafeFreezeArray# (unMArray mary) s of+ (# s', ary #) -> (# s', array ary (lengthM mary) #)+{-# INLINE unsafeFreeze #-}++run :: (forall s . ST s (MArray s e)) -> Array e+run act = runST $ act >>= unsafeFreeze+{-# INLINE run #-}++run2 :: (forall s. ST s (MArray s e, a)) -> (Array e, a)+run2 k = runST $ do+ (marr,b) <- k+ arr <- unsafeFreeze marr+ return (arr,b)++-- | Unsafely copy the elements of an array. Array bounds are not checked.+copy :: Array e -> Int -> MArray s e -> Int -> Int -> ST s ()+#if __GLASGOW_HASKELL__ >= 702+copy !src !_sidx@(I# sidx#) !dst !_didx@(I# didx#) _n@(I# n#) =+ CHECK_LE("copy", _sidx + _n, length src)+ CHECK_LE("copy", _didx + _n, lengthM dst)+ ST $ \ s# -> case copyArray# (unArray src) sidx# (unMArray dst) didx# n# s# of+ s2 -> (# s2, () #)+#else+copy !src !sidx !dst !didx n =+ CHECK_LE("copy", sidx + n, length src)+ CHECK_LE("copy", didx + n, lengthM dst)+ copy_loop sidx didx 0 where+ copy_loop !i !j !c+ | c >= n = return ()+ | otherwise = do+ b <- index_ src i+ write dst j b+ copy_loop (i+1) (j+1) (c+1)+#endif++-- | Unsafely copy the elements of an array. Array bounds are not checked.+copyM :: MArray s e -> Int -> MArray s e -> Int -> Int -> ST s ()+#if __GLASGOW_HASKELL__ >= 702+copyM !src !_sidx@(I# sidx#) !dst !_didx@(I# didx#) _n@(I# n#) =+ CHECK_BOUNDS("copyM: src", lengthM src, _sidx + _n - 1)+ CHECK_BOUNDS("copyM: dst", lengthM dst, _didx + _n - 1)+ ST $ \ s# -> case copyMutableArray# (unMArray src) sidx# (unMArray dst) didx# n# s# of+ s2 -> (# s2, () #)+#else+copyM !src !sidx !dst !didx n =+ CHECK_BOUNDS("copyM: src", lengthM src, sidx + n - 1)+ CHECK_BOUNDS("copyM: dst", lengthM dst, didx + n - 1)+ copy_loop sidx didx 0 where+ copy_loop !i !j !c+ | c >= n = return ()+ | otherwise = do + b <- indexM_ src i+ write dst j b+ copy_loop (i+1) (j+1) (c+1)+#endif++-- | /O(n)/ Insert an element at the given position in this array,+-- increasing its size by one.+insert :: Array e -> Int -> e -> Array e+insert ary idx b =+ CHECK_BOUNDS("insert", count + 1, idx)+ run $ do+ mary <- new_ (count+1)+ copy ary 0 mary 0 idx+ write mary idx b+ copy ary idx mary (idx+1) (count-idx)+ return mary + where !count = length ary+{-# INLINE insert #-}++-- | /O(n)/ Update the element at the given position in this array.+update :: Array e -> Int -> e -> Array e+update ary idx b =+ CHECK_BOUNDS("update", count, idx)+ run $ do+ mary <- thaw ary 0 count+ write mary idx b+ return mary+ where !count = length ary+{-# INLINE update #-}++foldl' :: (b -> a -> b) -> b -> Array a -> b+foldl' f = \ z0 ary0 -> go ary0 (length ary0) 0 z0 where+ go ary n i !z+ | i >= n = z+ | otherwise = go ary n (i+1) (f z (index ary i))+{-# INLINE foldl' #-}++foldr :: (a -> b -> b) -> b -> Array a -> b+foldr f = \ z0 ary0 -> go ary0 (length ary0) 0 z0 where+ go ary n i z+ | i >= n = z+ | otherwise = f (index ary i) (go ary n (i+1) z)+{-# INLINE foldr #-}++undefinedElem :: a+undefinedElem = error "Undefined element"++thaw :: Array e -> Int -> Int -> ST s (MArray s e)+#if __GLASGOW_HASKELL__ >= 702+thaw !ary !_o@(I# o#) !n@(I# n#) =+ CHECK_LE("thaw", _o + n, length ary)+ ST $ \ s -> case thawArray# (unArray ary) o# n# s of+ (# s2, mary# #) -> (# s2, marray mary# n #)+#else+thaw !ary !o !n =+ CHECK_LE("thaw", o + n, length ary)+ do mary <- new_ n+ copy ary o mary 0 n+ return mary+#endif+{-# INLINE thaw #-}++-- | /O(n)/ Delete an element at the given position in this array,+-- decreasing its size by one.+delete :: Array e -> Int -> Array e+delete ary idx = run $ do+ mary <- new_ (count-1)+ copy ary 0 mary 0 idx+ copy ary (idx+1) mary idx (count-(idx+1))+ return mary+ where !count = length ary+{-# INLINE delete #-}++map :: (a -> b) -> Array a -> Array b+map f = \ ary ->+ let !n = length ary+ in run $ do+ mary <- new_ n+ go ary mary 0 n+ where+ go ary mary i n+ | i >= n = return mary+ | otherwise = do+ write mary i $ f (index ary i)+ go ary mary (i+1) n+{-# INLINE map #-}++-- | Strict version of 'map'.+map' :: (a -> b) -> Array a -> Array b+map' f = \ ary ->+ let !n = length ary+ in run $ do+ mary <- new_ n+ go ary mary 0 n+ where+ go ary mary i n+ | i >= n = return mary+ | otherwise = do+ write mary i $! f (index ary i)+ go ary mary (i+1) n+{-# INLINE map' #-}++fromList :: Int -> [a] -> Array a+fromList n xs0 = run $ do+ mary <- new_ n+ go xs0 mary 0+ where+ go [] !mary !_ = return mary+ go (x:xs) mary i = do write mary i x+ go xs mary (i+1)++toList :: Array a -> [a]+toList = foldr (:) []++traverse :: Applicative f => (a -> f b) -> Array a -> f (Array b)+traverse f = \ ary ->+ fromList (length ary) `fmap`+ Traversable.traverse f (toList ary)+{-# INLINE traverse #-}++filter :: (a -> Bool) -> Array a -> Array a+filter p = \ ary ->+ let !n = length ary+ in run $ do+ mary <- new_ n+ go ary mary 0 0 n+ where+ go ary mary i j n+ | i >= n = if i == j+ then return mary+ else do mary2 <- new_ j+ copyM mary 0 mary2 0 j+ return mary2+ | p el = write mary j el >> go ary mary (i+1) (j+1) n+ | otherwise = go ary mary (i+1) j n+ where el = index ary i+{-# INLINE filter #-}
+ src/Text/Trifecta/Util/Combinators.hs view
@@ -0,0 +1,52 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Util.Combinators+-- Copyright : (C) 2011 Edward Kmett,+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : experimental+-- Portability : non-portable+--+----------------------------------------------------------------------------+module Text.Trifecta.Util.Combinators+ ( argmin+ , argmax+ -- * ByteString conversions+ , fromLazy+ , toLazy+ , takeLine+ , (<$!>)+ ) where++import Data.ByteString.Lazy as Lazy+import Data.ByteString as Strict++argmin :: Ord b => (a -> b) -> a -> a -> a+argmin f a b+ | f a <= f b = a+ | otherwise = b+{-# INLINE argmin #-}++argmax :: Ord b => (a -> b) -> a -> a -> a+argmax f a b+ | f a > f b = a+ | otherwise = b+{-# INLINE argmax #-}++fromLazy :: Lazy.ByteString -> Strict.ByteString+fromLazy = Strict.concat . Lazy.toChunks+ +toLazy :: Strict.ByteString -> Lazy.ByteString+toLazy = Lazy.fromChunks . return++takeLine :: Lazy.ByteString -> Lazy.ByteString+takeLine s = case Lazy.elemIndex 10 s of+ Just i -> Lazy.take (i + 1) s+ Nothing -> s++infixl 4 <$!>+(<$!>) :: Monad m => (a -> b) -> m a -> m b+f <$!> m = do+ a <- m + return $! f a
trifecta.cabal view
@@ -1,6 +1,6 @@ name: trifecta category: Text, Parsing, Diagnostics, Pretty Printer, Logging-version: 0.52+version: 0.53 license: BSD3 cabal-version: >= 1.6 license-file: LICENSE@@ -23,6 +23,8 @@ location: git://github.com/ekmett/trifecta.git library+ hs-source-dirs: src+ exposed-modules: Text.Trifecta Text.Trifecta.IntervalMap@@ -93,30 +95,28 @@ ghc-options: -Wall build-depends:- base >= 4 && < 5,+ base == 4.*, array >= 0.3.0.2 && < 0.5,- charset >= 0.3.2 && < 0.4,+ charset >= 0.3.2.1 && < 0.4, containers >= 0.3 && < 0.6, unordered-containers >= 0.2.1 && < 0.3, blaze-builder >= 0.3.0.1 && < 0.4, blaze-html >= 0.4.1.6 && < 0.5,- bifunctors >= 0.1.3.1 && < 0.2,- data-lens >= 2.0.3 && < 2.11,- data-lens-fd >= 2.0.1 && < 2.11,+ bifunctors == 3.0.*, deepseq >= 1.2.0.1 && < 1.4, hashable >= 1.1.2.1 && < 1.2,- bytestring >= 0.9.1 && < 0.10,+ bytestring >= 0.9.1 && < 0.11, mtl >= 2.0.1 && < 2.2, semigroups >= 0.8.3.1 && < 0.9, fingertree >= 0.0.1 && < 0.1,- reducers >= 0.3 && < 0.4,- profunctors >= 0.1.2.2 && < 0.2,+ reducers == 3.0.*,+ profunctors == 3.0.*, utf8-string >= 0.3.6 && < 0.4,- semigroupoids >= 1.3.1.2 && < 1.4,- pointed >= 2.1.0.1 && < 2.2,+ semigroupoids == 3.0.*,+ pointed == 3.0.*, transformers >= 0.2 && < 0.4,- comonad >= 1.1.1.3 && < 1.2,+ comonad == 3.0.*, terminfo >= 0.3.2 && < 0.4,- keys >= 2.1.3.1 && < 2.2,- wl-pprint-extras >= 1.6.3.1 && < 1.7,- wl-pprint-terminfo >= 0.8.3.1 && < 0.9+ keys == 3.0.*,+ wl-pprint-extras == 3.0.*,+ wl-pprint-terminfo == 3.0.*