trifecta 0.16.1 → 0.17
raw patch · 51 files changed
+2850/−1436 lines, 51 files
Files
- LICENSE +2/−1
- Text/Trifecta.hs +3/−57
- Text/Trifecta/Bytes.hs +0/−15
- Text/Trifecta/CharSet.hs +78/−0
- Text/Trifecta/CharSet/AsciiSet.hs +96/−0
- Text/Trifecta/CharSet/Common.hs +65/−0
- Text/Trifecta/CharSet/Posix/Ascii.hs +61/−0
- Text/Trifecta/CharSet/Posix/Unicode.hs +64/−0
- Text/Trifecta/CharSet/Prim.hs +339/−0
- Text/Trifecta/CharSet/Unicode.hs +177/−0
- Text/Trifecta/CharSet/Unicode/Block.hs +382/−0
- Text/Trifecta/CharSet/Unicode/Category.hs +212/−0
- Text/Trifecta/Delta.hs +0/−155
- Text/Trifecta/Diagnostic.hs +9/−76
- Text/Trifecta/Diagnostic/Err.hs +82/−0
- Text/Trifecta/Diagnostic/Err/State.hs +34/−0
- Text/Trifecta/Diagnostic/Prim.hs +82/−0
- Text/Trifecta/Diagnostic/Rendering.hs +12/−0
- Text/Trifecta/Diagnostic/Rendering/Caret.hs +107/−0
- Text/Trifecta/Diagnostic/Rendering/Fixit.hs +52/−0
- Text/Trifecta/Diagnostic/Rendering/Prim.hs +191/−0
- Text/Trifecta/Diagnostic/Rendering/Span.hs +113/−0
- Text/Trifecta/Hunk.hs +0/−58
- Text/Trifecta/Parser/Class.hs +2/−2
- Text/Trifecta/Parser/Combinators.hs +0/−1
- Text/Trifecta/Parser/Err.hs +0/−82
- Text/Trifecta/Parser/Err/State.hs +0/−34
- Text/Trifecta/Parser/It.hs +7/−9
- Text/Trifecta/Parser/Prim.hs +14/−17
- Text/Trifecta/Parser/Result.hs +1/−1
- Text/Trifecta/Parser/Step.hs +2/−2
- Text/Trifecta/Parser/Token.hs +16/−0
- Text/Trifecta/Parser/Token/Identifier.hs +52/−0
- Text/Trifecta/Parser/Token/Identifier/Style.hs +65/−0
- Text/Trifecta/Parser/Token/Prim.hs +0/−71
- Text/Trifecta/Parser/Token/Style.hs +50/−77
- Text/Trifecta/Path.hs +0/−103
- Text/Trifecta/Render/Caret.hs +0/−104
- Text/Trifecta/Render/Fixit.hs +0/−57
- Text/Trifecta/Render/Prim.hs +0/−191
- Text/Trifecta/Render/Span.hs +0/−124
- Text/Trifecta/Rope.hs +0/−83
- Text/Trifecta/Rope/Bytes.hs +15/−0
- Text/Trifecta/Rope/Delta.hs +155/−0
- Text/Trifecta/Rope/Hunk.hs +58/−0
- Text/Trifecta/Rope/Path.hs +103/−0
- Text/Trifecta/Rope/Prim.hs +83/−0
- Text/Trifecta/Rope/Strand.hs +37/−0
- Text/Trifecta/Strand.hs +0/−37
- Text/Trifecta/Util/MaybePair.hs +0/−62
- trifecta.cabal +29/−17
LICENSE view
@@ -1,4 +1,5 @@-Copyright 2011 Edward Kmett+Copyright 2010-2011 Edward Kmett+Copyright 2008 Bryan O'Sullivan Copyright 2007 Paolo Martini Copyright 1999-2000 Daan Leijen
Text/Trifecta.hs view
@@ -1,63 +1,9 @@ module Text.Trifecta - ( module Text.Trifecta.Bytes--- , module System.Console.Terminfo.Color+ ( module Text.Trifecta.Diagnostic+ , module Text.Trifecta.Parser , module System.Console.Terminfo.PrettyPrint--- , module Text.PrettyPrint.Free- , module Text.Trifecta.Delta- , module Text.Trifecta.Diagnostic- , module Text.Trifecta.Diagnostic.Level- , module Text.Trifecta.Hunk- , module Text.Trifecta.Parser.Char- , module Text.Trifecta.Parser.Class- , module Text.Trifecta.Parser.Combinators- , module Text.Trifecta.Parser.Err- , module Text.Trifecta.Parser.Err.State- , module Text.Trifecta.Parser.It- , module Text.Trifecta.Parser.Prim- , module Text.Trifecta.Parser.Result- , module Text.Trifecta.Parser.Step- , module Text.Trifecta.Parser.Token.Class- , module Text.Trifecta.Parser.Token.Combinators- , module Text.Trifecta.Parser.Token.Prim- , module Text.Trifecta.Parser.Token.Style- , module Text.Trifecta.Parser.Expr- , module Text.Trifecta.Path- , module Text.Trifecta.Render.Caret- , module Text.Trifecta.Render.Fixit- , module Text.Trifecta.Render.Prim- , module Text.Trifecta.Render.Span- , module Text.Trifecta.Rope- , module Text.Trifecta.Strand- , module Text.Trifecta.Util.MaybePair ) where -import Text.Trifecta.Bytes-import Text.Trifecta.Delta import Text.Trifecta.Diagnostic-import Text.Trifecta.Diagnostic.Level-import Text.Trifecta.Hunk-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Parser.Err-import Text.Trifecta.Parser.Err.State-import Text.Trifecta.Parser.It-import Text.Trifecta.Parser.Prim-import Text.Trifecta.Parser.Result-import Text.Trifecta.Parser.Step-import Text.Trifecta.Parser.Token.Class-import Text.Trifecta.Parser.Token.Combinators-import Text.Trifecta.Parser.Token.Prim-import Text.Trifecta.Parser.Token.Style-import Text.Trifecta.Parser.Expr-import Text.Trifecta.Path-import Text.Trifecta.Render.Caret-import Text.Trifecta.Render.Fixit-import Text.Trifecta.Render.Prim-import Text.Trifecta.Render.Span-import Text.Trifecta.Rope-import Text.Trifecta.Strand-import Text.Trifecta.Util.MaybePair--- import Text.PrettyPrint.Free hiding (column, char, line, string, space)+import Text.Trifecta.Parser import System.Console.Terminfo.PrettyPrint--- import System.Console.Terminfo.Color
− Text/Trifecta/Bytes.hs
@@ -1,15 +0,0 @@-module Text.Trifecta.Bytes- ( HasBytes(..)- ) where--import Data.ByteString as Strict-import Data.FingerTree--class HasBytes t where- bytes :: t -> Int--instance HasBytes ByteString where- bytes = Strict.length--instance (Measured v a, HasBytes v) => HasBytes (FingerTree v a) where- bytes = bytes . measure
+ Text/Trifecta/CharSet.hs view
@@ -0,0 +1,78 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet+-- Copyright : (c) Edward Kmett 2010-2011, +-- Bryan O'Sullivan 2008+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable (Data, BangPatterns, MagicHash)+--+-- Fast set membership tests for 'Char' values+--+-- Stored as a (possibly negated IntMap) and a fast set for the ASCII range.+--+-- The ASCII range is unboxed for efficiency. For small (complemented) sets, we+-- test for membership using a binary search. For larger (complemented) sets+-- we use a lookup table. +--+-- Designed to be imported qualified:+-- +-- > import Text.Trifecta.CharSet.Prim (CharSet)+-- > import qualified Text.Trifecta.CharSet.Prim as CharSet+--+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet+ ( + -- * Set type+ CharSet+ -- * Operators+ , (\\)+ -- * Query+ , null+ , size+ , member+ , notMember+ , overlaps, isSubsetOf+ , isComplemented + -- * Construction+ , build+ , empty+ , singleton+ , full+ , insert+ , delete+ , complement+ , range+ -- * Combine+ , union+ , intersection+ , difference+ -- * Filter+ , filter+ , partition+ -- * Map+ , map+ -- * Fold+ , fold+ -- * Conversion+ -- ** List+ , toList+ , fromList+ -- ** Ordered list+ , toAscList+ , fromAscList+ , fromDistinctAscList+ -- ** IntMaps+ , fromCharSet+ , toCharSet+ -- ** Array+ , toArray+ , module Text.Trifecta.CharSet.Common+ ) where++import Text.Trifecta.CharSet.Prim+import Text.Trifecta.CharSet.Common+import Prelude ()+
+ Text/Trifecta/CharSet/AsciiSet.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE BangPatterns, MagicHash #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.AsciiSet+-- Copyright : Edward Kmett 2011+-- Bryan O'Sullivan 2008+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : unknown+--+-- Fast set membership tests for ASCII values, The+-- set representation is unboxed for efficiency. For small sets, we+-- test for membership using a binary search. For larger sets, we use+-- a lookup table. +-----------------------------------------------------------------------------+module Text.Trifecta.CharSet.AsciiSet+ (+ -- * Data type+ AsciiSet+ -- * Construction+ , fromList+ -- * Lookup+ , member+ ) where++import Data.Bits ((.&.), (.|.))+import Foreign.Storable (peekByteOff, pokeByteOff)+import GHC.Base (Int(I#), iShiftRA#, narrow8Word#, shiftL#)+import GHC.Word (Word8(W8#))+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Internal as I+import qualified Data.ByteString.Unsafe as U++data AsciiSet + = Sorted !B.ByteString+ | Table !B.ByteString+ deriving (Eq, Ord, Show)++-- | The lower bound on the size of a lookup table. We choose this to+-- balance table density against performance.+tableCutoff :: Int+tableCutoff = 8++-- | Create a set.+fromList :: [Char] -> AsciiSet+fromList s + | B.length bs < tableCutoff = Sorted (B.sort bs)+ | otherwise = Table (mkTable bs)+ where+ bs = B8.pack (filter (<= toEnum 0x7f) s)++-- | Check the set for membership.+member :: Char -> AsciiSet -> Bool+member c (Table t) = U.unsafeIndex t byte .&. bit /= 0+ where + i = fromEnum c+ I byte bit = index i+member c (Sorted s) = search 0 (B.length s - 1)+ where + w = I.c2w c+ search lo hi+ | hi < lo = False+ | otherwise = let mid = (lo + hi) `div` 2 in+ case compare w (U.unsafeIndex s mid) of+ GT -> search (mid + 1) hi+ LT -> search lo (mid - 1)+ _ -> True++data I = I {-# UNPACK #-} !Int {-# UNPACK #-} !Word8++shiftR :: Int -> Int -> Int+shiftR (I# x#) (I# i#) = I# (x# `iShiftRA#` i#)++shiftL :: Word8 -> Int -> Word8+shiftL (W8# x#) (I# i#) = W8# (narrow8Word# (x# `shiftL#` i#))++index :: Int -> I+index i = I (i `shiftR` 3) (1 `shiftL` (i .&. 7))+{-# INLINE index #-}++mkTable :: B.ByteString -> B.ByteString+mkTable s = I.unsafeCreate 32 $ \t -> do+ _ <- I.memset t 0 32+ U.unsafeUseAsCStringLen s $ \(p, l) ->+ let loop n + | n == l = return ()+ | otherwise = do+ c <- peekByteOff p n :: IO Word8+ let I byte bit = index (fromIntegral c)+ prev <- peekByteOff t byte :: IO Word8+ pokeByteOff t byte (prev .|. bit)+ loop (n + 1)+ in loop 0
+ Text/Trifecta/CharSet/Common.hs view
@@ -0,0 +1,65 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Common+-- Copyright : (c) Edward Kmett 2010-2011+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : portable+--+-- The various character classifications from "Data.Char" as 'CharSet's+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Common+ ( + -- ** Data.Char classes+ control+ , space+ , lower+ , upper+ , alpha+ , alphaNum+ , print+ , digit+ , octDigit+ , letter+ , mark+ , number+ , punctuation+ , symbol+ , separator+ , ascii+ , latin1+ , asciiUpper+ , asciiLower+ ) where++import Prelude ()+import Data.Char+import Text.Trifecta.CharSet.Prim++-- Haskell character classes from Data.Char+control, space, lower, upper, alpha, alphaNum, + print, digit, octDigit, letter, mark, number, + punctuation, symbol, separator, ascii, latin1+ , asciiUpper, asciiLower :: CharSet++control = build isControl+space = build isSpace+lower = build isLower+upper = build isUpper+alpha = build isAlpha+alphaNum = build isAlphaNum+print = build isPrint+digit = build isDigit+octDigit = build isOctDigit+letter = build isLetter+mark = build isMark+number = build isNumber+punctuation = build isPunctuation+symbol = build isSymbol+separator = build isSeparator+ascii = build isAscii+latin1 = build isLatin1+asciiUpper = build isAsciiUpper+asciiLower = build isAsciiLower
+ Text/Trifecta/CharSet/Posix/Ascii.hs view
@@ -0,0 +1,61 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Posix.Ascii+-- Copyright : (c) Edward Kmett 2010+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : portable+--+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Posix.Ascii+ ( posixAscii+ , lookupPosixAsciiCharSet+ -- * Traditional POSIX ASCII \"classes\"+ , alnum, alpha, ascii, blank, cntrl, digit, graph, print, word, punct, space, upper, lower, xdigit+ ) where++import Prelude hiding (print)+import Data.Char+import Text.Trifecta.CharSet.Prim+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HashMap++alnum, alpha, ascii, blank, cntrl, digit, graph, print, word, punct, space, upper, lower, xdigit :: CharSet+alnum = alpha `union` digit+alpha = lower `union` upper+ascii = range '\x00' '\x7f'+blank = fromList " \t"+cntrl = insert '\x7f' $ range '\x00' '\x1f'+digit = range '0' '9'+lower = range 'a' 'z'+upper = range 'A' 'Z'+graph = range '\x21' '\x7e'+print = insert '\x20' graph+word = insert '_' alnum+punct = fromList "-!\"#$%&'()*+,./:;<=>?@[\\]^_`{|}~"+space = fromList " \t\r\n\v\f"+xdigit = digit `union` range 'a' 'f' `union` range 'A' 'F'++-- :digit:, etc.+posixAscii :: HashMap String CharSet+posixAscii = HashMap.fromList+ [ ("alnum", alnum)+ , ("alpha", alpha)+ , ("ascii", ascii)+ , ("blank", blank)+ , ("cntrl", cntrl)+ , ("digit", digit)+ , ("graph", graph) + , ("print", print)+ , ("word", word)+ , ("punct", punct)+ , ("space", space)+ , ("upper", upper)+ , ("lower", lower)+ , ("xdigit", xdigit)+ ]++lookupPosixAsciiCharSet :: String -> Maybe CharSet+lookupPosixAsciiCharSet s = HashMap.lookup (Prelude.map toLower s) posixAscii
+ Text/Trifecta/CharSet/Posix/Unicode.hs view
@@ -0,0 +1,64 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Posix.Unicode+-- Copyright : (c) Edward Kmett 2010+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : portable+--+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Posix.Unicode+ ( posixUnicode+ , lookupPosixUnicodeCharSet+ -- * POSIX ASCII \"classes\"+ , alnum, alpha, ascii, blank, cntrl, digit, graph, print, word, punct, space, upper, lower, xdigit+ ) where++import Prelude hiding (print)+import Data.Char+import Text.Trifecta.CharSet.Prim+import qualified Text.Trifecta.CharSet.Unicode.Category as Category+import qualified Text.Trifecta.CharSet.Unicode.Block as Block+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HashMap++alnum, alpha, ascii, blank, cntrl, digit, graph, print, word, punct, space, upper, lower, xdigit :: CharSet+alnum = alpha `union` digit+ascii = Block.basicLatin+alpha = Category.letterAnd+blank = insert '\t' Category.space +cntrl = Category.control+digit = Category.decimalNumber+lower = Category.lowercaseLetter+upper = Category.uppercaseLetter+graph = complement (Category.separator `union` Category.other)+print = complement (Category.other)+word = Category.letter `union` Category.number `union` Category.connectorPunctuation+punct = Category.punctuation `union` Category.symbol+space = fromList " \t\r\n\v\f" `union` Category.separator+xdigit = digit `union` range 'a' 'f' `union` range 'A' 'F'++-- :digit:, etc.+posixUnicode :: HashMap String CharSet+posixUnicode = HashMap.fromList+ [ ("alnum", alnum)+ , ("alpha", alpha)+ , ("ascii", ascii)+ , ("blank", blank)+ , ("cntrl", cntrl)+ , ("digit", digit)+ , ("graph", graph) + , ("print", print)+ , ("word", word)+ , ("punct", punct)+ , ("space", space)+ , ("upper", upper)+ , ("lower", lower)+ , ("xdigit", xdigit)+ ]++lookupPosixUnicodeCharSet :: String -> Maybe CharSet+lookupPosixUnicodeCharSet s = HashMap.lookup (Prelude.map toLower s) posixUnicode+
+ Text/Trifecta/CharSet/Prim.hs view
@@ -0,0 +1,339 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Prim+-- Copyright : (c) Edward Kmett 2010-2011+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable (Data, BangPatterns, MagicHash)+--+-- Fast set membership tests for 'Char' values+--+-- Stored as a (possibly negated IntMap) and a fast set for the ASCII range.+--+-- The ASCII range is unboxed for efficiency. For small (complemented) sets, we+-- test for membership using a binary search. For larger (complemented) sets+-- we use a lookup table. +--+-- Designed to be imported qualified:+-- +-- > import Text.Trifecta.CharSet.Prim (CharSet)+-- > import qualified Text.Trifecta.CharSet.Prim as CharSet+--+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Prim+ ( + -- * Set type+ CharSet+ -- * Operators+ , (\\)+ -- * Query+ , null+ , size+ , member+ , notMember+ , overlaps, isSubsetOf+ , isComplemented + -- * Construction+ , build+ , empty+ , singleton+ , full+ , insert+ , delete+ , complement+ , range+ -- * Combine+ , union+ , intersection+ , difference+ -- * Filter+ , filter+ , partition+ -- * Map+ , map+ -- * Fold+ , fold+ -- * Conversion+ -- ** List+ , toList+ , fromList+ -- ** Ordered list+ , toAscList+ , fromAscList+ , fromDistinctAscList+ -- ** IntMaps+ , fromCharSet+ , toCharSet+ -- ** Array+ , toArray+ ) where++import Data.Array.Unboxed hiding (range)+import Data.Data+import Data.Function (on)+import Data.IntSet (IntSet)+import Text.Trifecta.CharSet.AsciiSet (AsciiSet)+import qualified Text.Trifecta.CharSet.AsciiSet as AsciiSet+import Data.Monoid (Monoid(..))+import qualified Data.IntSet as I+import qualified Data.List as L+import Prelude hiding (filter, map, null)+import qualified Prelude as P+import Text.Read++data CharSet + = Pos AsciiSet !IntSet + | Neg AsciiSet !IntSet++pos :: IntSet -> CharSet+pos s = Pos (AsciiSet.fromList (fmap toEnum (takeWhile (<= 0x7f) (I.toAscList s)))) s++neg :: IntSet -> CharSet+neg s = Neg (AsciiSet.fromList (fmap toEnum (takeWhile (<= 0x7f) (I.toAscList s)))) s++(\\) :: CharSet -> CharSet -> CharSet+(\\) = difference++build :: (Char -> Bool) -> CharSet+build p = fromDistinctAscList $ P.filter p [minBound .. maxBound]+{-# INLINE build #-}++map :: (Char -> Char) -> CharSet -> CharSet+map f (Pos _ i) = pos (I.map (fromEnum . f . toEnum) i)+map f (Neg _ i) = fromList $ P.map f $ P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh] +{-# INLINE map #-}++isComplemented :: CharSet -> Bool+isComplemented (Pos _ _) = False+isComplemented (Neg _ _) = True+{-# INLINE isComplemented #-}++toList :: CharSet -> String+toList (Pos _ i) = P.map toEnum (I.toList i)+toList (Neg _ i) = P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]+{-# INLINE toList #-}++toAscList :: CharSet -> String+toAscList (Pos _ i) = P.map toEnum (I.toAscList i)+toAscList (Neg _ i) = P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]+{-# INLINE toAscList #-}+ +empty :: CharSet+empty = pos I.empty++singleton :: Char -> CharSet+singleton = pos . I.singleton . fromEnum+{-# INLINE singleton #-}++full :: CharSet+full = neg I.empty++-- | /O(n)/ worst case+null :: CharSet -> Bool+null (Pos _ i) = I.null i+null (Neg _ i) = I.size i == numChars+{-# INLINE null #-}++-- | /O(n)/+size :: CharSet -> Int+size (Pos _ i) = I.size i+size (Neg _ i) = numChars - I.size i+{-# INLINE size #-}++insert :: Char -> CharSet -> CharSet+insert c (Pos _ i) = pos (I.insert (fromEnum c) i)+insert c (Neg _ i) = neg (I.delete (fromEnum c) i)+{-# INLINE insert #-}++range :: Char -> Char -> CharSet+range a b + | a <= b = fromDistinctAscList [a..b]+ | otherwise = empty++delete :: Char -> CharSet -> CharSet+delete c (Pos _ i) = pos (I.delete (fromEnum c) i)+delete c (Neg _ i) = neg (I.insert (fromEnum c) i)+{-# INLINE delete #-}++complement :: CharSet -> CharSet+complement (Pos s i) = Neg s i+complement (Neg s i) = Pos s i+{-# INLINE complement #-}++union :: CharSet -> CharSet -> CharSet+union (Pos _ i) (Pos _ j) = pos (I.union i j)+union (Pos _ i) (Neg _ j) = neg (I.difference j i)+union (Neg _ i) (Pos _ j) = neg (I.difference i j)+union (Neg _ i) (Neg _ j) = neg (I.intersection i j)+{-# INLINE union #-}++intersection :: CharSet -> CharSet -> CharSet+intersection (Pos _ i) (Pos _ j) = pos (I.intersection i j)+intersection (Pos _ i) (Neg _ j) = pos (I.difference i j)+intersection (Neg _ i) (Pos _ j) = pos (I.difference j i)+intersection (Neg _ i) (Neg _ j) = neg (I.union i j)+{-# INLINE intersection #-}++difference :: CharSet -> CharSet -> CharSet +difference (Pos _ i) (Pos _ j) = pos (I.difference i j)+difference (Pos _ i) (Neg _ j) = pos (I.intersection i j)+difference (Neg _ i) (Pos _ j) = neg (I.union i j)+difference (Neg _ i) (Neg _ j) = pos (I.difference j i)+{-# INLINE difference #-}++member :: Char -> CharSet -> Bool+member c (Pos b i)+ | c <= toEnum 0x7f = AsciiSet.member c b+ | otherwise = I.member (fromEnum c) i+member c (Neg b i) + | c <= toEnum 0x7f = not (AsciiSet.member c b)+ | otherwise = I.notMember (fromEnum c) i+{-# INLINE member #-}++notMember :: Char -> CharSet -> Bool+notMember c s = not (member c s)+{-# INLINE notMember #-}++fold :: (Char -> b -> b) -> b -> CharSet -> b+fold f z (Pos _ i) = I.fold (f . toEnum) z i+fold f z (Neg _ i) = foldr f z $ P.filter (\x -> fromEnum x `I.notMember` i) [ul..uh]+{-# INLINE fold #-}++filter :: (Char -> Bool) -> CharSet -> CharSet +filter p (Pos _ i) = pos (I.filter (p . toEnum) i)+filter p (Neg _ i) = neg $ foldr (I.insert) i $ P.filter (\x -> (x `I.notMember` i) && not (p (toEnum x))) [ol..oh]+{-# INLINE filter #-}++partition :: (Char -> Bool) -> CharSet -> (CharSet, CharSet)+partition p (Pos _ i) = (pos l, pos r)+ where (l,r) = I.partition (p . toEnum) i+partition p (Neg _ i) = (neg (foldr I.insert i l), neg (foldr I.insert i r))+ where (l,r) = L.partition (p . toEnum) $ P.filter (\x -> x `I.notMember` i) [ol..oh]+{-# INLINE partition #-}++overlaps :: CharSet -> CharSet -> Bool+overlaps (Pos _ i) (Pos _ j) = not (I.null (I.intersection i j))+overlaps (Pos _ i) (Neg _ j) = not (I.isSubsetOf j i)+overlaps (Neg _ i) (Pos _ j) = not (I.isSubsetOf i j)+overlaps (Neg _ i) (Neg _ j) = any (\x -> I.notMember x i && I.notMember x j) [ol..oh] -- not likely+{-# INLINE overlaps #-}++isSubsetOf :: CharSet -> CharSet -> Bool+isSubsetOf (Pos _ i) (Pos _ j) = I.isSubsetOf i j+isSubsetOf (Pos _ i) (Neg _ j) = I.null (I.intersection i j)+isSubsetOf (Neg _ i) (Pos _ j) = all (\x -> I.member x i && I.member x j) [ol..oh] -- not bloody likely+isSubsetOf (Neg _ i) (Neg _ j) = I.isSubsetOf j i+{-# INLINE isSubsetOf #-}++fromList :: String -> CharSet +fromList = pos . I.fromList . P.map fromEnum+{-# INLINE fromList #-}++fromAscList :: String -> CharSet+fromAscList = pos . I.fromAscList . P.map fromEnum+{-# INLINE fromAscList #-}++fromDistinctAscList :: String -> CharSet+fromDistinctAscList = pos . I.fromDistinctAscList . P.map fromEnum+{-# INLINE fromDistinctAscList #-}++-- isProperSubsetOf :: CharSet -> CharSet -> Bool+-- isProperSubsetOf (P i) (P j) = I.isProperSubsetOf i j+-- isProperSubsetOf (P i) (N j) = null (I.intersection i j) && ...+-- isProperSubsetOf (N i) (N j) = I.isProperSubsetOf j i++ul, uh :: Char+ul = minBound+uh = maxBound+{-# INLINE ul #-}+{-# INLINE uh #-}++ol, oh :: Int+ol = fromEnum ul+oh = fromEnum uh+{-# INLINE ol #-}+{-# INLINE oh #-}++numChars :: Int+numChars = oh - ol + 1+{-# INLINE numChars #-}++instance Typeable CharSet where+ typeOf _ = mkTyConApp charSetTyCon []++charSetTyCon :: TyCon+charSetTyCon = mkTyCon "Text.Trifecta.CharSet.CharSet"+{-# NOINLINE charSetTyCon #-}++instance Data CharSet where+ gfoldl k z set + | isComplemented set = z complement `k` complement set+ | otherwise = z fromList `k` toList set++ toConstr set + | isComplemented set = complementConstr+ | otherwise = fromListConstr++ dataTypeOf _ = charSetDataType++ gunfold k z c = case constrIndex c of+ 1 -> k (z fromList)+ 2 -> k (z complement)+ _ -> error "gunfold"++fromListConstr :: Constr+fromListConstr = mkConstr charSetDataType "fromList" [] Prefix+{-# NOINLINE fromListConstr #-}++complementConstr :: Constr+complementConstr = mkConstr charSetDataType "complement" [] Prefix+{-# NOINLINE complementConstr #-}++charSetDataType :: DataType+charSetDataType = mkDataType "Text.Trifecta.CharSet.CharSet" [fromListConstr, complementConstr]+{-# NOINLINE charSetDataType #-}++-- returns an intset and if the intset should be complemented to obtain the contents of the CharSet+fromCharSet :: CharSet -> (Bool, IntSet)+fromCharSet (Pos _ i) = (False, i)+fromCharSet (Neg _ i) = (True, i) +{-# INLINE fromCharSet #-}++toCharSet :: IntSet -> CharSet+toCharSet = pos+{-# INLINE toCharSet #-}++instance Eq CharSet where+ (==) = (==) `on` toAscList++instance Ord CharSet where+ compare = compare `on` toAscList++instance Bounded CharSet where+ minBound = empty+ maxBound = full++-- TODO return a tighter bounded array perhaps starting from the least element present to the last element present?+toArray :: CharSet -> UArray Char Bool+toArray set = array (minBound, maxBound) $ fmap (\x -> (x, x `member` set)) [minBound .. maxBound]+ +instance Show CharSet where+ showsPrec d i+ | isComplemented i = showParen (d > 10) $ showString "complement " . showsPrec 11 (complement i)+ | otherwise = showParen (d > 10) $ showString "fromDistinctAscList " . showsPrec 11 (toAscList i)++instance Read CharSet where+ readPrec = parens $ complemented +++ normal + where+ complemented = prec 10 $ do + Ident "complement" <- lexP+ complement `fmap` step readPrec+ normal = prec 10 $ do+ Ident "fromDistinctAscList" <- lexP+ fromDistinctAscList `fmap` step readPrec++instance Monoid CharSet where+ mempty = empty+ mappend = union
+ Text/Trifecta/CharSet/Unicode.hs view
@@ -0,0 +1,177 @@+{-# LANGUAGE DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Unicode+-- Copyright : (c) Edward Kmett 2010+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : portable+--+-- Provides unicode general categories, which are typically connoted by +-- @\p{Ll}@ or @\p{Modifier_Letter}@. Lookups can be constructed using 'categories'+-- or individual character sets can be used directly.+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Unicode+ ( + -- * Unicode General Category+ UnicodeCategory(..)+ -- * Lookup+ , unicodeCategories+ -- * CharSets by UnicodeCategory+ -- ** Letter+ , modifierLetter, otherLetter, letter+ -- *** Letter\&+ , lowercaseLetter, uppercaseLetter, titlecaseLetter, letterAnd+ -- ** Mark+ , nonSpacingMark, spacingCombiningMark, enclosingMark, mark+ -- ** Separator+ , space, lineSeparator, paragraphSeparator, separator+ -- ** Symbol+ , mathSymbol, currencySymbol, modifierSymbol, otherSymbol, symbol+ -- ** Number+ , decimalNumber, letterNumber, otherNumber, number+ -- ** Punctuation+ , dashPunctuation, openPunctuation, closePunctuation, initialQuote+ , finalQuote, connectorPunctuation, otherPunctuation, punctuation + -- ** Other+ , control, format, privateUse, surrogate, notAssigned, other+ ) where++import Data.Char+import Data.Data+import Text.Trifecta.CharSet.Prim++data UnicodeCategory = UnicodeCategory String String CharSet String+ deriving (Show, Data, Typeable)++-- \p{Letter} or \p{Mc}+unicodeCategories :: [UnicodeCategory]+unicodeCategories =+ [ UnicodeCategory "Letter" "L" letter "any kind of letter from any language."+ , UnicodeCategory "Lowercase_Letter" "Ll" lowercaseLetter "a lowercase letter that has an uppercase variant"+ , UnicodeCategory "Uppercase_Letter" "Lu" uppercaseLetter "an uppercase letter that has a lowercase variant"+ , UnicodeCategory "Titlecase_Letter" "Lt" titlecaseLetter "a letter that appears at the start of a word when only the first letter of the word is capitalized"+ , UnicodeCategory "Letter&" "L&" letterAnd "a letter that exists in lowercase and uppercase variants (combination of Ll, Lu and Lt)"+ , UnicodeCategory "Modifier_Letter" "Lm" modifierLetter "a special character that is used like a letter"+ , UnicodeCategory "Other_Letter" "Lo" otherLetter "a letter or ideograph that does not have lowercase and uppercase variants"+ , UnicodeCategory "Mark" "M" mark "a character intended to be combined with another character (e.g. accents, umlauts, enclosing boxes, etc.)"+ , UnicodeCategory "Non_Spacing_Mark" "Mn" nonSpacingMark "a character intended to be combined with another character without taking up extra space (e.g. accents, umlauts, etc.)"+ , UnicodeCategory "Spacing_Combining_Mark" "Mc" spacingCombiningMark "a character intended to be combined with another character that takes up extra space (vowel signs in many Eastern languages)"+ , UnicodeCategory "Enclosing_Mark" "Me" enclosingMark "a character that encloses the character is is combined with (circle, square, keycap, etc.)"+ , UnicodeCategory "Separator" "Z" separator "any kind of whitespace or invisible separator"+ , UnicodeCategory "Space_Separator" "Zs" space "a whitespace character that is invisible, but does take up space"+ , UnicodeCategory "Line_Separator" "Zl" lineSeparator "line separator character U+2028"+ , UnicodeCategory "Paragraph_Separator" "Zp" paragraphSeparator "paragraph separator character U+2029"+ , UnicodeCategory "Symbol" "S" symbol "math symbols, currency signs, dingbats, box-drawing characters, etc."+ , UnicodeCategory "Math_Symbol" "Sm" mathSymbol "any mathematical symbol"+ , UnicodeCategory "Currency_Symbol" "Sc" currencySymbol "any currency sign"+ , UnicodeCategory "Modifier_Symbol" "Sk" modifierSymbol "a combining character (mark) as a full character on its own"+ , UnicodeCategory "Other_Symbol" "So" otherSymbol "various symbols that are not math symbols, currency signs, or combining characters"+ , UnicodeCategory "Number" "N" number "any kind of numeric character in any script"+ , UnicodeCategory "Decimal_Digit_Number" "Nd" decimalNumber "a digit zero through nine in any script except ideographic scripts"+ , UnicodeCategory "Letter_Number" "Nl" letterNumber "a number that looks like a letter, such as a Roman numeral"+ , UnicodeCategory "Other_Number" "No" otherNumber "a superscript or subscript digit, or a number that is not a digit 0..9 (excluding numbers from ideographic scripts)"+ , UnicodeCategory "Punctuation" "P" punctuation "any kind of punctuation character"+ , UnicodeCategory "Dash_Punctuation" "Pd" dashPunctuation "any kind of hyphen or dash"+ , UnicodeCategory "Open_Punctuation" "Ps" openPunctuation "any kind of opening bracket"+ , UnicodeCategory "Close_Punctuation" "Pe" closePunctuation "any kind of closing bracket"+ , UnicodeCategory "Initial_Punctuation" "Pi" initialQuote "any kind of opening quote"+ , UnicodeCategory "Final_Punctuation" "Pf" finalQuote "any kind of closing quote"+ , UnicodeCategory "Connector_Punctuation" "Pc" connectorPunctuation "a punctuation character such as an underscore that connects words"+ , UnicodeCategory "Other_Punctuation" "Po" otherPunctuation "any kind of punctuation character that is not a dash, bracket, quote or connector"+ , UnicodeCategory "Other" "C" other "invisible control characters and unused code points"+ , UnicodeCategory "Control" "Cc" control "an ASCII 0x00..0x1F or Latin-1 0x80..0x9F control character"+ , UnicodeCategory "Format" "Cf" format "invisible formatting indicator"+ , UnicodeCategory "Private_Use" "Co" privateUse "any code point reserved for private use"+ , UnicodeCategory "Surrogate" "Cs" surrogate "one half of a surrogate pair in UTF-16 encoding"+ , UnicodeCategory "Unassigned" "Cn" notAssigned "any code point to which no character has been assigned.properties" ]++cat :: GeneralCategory -> CharSet+cat category = build ((category ==) . generalCategory)++-- Letter+lowercaseLetter, uppercaseLetter, titlecaseLetter, letterAnd, modifierLetter, otherLetter, letter :: CharSet+lowercaseLetter = cat LowercaseLetter+uppercaseLetter = cat UppercaseLetter+titlecaseLetter = cat TitlecaseLetter+letterAnd = lowercaseLetter + `union` uppercaseLetter + `union` titlecaseLetter+modifierLetter = cat ModifierLetter+otherLetter = cat OtherLetter+letter + = letterAnd + `union` modifierLetter + `union` otherLetter++-- Marks+nonSpacingMark, spacingCombiningMark, enclosingMark, mark :: CharSet+nonSpacingMark = cat NonSpacingMark+spacingCombiningMark = cat SpacingCombiningMark+enclosingMark = cat EnclosingMark+mark + = nonSpacingMark + `union` spacingCombiningMark + `union` enclosingMark++space, lineSeparator, paragraphSeparator, separator :: CharSet+space = cat Space+lineSeparator = cat LineSeparator+paragraphSeparator = cat ParagraphSeparator+separator + = space + `union` lineSeparator + `union` paragraphSeparator++mathSymbol, currencySymbol, modifierSymbol, otherSymbol, symbol :: CharSet+mathSymbol = cat MathSymbol+currencySymbol = cat CurrencySymbol+modifierSymbol = cat ModifierSymbol+otherSymbol = cat OtherSymbol+symbol + = mathSymbol + `union` currencySymbol + `union` modifierSymbol + `union` otherSymbol++decimalNumber, letterNumber, otherNumber, number :: CharSet+decimalNumber = cat DecimalNumber+letterNumber = cat LetterNumber+otherNumber = cat OtherNumber+number + = decimalNumber + `union` letterNumber + `union` otherNumber++dashPunctuation, openPunctuation, closePunctuation, initialQuote, + finalQuote, connectorPunctuation, otherPunctuation, punctuation :: CharSet++dashPunctuation = cat DashPunctuation+openPunctuation = cat OpenPunctuation+closePunctuation = cat ClosePunctuation+initialQuote = cat InitialQuote+finalQuote = cat FinalQuote+connectorPunctuation = cat ConnectorPunctuation+otherPunctuation = cat OtherPunctuation+punctuation + = dashPunctuation + `union` openPunctuation + `union` closePunctuation + `union` initialQuote + `union` finalQuote + `union` connectorPunctuation + `union` otherPunctuation++control, format, privateUse, surrogate, notAssigned, other :: CharSet+control = cat Control+format = cat Format+privateUse = cat PrivateUse+surrogate = cat Surrogate+notAssigned = cat NotAssigned+other = control + `union` format + `union` privateUse + `union` surrogate + `union` notAssigned
+ Text/Trifecta/CharSet/Unicode/Block.hs view
@@ -0,0 +1,382 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Unicode.Block+-- Copyright : (c) Edward Kmett 2010-2011+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : portable+--+-- Provides unicode general categories, which are typically connoted by +-- @\p{InBasicLatin}@ or @\p{InIPA_Extensions}@. Lookups can be constructed using 'categories'+-- or individual character sets can be used directly.+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Unicode.Block+ ( + -- * Unicode General Category+ Block(..)+ -- * Lookup+ , blocks+ , lookupBlock+ , lookupBlockCharSet+ -- * CharSets by Block+ , basicLatin+ , latin1Supplement+ , latinExtendedA+ , latinExtendedB+ , ipaExtensions+ , spacingModifierLetters+ , combiningDiacriticalMarks+ , greekAndCoptic+ , cyrillic+ , cyrillicSupplementary+ , armenian+ , hebrew+ , arabic+ , syriac+ , thaana+ , devanagari+ , bengali+ , gurmukhi+ , gujarati+ , oriya+ , tamil+ , telugu+ , kannada+ , malayalam+ , sinhala+ , thai+ , lao+ , tibetan+ , myanmar+ , georgian+ , hangulJamo+ , ethiopic+ , cherokee+ , unifiedCanadianAboriginalSyllabics+ , ogham+ , runic+ , tagalog+ , hanunoo+ , buhid+ , tagbanwa+ , khmer+ , mongolian+ , limbu+ , taiLe+ , khmerSymbols+ , phoneticExtensions+ , latinExtendedAdditional+ , greekExtended+ , generalPunctuation+ , superscriptsAndSubscripts+ , currencySymbols+ , combiningDiacriticalMarksForSymbols+ , letterlikeSymbols+ , numberForms+ , arrows+ , mathematicalOperators+ , miscellaneousTechnical+ , controlPictures+ , opticalCharacterRecognition+ , enclosedAlphanumerics+ , boxDrawing+ , blockElements+ , geometricShapes+ , miscellaneousSymbols+ , dingbats+ , miscellaneousMathematicalSymbolsA+ , supplementalArrowsA+ , braillePatterns+ , supplementalArrowsB+ , miscellaneousMathematicalSymbolsB+ , supplementalMathematicalOperators+ , miscellaneousSymbolsAndArrows+ , cjkRadicalsSupplement+ , kangxiRadicals+ , ideographicDescriptionCharacters+ , cjkSymbolsAndPunctuation+ , hiragana+ , katakana+ , bopomofo+ , hangulCompatibilityJamo+ , kanbun+ , bopomofoExtended+ , katakanaPhoneticExtensions+ , enclosedCjkLettersAndMonths+ , cjkCompatibility+ , cjkUnifiedIdeographsExtensionA+ , yijingHexagramSymbols+ , cjkUnifiedIdeographs+ , yiSyllables+ , yiRadicals+ , hangulSyllables+ , highSurrogates+ , highPrivateUseSurrogates+ , lowSurrogates+ , privateUseArea+ , cjkCompatibilityIdeographs+ , alphabeticPresentationForms+ , arabicPresentationFormsA+ , variationSelectors+ , combiningHalfMarks+ , cjkCompatibilityForms+ , smallFormVariants+ , arabicPresentationFormsB+ , halfwidthAndFullwidthForms+ , specials+ ) where++import Data.Char+import Text.Trifecta.CharSet.Prim+import Data.Data+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HashMap++data Block = Block + { blockName :: String+ , blockCharSet :: CharSet+ } deriving (Show, Data, Typeable)++blocks :: [Block]+blocks =+ [ Block "Basic_Latin" basicLatin+ , Block "Latin-1_Supplement" latin1Supplement+ , Block "Latin_Extended-A" latinExtendedA+ , Block "IPA_Extensions" ipaExtensions+ , Block "Spacing_Modifier_Letters" spacingModifierLetters++ , Block "Latin_Extended-A" latinExtendedA+ , Block "Latin_Extended-B" latinExtendedB+ , Block "IPA_Extensions" ipaExtensions+ , Block "Spacing_Modifier_Letters" spacingModifierLetters+ , Block "Combining_Diacritical_Marks" combiningDiacriticalMarks+ , Block "Greek_and_Coptic" greekAndCoptic+ , Block "Cyrillic" cyrillic+ , Block "Cyrillic_Supplementary" cyrillicSupplementary+ , Block "Armenian" armenian+ , Block "Hebrew" hebrew+ , Block "Arabic" arabic+ , Block "Syriac" syriac+ , Block "Thaana" thaana+ , Block "Devanagari" devanagari+ , Block "Bengali" bengali+ , Block "Gurmukhi" gurmukhi+ , Block "Gujarati" gujarati+ , Block "Oriya" oriya+ , Block "Tamil" tamil+ , Block "Telugu" telugu+ , Block "Kannada" kannada+ , Block "Malayalam" malayalam+ , Block "Sinhala" sinhala+ , Block "Thai" thai+ , Block "Lao" lao+ , Block "Tibetan" tibetan+ , Block "Myanmar" myanmar+ , Block "Georgian" georgian+ , Block "Hangul_Jamo" hangulJamo+ , Block "Ethiopic" ethiopic+ , Block "Cherokee" cherokee+ , Block "Unified_Canadian_Aboriginal_Syllabics" unifiedCanadianAboriginalSyllabics+ , Block "Ogham" ogham+ , Block "Runic" runic+ , Block "Tagalog" tagalog+ , Block "Hanunoo" hanunoo+ , Block "Buhid" buhid+ , Block "Tagbanwa" tagbanwa+ , Block "Khmer" khmer+ , Block "Mongolian" mongolian+ , Block "Limbu" limbu+ , Block "Tai_Le" taiLe+ , Block "Khmer_Symbols" khmerSymbols+ , Block "Phonetic_Extensions" phoneticExtensions+ , Block "Latin_Extended_Additional" latinExtendedAdditional+ , Block "Greek_Extended" greekExtended+ , Block "General_Punctuation" generalPunctuation+ , Block "Superscripts_and_Subscripts" superscriptsAndSubscripts+ , Block "Currency_Symbols" currencySymbols+ , Block "Combining_Diacritical_Marks_for_Symbols" combiningDiacriticalMarksForSymbols+ , Block "Letterlike_Symbols" letterlikeSymbols+ , Block "Number_Forms" numberForms+ , Block "Arrows" arrows+ , Block "Mathematical_Operators" mathematicalOperators+ , Block "Miscellaneous_Technical" miscellaneousTechnical+ , Block "Control_Pictures" controlPictures+ , Block "Optical_Character_Recognition" opticalCharacterRecognition+ , Block "Enclosed_Alphanumerics" enclosedAlphanumerics+ , Block "Box_Drawing" boxDrawing+ , Block "Block_Elements" blockElements+ , Block "Geometric_Shapes" geometricShapes+ , Block "Miscellaneous_Symbols" miscellaneousSymbols+ , Block "Dingbats" dingbats+ , Block "Miscellaneous_Mathematical_Symbols-A" miscellaneousMathematicalSymbolsA+ , Block "Supplemental_Arrows-A" supplementalArrowsA+ , Block "Braille_Patterns" braillePatterns+ , Block "Supplemental_Arrows-B" supplementalArrowsB+ , Block "Miscellaneous_Mathematical_Symbols-B" miscellaneousMathematicalSymbolsB+ , Block "Supplemental_Mathematical_Operators" supplementalMathematicalOperators+ , Block "Miscellaneous_Symbols_and_Arrows" miscellaneousSymbolsAndArrows+ , Block "CJK_Radicals_Supplement" cjkRadicalsSupplement+ , Block "Kangxi_Radicals" kangxiRadicals+ , Block "Ideographic_Description_Characters" ideographicDescriptionCharacters+ , Block "CJK_Symbols_and_Punctuation" cjkSymbolsAndPunctuation+ , Block "Hiragana" hiragana+ , Block "Katakana" katakana+ , Block "Bopomofo" bopomofo+ , Block "Hangul_Compatibility_Jamo" hangulCompatibilityJamo+ , Block "Kanbun" kanbun+ , Block "Bopomofo_Extended" bopomofoExtended+ , Block "Katakana_Phonetic_Extensions" katakanaPhoneticExtensions+ , Block "Enclosed_CJK_Letters_and_Months" enclosedCjkLettersAndMonths+ , Block "CJK_Compatibility" cjkCompatibility+ , Block "CJK_Unified_Ideographs_Extension_A" cjkUnifiedIdeographsExtensionA+ , Block "Yijing_Hexagram_Symbols" yijingHexagramSymbols+ , Block "CJK_Unified_Ideographs" cjkUnifiedIdeographs+ , Block "Yi_Syllables" yiSyllables+ , Block "Yi_Radicals" yiRadicals+ , Block "Hangul_Syllables" hangulSyllables+ , Block "High_Surrogates" highSurrogates+ , Block "High_Private_Use_Surrogates" highPrivateUseSurrogates+ , Block "Low_Surrogates" lowSurrogates+ , Block "Private_Use_Area" privateUseArea+ , Block "CJK_Compatibility_Ideographs" cjkCompatibilityIdeographs+ , Block "Alphabetic_Presentation_Forms" alphabeticPresentationForms+ , Block "Arabic_Presentation_Forms-A" arabicPresentationFormsA+ , Block "Variation_Selectors" variationSelectors+ , Block "Combining_Half_Marks" combiningHalfMarks+ , Block "CJK_Compatibility_Forms" cjkCompatibilityForms+ , Block "Small_Form_Variants" smallFormVariants+ , Block "Arabic_Presentation_Forms-B" arabicPresentationFormsB+ , Block "Halfwidth_and_Fullwidth_Forms" halfwidthAndFullwidthForms+ , Block "Specials" specials ]++lookupTable :: HashMap String Block+lookupTable = HashMap.fromList $ + Prelude.map (\y@(Block x _) -> (canonicalize x, y))+ blocks++canonicalize :: String -> String+canonicalize s = case Prelude.map toLower s of+ 'i': 'n' : xs -> go xs+ xs -> go xs+ where+ go ('-':xs) = go xs+ go ('_':xs) = go xs+ go (' ':xs) = go xs+ go (x:xs) = x : go xs+ go [] = []++lookupBlock :: String -> Maybe Block+lookupBlock s = HashMap.lookup (canonicalize s) lookupTable++lookupBlockCharSet :: String -> Maybe CharSet+lookupBlockCharSet = fmap blockCharSet . lookupBlock++basicLatin = range '\x0000' '\x007f'+latin1Supplement = range '\x0080' '\x00ff'+latinExtendedA = range '\x0100' '\x017F'+latinExtendedB = range '\x0180' '\x024F'+ipaExtensions = range '\x0250' '\x02AF'+spacingModifierLetters = range '\x02B0' '\x02FF'+combiningDiacriticalMarks = range '\x0300' '\x036F'+greekAndCoptic = range '\x0370' '\x03FF'+cyrillic = range '\x0400' '\x04FF'+cyrillicSupplementary = range '\x0500' '\x052F'+armenian = range '\x0530' '\x058F'+hebrew = range '\x0590' '\x05FF'+arabic = range '\x0600' '\x06FF'+syriac = range '\x0700' '\x074F'+thaana = range '\x0780' '\x07BF'+devanagari = range '\x0900' '\x097F'+bengali = range '\x0980' '\x09FF'+gurmukhi = range '\x0A00' '\x0A7F'+gujarati = range '\x0A80' '\x0AFF'+oriya = range '\x0B00' '\x0B7F'+tamil = range '\x0B80' '\x0BFF'+telugu = range '\x0C00' '\x0C7F'+kannada = range '\x0C80' '\x0CFF'+malayalam = range '\x0D00' '\x0D7F'+sinhala = range '\x0D80' '\x0DFF'+thai = range '\x0E00' '\x0E7F'+lao = range '\x0E80' '\x0EFF'+tibetan = range '\x0F00' '\x0FFF'+myanmar = range '\x1000' '\x109F'+georgian = range '\x10A0' '\x10FF'+hangulJamo = range '\x1100' '\x11FF'+ethiopic = range '\x1200' '\x137F'+cherokee = range '\x13A0' '\x13FF'+unifiedCanadianAboriginalSyllabics = range '\x1400' '\x167F'+ogham = range '\x1680' '\x169F'+runic = range '\x16A0' '\x16FF'+tagalog = range '\x1700' '\x171F'+hanunoo = range '\x1720' '\x173F'+buhid = range '\x1740' '\x175F'+tagbanwa = range '\x1760' '\x177F'+khmer = range '\x1780' '\x17FF'+mongolian = range '\x1800' '\x18AF'+limbu = range '\x1900' '\x194F'+taiLe = range '\x1950' '\x197F'+khmerSymbols = range '\x19E0' '\x19FF'+phoneticExtensions = range '\x1D00' '\x1D7F'+latinExtendedAdditional = range '\x1E00' '\x1EFF'+greekExtended = range '\x1F00' '\x1FFF'+generalPunctuation = range '\x2000' '\x206F'+superscriptsAndSubscripts = range '\x2070' '\x209F'+currencySymbols = range '\x20A0' '\x20CF'+combiningDiacriticalMarksForSymbols = range '\x20D0' '\x20FF'+letterlikeSymbols = range '\x2100' '\x214F'+numberForms = range '\x2150' '\x218F'+arrows = range '\x2190' '\x21FF'+mathematicalOperators = range '\x2200' '\x22FF'+miscellaneousTechnical = range '\x2300' '\x23FF'+controlPictures = range '\x2400' '\x243F'+opticalCharacterRecognition = range '\x2440' '\x245F'+enclosedAlphanumerics = range '\x2460' '\x24FF'+boxDrawing = range '\x2500' '\x257F'+blockElements = range '\x2580' '\x259F'+geometricShapes = range '\x25A0' '\x25FF'+miscellaneousSymbols = range '\x2600' '\x26FF'+dingbats = range '\x2700' '\x27BF'+miscellaneousMathematicalSymbolsA = range '\x27C0' '\x27EF'+supplementalArrowsA = range '\x27F0' '\x27FF'+braillePatterns = range '\x2800' '\x28FF'+supplementalArrowsB = range '\x2900' '\x297F'+miscellaneousMathematicalSymbolsB = range '\x2980' '\x29FF'+supplementalMathematicalOperators = range '\x2A00' '\x2AFF'+miscellaneousSymbolsAndArrows = range '\x2B00' '\x2BFF'+cjkRadicalsSupplement = range '\x2E80' '\x2EFF'+kangxiRadicals = range '\x2F00' '\x2FDF'+ideographicDescriptionCharacters = range '\x2FF0' '\x2FFF'+cjkSymbolsAndPunctuation = range '\x3000' '\x303F'+hiragana = range '\x3040' '\x309F'+katakana = range '\x30A0' '\x30FF'+bopomofo = range '\x3100' '\x312F'+hangulCompatibilityJamo = range '\x3130' '\x318F'+kanbun = range '\x3190' '\x319F'+bopomofoExtended = range '\x31A0' '\x31BF'+katakanaPhoneticExtensions = range '\x31F0' '\x31FF'+enclosedCjkLettersAndMonths = range '\x3200' '\x32FF'+cjkCompatibility = range '\x3300' '\x33FF'+cjkUnifiedIdeographsExtensionA = range '\x3400' '\x4DBF'+yijingHexagramSymbols = range '\x4DC0' '\x4DFF'+cjkUnifiedIdeographs = range '\x4E00' '\x9FFF'+yiSyllables = range '\xA000' '\xA48F'+yiRadicals = range '\xA490' '\xA4CF'+hangulSyllables = range '\xAC00' '\xD7AF'+highSurrogates = range '\xD800' '\xDB7F'+highPrivateUseSurrogates = range '\xDB80' '\xDBFF'+lowSurrogates = range '\xDC00' '\xDFFF'+privateUseArea = range '\xE000' '\xF8FF'+cjkCompatibilityIdeographs = range '\xF900' '\xFAFF'+alphabeticPresentationForms = range '\xFB00' '\xFB4F'+arabicPresentationFormsA = range '\xFB50' '\xFDFF'+variationSelectors = range '\xFE00' '\xFE0F'+combiningHalfMarks = range '\xFE20' '\xFE2F'+cjkCompatibilityForms = range '\xFE30' '\xFE4F'+smallFormVariants = range '\xFE50' '\xFE6F'+arabicPresentationFormsB = range '\xFE70' '\xFEFF'+halfwidthAndFullwidthForms = range '\xFF00' '\xFFEF'+specials = range '\xFFF0' '\xFFFF'
+ Text/Trifecta/CharSet/Unicode/Category.hs view
@@ -0,0 +1,212 @@+{-# LANGUAGE DeriveDataTypeable #-}+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.CharSet.Unicode.Category+-- Copyright : (c) Edward Kmett 2010-2011+-- License : BSD3+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : portable+--+-- Provides unicode general categories, which are typically connoted by +-- @\p{Ll}@ or @\p{Modifier_Letter}@. Lookups can be constructed using 'categories'+-- or individual character sets can be used directly.+-- +-- A case, @_@ and @-@ insensitive lookup is provided by 'lookupCategory'+-- and can be used to provide behavior similar to that of Perl or PCRE.+-------------------------------------------------------------------------------++module Text.Trifecta.CharSet.Unicode.Category+ ( + -- * Unicode General Category+ Category(..)+ -- * Lookup+ , categories+ , lookupCategory+ , lookupCategoryCharSet+ -- * CharSets by Category+ -- ** Letter+ , modifierLetter, otherLetter, letter+ -- *** Letter\&+ , lowercaseLetter, uppercaseLetter, titlecaseLetter, letterAnd+ -- ** Mark+ , nonSpacingMark, spacingCombiningMark, enclosingMark, mark+ -- ** Separator+ , space, lineSeparator, paragraphSeparator, separator+ -- ** Symbol+ , mathSymbol, currencySymbol, modifierSymbol, otherSymbol, symbol+ -- ** Number+ , decimalNumber, letterNumber, otherNumber, number+ -- ** Punctuation+ , dashPunctuation, openPunctuation, closePunctuation, initialQuote+ , finalQuote, connectorPunctuation, otherPunctuation, punctuation + -- ** Other+ , control, format, privateUse, surrogate, notAssigned, other+ ) where++import Data.Char+import Text.Trifecta.CharSet.Prim+import Data.Data+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HashMap++data Category = Category + { categoryName :: String+ , categoryAbbreviation :: String+ , categoryCharSet :: CharSet+ , categoryDescription :: String+ } deriving (Show, Data, Typeable)++-- \p{Letter} or \p{Mc}+categories :: [Category]+categories =+ [ Category "Letter" "L" letter "any kind of letter from any language."+ , Category "Lowercase_Letter" "Ll" lowercaseLetter "a lowercase letter that has an uppercase variant"+ , Category "Uppercase_Letter" "Lu" uppercaseLetter "an uppercase letter that has a lowercase variant"+ , Category "Titlecase_Letter" "Lt" titlecaseLetter "a letter that appears at the start of a word when only the first letter of the word is capitalized"+ , Category "Letter&" "L&" letterAnd "a letter that exists in lowercase and uppercase variants (combination of Ll, Lu and Lt)"+ , Category "Modifier_Letter" "Lm" modifierLetter "a special character that is used like a letter"+ , Category "Other_Letter" "Lo" otherLetter "a letter or ideograph that does not have lowercase and uppercase variants"+ , Category "Mark" "M" mark "a character intended to be combined with another character (e.g. accents, umlauts, enclosing boxes, etc.)"+ , Category "Non_Spacing_Mark" "Mn" nonSpacingMark "a character intended to be combined with another character without taking up extra space (e.g. accents, umlauts, etc.)"+ , Category "Spacing_Combining_Mark" "Mc" spacingCombiningMark "a character intended to be combined with another character that takes up extra space (vowel signs in many Eastern languages)"+ , Category "Enclosing_Mark" "Me" enclosingMark "a character that encloses the character is is combined with (circle, square, keycap, etc.)"+ , Category "Separator" "Z" separator "any kind of whitespace or invisible separator"+ , Category "Space_Separator" "Zs" space "a whitespace character that is invisible, but does take up space"+ , Category "Line_Separator" "Zl" lineSeparator "line separator character U+2028"+ , Category "Paragraph_Separator" "Zp" paragraphSeparator "paragraph separator character U+2029"+ , Category "Symbol" "S" symbol "math symbols, currency signs, dingbats, box-drawing characters, etc."+ , Category "Math_Symbol" "Sm" mathSymbol "any mathematical symbol"+ , Category "Currency_Symbol" "Sc" currencySymbol "any currency sign"+ , Category "Modifier_Symbol" "Sk" modifierSymbol "a combining character (mark) as a full character on its own"+ , Category "Other_Symbol" "So" otherSymbol "various symbols that are not math symbols, currency signs, or combining characters"+ , Category "Number" "N" number "any kind of numeric character in any script"+ , Category "Decimal_Digit_Number" "Nd" decimalNumber "a digit zero through nine in any script except ideographic scripts"+ , Category "Letter_Number" "Nl" letterNumber "a number that looks like a letter, such as a Roman numeral"+ , Category "Other_Number" "No" otherNumber "a superscript or subscript digit, or a number that is not a digit 0..9 (excluding numbers from ideographic scripts)"+ , Category "Punctuation" "P" punctuation "any kind of punctuation character"+ , Category "Dash_Punctuation" "Pd" dashPunctuation "any kind of hyphen or dash"+ , Category "Open_Punctuation" "Ps" openPunctuation "any kind of opening bracket"+ , Category "Close_Punctuation" "Pe" closePunctuation "any kind of closing bracket"+ , Category "Initial_Punctuation" "Pi" initialQuote "any kind of opening quote"+ , Category "Final_Punctuation" "Pf" finalQuote "any kind of closing quote"+ , Category "Connector_Punctuation" "Pc" connectorPunctuation "a punctuation character such as an underscore that connects words"+ , Category "Other_Punctuation" "Po" otherPunctuation "any kind of punctuation character that is not a dash, bracket, quote or connector"+ , Category "Other" "C" other "invisible control characters and unused code points"+ , Category "Control" "Cc" control "an ASCII 0x00..0x1F or Latin-1 0x80..0x9F control character"+ , Category "Format" "Cf" format "invisible formatting indicator"+ , Category "Private_Use" "Co" privateUse "any code point reserved for private use"+ , Category "Surrogate" "Cs" surrogate "one half of a surrogate pair in UTF-16 encoding"+ , Category "Unassigned" "Cn" notAssigned "any code point to which no character has been assigned.properties" ]++lookupTable :: HashMap String Category+lookupTable = HashMap.fromList + [ (canonicalize x, category) + | category@(Category l s _ _) <- categories+ , x <- [l,s] + ]++lookupCategory :: String -> Maybe Category+lookupCategory s = HashMap.lookup (canonicalize s) lookupTable++lookupCategoryCharSet :: String -> Maybe CharSet+lookupCategoryCharSet = fmap categoryCharSet . lookupCategory++canonicalize :: String -> String+canonicalize s = case Prelude.map toLower s of+ 'i' : 's' : xs -> go xs+ xs -> go xs+ where+ go ('-':xs) = go xs+ go ('_':xs) = go xs+ go (' ':xs) = go xs+ go (x:xs) = x : go xs+ go [] = []++cat :: GeneralCategory -> CharSet+cat category = build ((category ==) . generalCategory)++-- Letter+lowercaseLetter, uppercaseLetter, titlecaseLetter, letterAnd, modifierLetter, otherLetter, letter :: CharSet+lowercaseLetter = cat LowercaseLetter+uppercaseLetter = cat UppercaseLetter+titlecaseLetter = cat TitlecaseLetter+letterAnd = lowercaseLetter + `union` uppercaseLetter + `union` titlecaseLetter+modifierLetter = cat ModifierLetter+otherLetter = cat OtherLetter+letter + = letterAnd + `union` modifierLetter + `union` otherLetter++-- Marks+nonSpacingMark, spacingCombiningMark, enclosingMark, mark :: CharSet+nonSpacingMark = cat NonSpacingMark+spacingCombiningMark = cat SpacingCombiningMark+enclosingMark = cat EnclosingMark+mark + = nonSpacingMark + `union` spacingCombiningMark + `union` enclosingMark++space, lineSeparator, paragraphSeparator, separator :: CharSet+space = cat Space+lineSeparator = cat LineSeparator+paragraphSeparator = cat ParagraphSeparator+separator + = space + `union` lineSeparator + `union` paragraphSeparator++mathSymbol, currencySymbol, modifierSymbol, otherSymbol, symbol :: CharSet+mathSymbol = cat MathSymbol+currencySymbol = cat CurrencySymbol+modifierSymbol = cat ModifierSymbol+otherSymbol = cat OtherSymbol+symbol + = mathSymbol + `union` currencySymbol + `union` modifierSymbol + `union` otherSymbol++decimalNumber, letterNumber, otherNumber, number :: CharSet+decimalNumber = cat DecimalNumber+letterNumber = cat LetterNumber+otherNumber = cat OtherNumber+number + = decimalNumber + `union` letterNumber + `union` otherNumber++dashPunctuation, openPunctuation, closePunctuation, initialQuote, + finalQuote, connectorPunctuation, otherPunctuation, punctuation :: CharSet++dashPunctuation = cat DashPunctuation+openPunctuation = cat OpenPunctuation+closePunctuation = cat ClosePunctuation+initialQuote = cat InitialQuote+finalQuote = cat FinalQuote+connectorPunctuation = cat ConnectorPunctuation+otherPunctuation = cat OtherPunctuation+punctuation + = dashPunctuation + `union` openPunctuation + `union` closePunctuation + `union` initialQuote + `union` finalQuote + `union` connectorPunctuation + `union` otherPunctuation++control, format, privateUse, surrogate, notAssigned, other :: CharSet+control = cat Control+format = cat Format+privateUse = cat PrivateUse+surrogate = cat Surrogate+notAssigned = cat NotAssigned+other = control + `union` format + `union` privateUse + `union` surrogate + `union` notAssigned
− Text/Trifecta/Delta.hs
@@ -1,155 +0,0 @@-module Text.Trifecta.Delta - ( Delta(..) - , HasDelta(..)- , nextTab- , rewind- , near- , column- , columnByte- ) where--import Control.Applicative-import Data.Monoid-import Data.Semigroup-import Data.Hashable-import Data.Word-import Data.Interned-import Data.Foldable-import Data.FingerTree hiding (empty)-import Data.ByteString hiding (empty)-import Text.Trifecta.Path-import Text.Trifecta.Bytes-import Text.PrettyPrint.Free hiding (column)-import System.Console.Terminfo.PrettyPrint--data Delta- = Columns {-# UNPACK #-} !Int -- the number of characters- {-# UNPACK #-} !Int -- the number of bytes- | Tab {-# UNPACK #-} !Int -- the number of characters before the tab- {-# UNPACK #-} !Int -- the number of characters after the tab- {-# UNPACK #-} !Int -- the number of bytes- | Lines {-# UNPACK #-} !Int -- the number of newlines contained- {-# UNPACK #-} !Int -- the number of characters since the last newline- {-# UNPACK #-} !Int -- number of bytes- {-# UNPACK #-} !Int -- the number of bytes since the last newline- | Directed !Path -- the sequence of #line directives since the start of the file- {-# UNPACK #-} !Int -- the number of lines since the last line directive- {-# UNPACK #-} !Int -- the number of characters since the last newline- {-# UNPACK #-} !Int -- number of bytes- {-# UNPACK #-} !Int -- the number of bytes since the last newline- deriving (Eq, Ord, Show)--columnByte :: Delta -> Int-columnByte (Columns _ b) = b-columnByte (Tab _ _ b) = b-columnByte (Lines _ _ _ b) = b-columnByte (Directed _ _ _ _ b) = b--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 "-" 1 c- Tab x y _ -> k "-" 1 (nextTab x + y)- Lines l c _ _ -> k "-" l c- Directed (Path _ _ _ fn _ _) l c _ _ -> k (maybeFileName "-" unintern fn) l c -- TODO: add include path- where - k fn ln cn = bold (string fn) - <> char ':' - <> bold (int ln) - <> char ':' - <> bold (int (cn + 1))--column :: HasDelta t => t -> Int-column t = case delta t of - Columns c _ -> c- Tab b a _ -> nextTab b + a- Lines _ c _ _ -> c- Directed _ _ c _ _ -> c--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 a <> Lines m d t' b = Directed p (l + m) d (t + t') (a + b)- Directed p l _ t _ <> Directed p' l' c' t' b = Directed (appendPath p l p') l' c' (t + t') b- -nextTab :: Int -> Int-nextTab x = x + (8 - mod x 8)--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 --near :: (HasDelta s, HasDelta t) => s -> t -> Bool-near s t = case (delta s, delta t) of- (Directed p l _ _ _, Directed p' l' _ _ _) -> p == p' && l == l'- (Lines l _ _ _, Lines l' _ _ _) -> l == l'- (Columns _ _, Columns _ _) -> True- (Columns _ _, Tab _ _ _) -> True- (Tab _ _ _, Columns _ _) -> True- (Tab _ _ _, Tab _ _ _) -> True- _ -> False--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 HasDelta Path where- delta p = Directed p 0 0 0 0--instance (Measured v a, HasDelta v) => HasDelta (FingerTree v a) where- delta = delta . measure
Text/Trifecta/Diagnostic.hs view
@@ -1,82 +1,15 @@-{-# LANGUAGE FlexibleContexts #-} module Text.Trifecta.Diagnostic ( Diagnostic(..) , tellDiagnostic+ , DiagnosticLevel(..)+ , Renderable(..)+ , Source+ , rendering+ , Caret(..), Careted(..)+ , Span(..), Spanned(..)+ , Fixit(..), Rendered(..) ) where -import Control.Applicative-import Control.Comonad-import Control.Monad (guard)-import Control.Monad.Writer.Class-import Data.Functor.Apply-import Data.Foldable-import Data.Traversable-import Data.Monoid-import Data.List.NonEmpty hiding (map)-import Data.Semigroup-import Data.Semigroup.Reducer-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Text.Trifecta.Bytes-import Text.Trifecta.Delta-import Text.Trifecta.Render.Prim+import Text.Trifecta.Diagnostic.Prim import Text.Trifecta.Diagnostic.Level-import Text.PrettyPrint.Free-import System.Console.Terminfo.PrettyPrint-import Prelude hiding (log)--data Diagnostic m = Diagnostic !Render !DiagnosticLevel m [Diagnostic m]- deriving Show--tellDiagnostic :: (MonadWriter t m, Reducer (Diagnostic e) t) => Diagnostic e -> m ()-tellDiagnostic = tell . unit--instance Renderable (Diagnostic m) where- render (Diagnostic r _ _ _) = r--instance HasDelta (Diagnostic m) where- delta (Diagnostic r _ _ _) = delta r--instance HasBytes (Diagnostic m) where- bytes = bytes . delta--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 r l m xs) = vsep $- [ pretty (delta r) <> char ':' <+> pretty l <> char ':' <+> nest 4 (pretty m) ] - <> (pretty r <$ guard (not (nullRender r)))- <> (indent 2 (prettyList xs) <$ guard (not (null xs)))- prettyList = Prelude.foldr ((<>) . pretty) empty--instance PrettyTerm m => PrettyTerm (Diagnostic m) where- prettyTerm (Diagnostic r l m xs) = vsep $ - [ prettyTerm (delta r) <> char ':' <+> prettyTerm l <> char ':' <+> nest 4 (prettyTerm m) ]- <> (prettyTerm r <$ guard (not (nullRender r)))- <> (indent 2 (prettyTermList xs) <$ guard (not (null xs)))- prettyTermList = Prelude.foldr ((<>) . prettyTerm) empty--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)--+import Text.Trifecta.Diagnostic.Rendering
+ Text/Trifecta/Diagnostic/Err.hs view
@@ -0,0 +1,82 @@+module Text.Trifecta.Diagnostic.Err+ ( Err(..)+ , diagnose+ , knownErr+ ) where++import Control.Applicative+import Control.Comonad+import Data.Semigroup+import Data.Monoid+import Data.Functor.Plus+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Level+import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.PrettyPrint.Free+import System.Console.Terminfo.PrettyPrint++-- | unlocated error messages+data Err e+ = EmptyErr+ | FailErr String + | UnexpectedErr String+ | EndOfFileErr+ | RichErr (Rendering -> Diagnostic e)++instance Show (Err e) where+ showsPrec _ EmptyErr = showString "EmptyErr"+ showsPrec d (FailErr s) = showParen (d > 10) $+ showString "FailErr " . showsPrec 11 s+ showsPrec d (UnexpectedErr s) = showParen (d > 10) $+ showString "UnexpectedErr " . showsPrec 11 s+ showsPrec _ EndOfFileErr = showString "EndOfFileErr"+ showsPrec d (RichErr _) = showParen (d > 10) $ + showString "RichErr ..."++knownErr :: Err e -> Bool+knownErr EmptyErr = False+knownErr _ = True++diagnose :: (t -> Doc e) -> Rendering -> Err t -> Diagnostic (Doc e)+diagnose _ r EmptyErr = Diagnostic r Error (text "unexpected") []+diagnose _ r (FailErr m) = Diagnostic r Error (fillSep $ text <$> words m) []+diagnose _ r (UnexpectedErr s) = Diagnostic r Error (fillSep $ fmap text $ "unexpected" : words s) []+diagnose _ r EndOfFileErr = Diagnostic r Error (text "unexpected EOF") []+diagnose k r (RichErr f) = fmap k (f r)++diagnose0 :: Pretty t => Err t -> Diagnostic (Doc e)+diagnose0 = diagnose pretty emptyRendering++diagnoseTerm0 :: PrettyTerm t => Err t -> Diagnostic TermDoc+diagnoseTerm0 = diagnose prettyTerm emptyRendering++instance Pretty t => Pretty (Err t) where+ pretty = pretty . extract . diagnose0+ prettyList = prettyList . map (extract . diagnose0)++instance PrettyTerm t => PrettyTerm (Err t) where+ prettyTerm = prettyTerm . diagnoseTerm0+ prettyTermList = prettyTermList . map diagnoseTerm0+ +instance Functor Err where+ fmap _ EmptyErr = EmptyErr+ fmap _ (FailErr s) = FailErr s+ fmap _ EndOfFileErr = EndOfFileErr+ fmap _ (UnexpectedErr s) = UnexpectedErr s + fmap f (RichErr k) = RichErr (fmap f . k)++instance Alt Err where+ EmptyErr <!> a = a+ a <!> _ = a+ {-# INLINE (<!>) #-}++instance Plus Err where+ zero = EmptyErr++instance Semigroup (Err t) where+ (<>) = (<!>)+ replicate1p _ = id++instance Monoid (Err t) where+ mempty = EmptyErr+ mappend = (<!>)
+ Text/Trifecta/Diagnostic/Err/State.hs view
@@ -0,0 +1,34 @@+module Text.Trifecta.Diagnostic.Err.State + ( ErrState(..)+ ) where++import Data.Functor.Plus+import Data.Set as Set+import Data.Sequence as Seq+import Data.Semigroup+import Data.Monoid+import Text.Trifecta.Diagnostic.Err+import Text.Trifecta.Diagnostic++data ErrState e = ErrState+ { errExpected :: !(Set String)+ , errMessage :: !(Err e)+ , errLog :: !(Seq (Diagnostic e))+ }++instance Functor ErrState where+ fmap f (ErrState a b c) = ErrState a (fmap f b) (fmap (fmap f) c)++instance Alt ErrState where+ ErrState a b c <!> ErrState a' b' c' = ErrState (a <> a') (b <!> b') (c <!> c')+ {-# INLINE (<!>) #-}++instance Plus ErrState where+ zero = ErrState mempty zero zero+ +instance Semigroup (ErrState e) where+ (<>) = (<!>) ++instance Monoid (ErrState e) where+ mempty = zero+ mappend = (<!>)
+ Text/Trifecta/Diagnostic/Prim.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE FlexibleContexts #-}+module Text.Trifecta.Diagnostic.Prim+ ( Diagnostic(..)+ , tellDiagnostic+ ) where++import Control.Applicative+import Control.Comonad+import Control.Monad (guard)+import Control.Monad.Writer.Class+import Data.Functor.Apply+import Data.Foldable+import Data.Traversable+import Data.Monoid+import Data.List.NonEmpty hiding (map)+import Data.Semigroup+import Data.Semigroup.Reducer+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 System.Console.Terminfo.PrettyPrint+import Prelude hiding (log)++data Diagnostic m = Diagnostic !Rendering !DiagnosticLevel m [Diagnostic m]+ deriving Show++tellDiagnostic :: (MonadWriter t m, Reducer (Diagnostic e) t) => Diagnostic e -> m ()+tellDiagnostic = tell . unit++instance Renderable (Diagnostic m) where+ render (Diagnostic r _ _ _) = r++instance HasDelta (Diagnostic m) where+ delta (Diagnostic r _ _ _) = delta r++instance HasBytes (Diagnostic m) where+ bytes = bytes . delta++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 r l m xs) = vsep $+ [ pretty (delta r) <> char ':' <+> pretty l <> char ':' <+> nest 4 (pretty m) ] + <> (pretty r <$ guard (not (nullRendering r)))+ <> (indent 2 (prettyList xs) <$ guard (not (null xs)))+ prettyList = Prelude.foldr ((<>) . pretty) empty++instance PrettyTerm m => PrettyTerm (Diagnostic m) where+ prettyTerm (Diagnostic r l m xs) = vsep $ + [ prettyTerm (delta r) <> char ':' <+> prettyTerm l <> char ':' <+> nest 4 (prettyTerm m) ]+ <> (prettyTerm r <$ guard (not (nullRendering r)))+ <> (indent 2 (prettyTermList xs) <$ guard (not (null xs)))+ prettyTermList = Prelude.foldr ((<>) . prettyTerm) empty++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 view
@@ -0,0 +1,12 @@+module Text.Trifecta.Diagnostic.Rendering+ ( Renderable(..)+ , Source, rendering+ , 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 view
@@ -0,0 +1,107 @@+{-# LANGUAGE MultiParamTypeClasses #-}+module Text.Trifecta.Diagnostic.Rendering.Caret+ ( Caret(..)+ , caret+ , Careted(..)+ , careted+ -- * Internals+ , drawCaret+ , addCaret+ , caretEffects+ ) 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 (column p) "^"++addCaret :: Delta -> Rendering -> Rendering+addCaret p r = drawCaret p .# r++caret :: MonadParser m => m Caret+caret = Caret <$> mark <*> line+ +careted :: MonadParser m => m a -> m (Careted a)+careted p = do+ m <- mark+ 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++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 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 view
@@ -0,0 +1,52 @@+{-# LANGUAGE MultiParamTypeClasses #-}+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+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 (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 view
@@ -0,0 +1,191 @@+{-# LANGUAGE TypeSynonymInstances #-}++-- | Diagnostics rendering+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 hiding (groupBy, empty, any)+import Data.Foldable+import Data.Monoid+import Data.Function (on)+import Data.Functor.Bind+import Data.List (groupBy)+import Data.Semigroup+import Data.Semigroup.Foldable+import Data.Semigroup.Traversable+import Data.Traversable+import Prelude as P+import Prelude hiding (span)+import System.Console.Terminfo.PrettyPrint+import Text.PrettyPrint.Free hiding (column)+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta+import qualified Data.ByteString.UTF8 as UTF8 ++outOfRangeEffects :: [ScopedEffect] -> [ScopedEffect]+outOfRangeEffects xs = soft Bold : xs++type Lines = Array (Int,Int) ([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 -> Int -> 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++data Rendering = Rendering+ { renderingDelta :: !Delta -- focus, the render will keep this visible+ , renderingLineLen :: {-# UNPACK #-} !Int -- actual line length+ , renderingLine :: Lines -> Lines+ , renderingOverlays :: Delta -> Lines -> Lines+ }++instance Show Rendering where+ showsPrec d (Rendering p ll _ _) = showParen (d > 10) $ + showString "Rendering " . showsPrec 11 p . showChar ' ' . showsPrec 11 ll . showString " ... ..."++nullRendering :: Rendering -> Bool+nullRendering (Rendering (Columns 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 _ f <> Rendering del len doc g = Rendering del len doc $ \d l -> f d (g d l)+ Rendering del len doc f <> Rendering _ _ _ g = Rendering del len 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 -> (Int, Lines -> Lines)++instance Source String where+ source s = (P.length s', draw [] 0 0 s') where + s' = go 0 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, doc) -> Rendering del len doc (\_ l -> l)++(.#) :: (Delta -> Lines -> Lines) -> Rendering -> Rendering+f .# Rendering d ll s g = Rendering d ll 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 (n - k) where+ go cols = align (vsep (P.map ln [t..b])) where + (lo, hi) = window (column d) ll (cols - 2)+ a = f d $ l $ array ((0,lo),(-1,hi)) []+ ((t,_),(b,_)) = bounds a+ ln y = hcat + $ P.map (\g -> P.foldr with (string (P.map snd g)) (fst (P.head g)))+ $ groupBy ((==) `on` fst) + [ a ! (y,i) | i <- [lo..hi] ] ++window :: Int -> Int -> Int -> (Int, Int)+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 view
@@ -0,0 +1,113 @@+{-# LANGUAGE MultiParamTypeClasses #-}+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+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) (P.replicate (max (column h - column l + 1) 0) '~') a+ | nl = go (column l) (P.replicate (max (snd (snd (bounds a)) - column l + 2) 0) '~') a+ | nh = go (-1) (P.replicate (max (column h + 1) 0) '~') a+ | otherwise = a+ where+ go = draw spanEffects 1+ l = argmin bytes s e+ h = argmax bytes s e+ nl = near l d+ nh = near h d++-- |+-- > 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) <$> mark <*> line <*> (p *> mark)+ +spanned :: MonadParser m => m a -> m (Spanned a)+spanned p = (\s l a e -> a :~ Span s e l) <$> mark <*> line <*> p <*> mark
− Text/Trifecta/Hunk.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}-module Text.Trifecta.Hunk - ( Hunk(..)- , hunk- ) where--import Data.ByteString-import qualified Data.ByteString.UTF8 as UTF8-import Data.FingerTree as FingerTree-import Data.Function (on)-import Data.Hashable-import Data.Interned-import Data.String-import Text.Trifecta.Delta--data Hunk = Hunk {-# UNPACK #-} !Id !Delta {-# UNPACK #-} !ByteString- deriving Show--hunk :: ByteString -> Hunk-hunk = intern ---- instance Show Hunk where showsPrec d (Hunk _ _ b) = showsPrec d b--instance IsString Hunk where- fromString = hunk . UTF8.fromString--instance Eq Hunk where- (==) = (==) `on` identity--instance Hashable Hunk where- hash = hash . identity--instance Ord Hunk where- compare = compare `on` identity--instance HasDelta Hunk where- delta (Hunk _ d _) = d--instance Interned Hunk where- type Uninterned Hunk = ByteString- data Description Hunk = Describe {-# UNPACK #-} !ByteString deriving (Eq)- describe = Describe- identify i bs = Hunk i (delta bs) bs- identity (Hunk i _ _) = i- cache = hunkCache--instance Uninternable Hunk where- unintern (Hunk _ _ bs) = bs--instance Hashable (Description Hunk) where- hash (Describe bs) = hash bs--hunkCache :: Cache Hunk-hunkCache = mkCache -{-# NOINLINE hunkCache #-}--instance Measured Delta Hunk where- measure = delta
Text/Trifecta/Parser/Class.hs view
@@ -28,8 +28,8 @@ import Data.ByteString as Strict import Data.Semigroup import Data.Set as Set-import Text.Trifecta.Delta-import Text.Trifecta.Rope+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Prim import Text.Trifecta.Parser.It infix 0 <?>
Text/Trifecta/Parser/Combinators.hs view
@@ -216,4 +216,3 @@ m <- mark p <* release m -
− Text/Trifecta/Parser/Err.hs
@@ -1,82 +0,0 @@-module Text.Trifecta.Parser.Err- ( Err(..)- , diagnose- , knownErr- ) where--import Control.Applicative-import Control.Comonad-import Data.Semigroup-import Data.Monoid-import Data.Functor.Plus-import Text.Trifecta.Render.Prim-import Text.Trifecta.Diagnostic-import Text.Trifecta.Diagnostic.Level-import Text.PrettyPrint.Free-import System.Console.Terminfo.PrettyPrint---- | unlocated error messages-data Err e- = EmptyErr- | FailErr String - | UnexpectedErr String- | EndOfFileErr- | RichErr (Render -> Diagnostic e)--instance Show (Err e) where- showsPrec _ EmptyErr = showString "EmptyErr"- showsPrec d (FailErr s) = showParen (d > 10) $- showString "FailErr " . showsPrec 11 s- showsPrec d (UnexpectedErr s) = showParen (d > 10) $- showString "UnexpectedErr " . showsPrec 11 s- showsPrec _ EndOfFileErr = showString "EndOfFileErr"- showsPrec d (RichErr _) = showParen (d > 10) $ - showString "RichErr ..."--knownErr :: Err e -> Bool-knownErr EmptyErr = False-knownErr _ = True--diagnose :: (t -> Doc e) -> Render -> Err t -> Diagnostic (Doc e)-diagnose _ r EmptyErr = Diagnostic r Error (text "unexpected") []-diagnose _ r (FailErr m) = Diagnostic r Error (fillSep $ text <$> words m) []-diagnose _ r (UnexpectedErr s) = Diagnostic r Error (fillSep $ fmap text $ "unexpected" : words s) []-diagnose _ r EndOfFileErr = Diagnostic r Error (text "unexpected EOF") []-diagnose k r (RichErr f) = fmap k (f r)--diagnose0 :: Pretty t => Err t -> Diagnostic (Doc e)-diagnose0 = diagnose pretty emptyRender--diagnoseTerm0 :: PrettyTerm t => Err t -> Diagnostic TermDoc-diagnoseTerm0 = diagnose prettyTerm emptyRender--instance Pretty t => Pretty (Err t) where- pretty = pretty . extract . diagnose0- prettyList = prettyList . map (extract . diagnose0)--instance PrettyTerm t => PrettyTerm (Err t) where- prettyTerm = prettyTerm . diagnoseTerm0- prettyTermList = prettyTermList . map diagnoseTerm0- -instance Functor Err where- fmap _ EmptyErr = EmptyErr- fmap _ (FailErr s) = FailErr s- fmap _ EndOfFileErr = EndOfFileErr- fmap _ (UnexpectedErr s) = UnexpectedErr s - fmap f (RichErr k) = RichErr (fmap f . k)--instance Alt Err where- EmptyErr <!> a = a- a <!> _ = a- {-# INLINE (<!>) #-}--instance Plus Err where- zero = EmptyErr--instance Semigroup (Err t) where- (<>) = (<!>)- replicate1p _ = id--instance Monoid (Err t) where- mempty = EmptyErr- mappend = (<!>)
− Text/Trifecta/Parser/Err/State.hs
@@ -1,34 +0,0 @@-module Text.Trifecta.Parser.Err.State - ( ErrState(..)- ) where--import Data.Functor.Plus-import Data.Set as Set-import Data.Sequence as Seq-import Data.Semigroup-import Data.Monoid-import Text.Trifecta.Parser.Err-import Text.Trifecta.Diagnostic--data ErrState e = ErrState- { errExpected :: !(Set String)- , errMessage :: !(Err e)- , errLog :: !(Seq (Diagnostic e))- }--instance Functor ErrState where- fmap f (ErrState a b c) = ErrState a (fmap f b) (fmap (fmap f) c)--instance Alt ErrState where- ErrState a b c <!> ErrState a' b' c' = ErrState (a <> a') (b <!> b') (c <!> c')- {-# INLINE (<!>) #-}--instance Plus ErrState where- zero = ErrState mempty zero zero- -instance Semigroup (ErrState e) where- (<>) = (<!>) --instance Monoid (ErrState e) where- mempty = zero- mappend = (<!>)
Text/Trifecta/Parser/It.hs view
@@ -22,12 +22,11 @@ import Data.Functor.Plus import Data.Profunctor import Data.Key as Key-import Text.Trifecta.Rope as Rope-import Text.Trifecta.Delta-import Text.Trifecta.Bytes-import Text.Trifecta.Util as Util-import Text.Trifecta.Util.MaybePair+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 as Util data It r a = Pure a @@ -113,10 +112,10 @@ -- * Rope specifics -- | Given a position, go there, and grab the text forward from that point-fillIt :: Delta -> It Rope (MaybePair Delta Strict.ByteString)-fillIt n = wantIt NothingPair $ \r -> +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 NothingPair JustPair #) + , grabLine n r kf ks #) stepIt :: It Rope a -> Step e a stepIt = go mempty where@@ -136,4 +135,3 @@ where bi = bytes i bj = bytes j-
Text/Trifecta/Parser/Prim.hs view
@@ -25,25 +25,24 @@ import Data.Semigroup import Data.Foldable import Data.Monoid-import Data.Functor.Bind+import Data.Functor.Bind (Apply(..), Bind((>>-))) 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 Data.Bifunctor import Text.PrettyPrint.Free-import Text.Trifecta.Delta-import Text.Trifecta.Diagnostic-import Text.Trifecta.Render.Prim-import Text.Trifecta.Render.Caret-import Text.Trifecta.Rope+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Prim+import Text.Trifecta.Diagnostic.Prim+import Text.Trifecta.Diagnostic.Err+import Text.Trifecta.Diagnostic.Err.State+import Text.Trifecta.Diagnostic.Rendering.Prim+import Text.Trifecta.Diagnostic.Rendering.Caret import Text.Trifecta.Parser.Class import Text.Trifecta.Parser.It-import Text.Trifecta.Parser.Err-import Text.Trifecta.Parser.Err.State import Text.Trifecta.Parser.Step import Text.Trifecta.Parser.Result-import Text.Trifecta.Util.MaybePair import System.Console.Terminfo.PrettyPrint data Parser e a = Parser @@ -164,9 +163,8 @@ Nothing -> ee mempty { errMessage = EndOfFileErr } d bs Just (c, xs) | not (f c) -> ee mempty d bs- | Strict.null xs -> fillIt (d <> delta c) >>= \dbs -> case dbs of- JustPair d' bs' -> co c mempty d' bs'- NothingPair -> co c mempty (d <> delta c) bs -- END OF LINE+ | Strict.null xs -> let ddc = d <> delta c in+ join $ fillIt (co c mempty ddc bs) (co c mempty) ddc | otherwise -> co c mempty (d <> delta c) bs {-# INLINE satisfy #-} satisfyAscii f = Parser $ \ _ ee co _ d bs ->@@ -174,9 +172,8 @@ if b >= 0 && b < Strict.length bs then case toEnum $ fromEnum $ Strict.index bs b of c | not (f c) -> ee mempty d bs- | b == Strict.length bs - 1 -> fillIt (d <> delta c) >>= \dbs -> case dbs of- JustPair d' bs' -> co c mempty d' bs'- NothingPair -> co c mempty (d <> delta c) bs+ | b == Strict.length bs - 1 -> let ddc = d <> delta c in + join $ fillIt (co c mempty ddc bs) (co c mempty) ddc | otherwise -> co c mempty (d <> delta c) bs else ee mempty { errMessage = EndOfFileErr } d bs {-# INLINE satisfyAscii #-}@@ -205,8 +202,8 @@ why :: Pretty e => (e -> Doc t) -> ErrState e -> Delta -> ByteString -> Diagnostic (Doc t) why pp (ErrState ss _m _) d bs - | Set.null ss = diagnose pp (addCaret d $ surface d bs) m- | otherwise = expected <$> diagnose pp (addCaret d $ surface d bs) m + | Set.null ss = diagnose pp (addCaret d $ rendering d bs) m+ | otherwise = expected <$> diagnose pp (addCaret d $ rendering d bs) m where m = EmptyErr expected doc = doc <> text ", expected" <+> fillSep (punctuate (char ',') $ text <$> toList ss)
Text/Trifecta/Parser/Result.hs view
@@ -11,7 +11,7 @@ import Data.Traversable import Data.Bifunctor import Data.Sequence-import Text.Trifecta.Diagnostic+import Text.Trifecta.Diagnostic.Prim import Text.PrettyPrint.Free import System.Console.Terminfo.PrettyPrint
Text/Trifecta/Parser/Step.hs view
@@ -9,8 +9,8 @@ import Data.Bifunctor import Data.Semigroup.Reducer import Data.Sequence-import Text.Trifecta.Rope-import Text.Trifecta.Diagnostic+import Text.Trifecta.Rope.Prim+import Text.Trifecta.Diagnostic.Prim import Text.Trifecta.Parser.Result data Step e a
+ Text/Trifecta/Parser/Token.hs view
@@ -0,0 +1,16 @@+++module Text.Trifecta.Parser.Token+ ( module Text.Trifecta.Parser.Token.Class+ , module Text.Trifecta.Parser.Token.Combinators+ , module Text.Trifecta.Parser.Token.Identifier+ ) where++import Text.Trifecta.Parser.Token.Class+import Text.Trifecta.Parser.Token.Combinators+import Text.Trifecta.Parser.Token.Identifier++-- expected to be imported manually++-- import Text.Trifecta.Parser.Token.Style+-- import Text.Trifecta.Parser.Token.Identifier.Style
+ Text/Trifecta/Parser/Token/Identifier.hs view
@@ -0,0 +1,52 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Token.Identifier+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+-- +-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Token.Identifier+ ( IdentifierStyle(..)+ , ident+ , reserved+ , reservedByteString+ ) 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 Text.Trifecta.Parser.Class+import Text.Trifecta.Parser.Char+import Text.Trifecta.Parser.Combinators+import Text.Trifecta.Parser.Token.Class++data IdentifierStyle m = IdentifierStyle+ { styleName :: String+ , styleStart :: m ()+ , styleLetter :: m ()+ , styleReserved :: HashSet ByteString+ }++-- | parse a reserved operator or identifier+reserved :: MonadTokenParser m => IdentifierStyle m -> String -> m ()+reserved s name = reservedByteString s $! UTF8.fromString name++-- | parse a reserved operator or identifier specified by bytestring+reservedByteString :: MonadTokenParser m => IdentifierStyle m -> ByteString -> m ()+reservedByteString s name = lexeme $ try $ do+ _ <- byteString name + notFollowedBy (styleLetter s) <?> "end of " ++ show name++-- | parse an non-reserved identifier or symbol+ident :: MonadTokenParser m => IdentifierStyle m -> m ByteString+ident s = lexeme $ try $ do+ name <- sliced (styleStart s *> skipMany (styleLetter s)) <?> styleName s+ when (member name (styleReserved s)) $ unexpected $ "reserved " ++ styleName s ++ " " ++ show name+ return name+
+ Text/Trifecta/Parser/Token/Identifier/Style.hs view
@@ -0,0 +1,65 @@+-----------------------------------------------------------------------------+-- |+-- Module : Text.Trifecta.Parser.Token.Identifier.Style+-- Copyright : (c) Edward Kmett 2011+-- License : BSD3+-- +-- Maintainer : ekmett@gmail.com+-- Stability : provisional+-- Portability : non-portable+-- +-----------------------------------------------------------------------------+module Text.Trifecta.Parser.Token.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.Char+import Text.Trifecta.Parser.Token.Class+import Text.Trifecta.Parser.Token.Identifier++set :: [String] -> HashSet ByteString+set = HashSet.fromList . fmap UTF8.fromString++emptyOps, haskell98Ops, haskellOps :: MonadTokenParser m => IdentifierStyle m+emptyOps = IdentifierStyle+ { styleName = "operator"+ , styleStart = styleLetter emptyOps+ , styleLetter = () <$ oneOf ":!#$%&*+./<=>?@\\^|-~"+ , styleReserved = mempty+ }+haskell98Ops = emptyOps + { styleReserved = set ["::","..","=","\\","|","<-","->","@","~","=>"]+ }+haskellOps = haskell98Ops++emptyIdents, haskell98Idents, haskellIdents :: MonadTokenParser m => IdentifierStyle m+emptyIdents = IdentifierStyle+ { styleName = "identifier"+ , styleStart = () <$ (letter <|> char '_')+ , styleLetter = () <$ (alphaNum <|> oneOf "_'")+ , styleReserved = set [] }++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/Token/Prim.hs
@@ -1,71 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Text.Trifecta.Parser.Token.Prim--- Copyright : (c) Edward Kmett 2011--- License : BSD3--- --- Maintainer : ekmett@gmail.com--- Stability : provisional--- Portability : non-portable--- -------------------------------------------------------------------------------module Text.Trifecta.Parser.Token.Prim- ( CommentStyle(..)- , emptyCommentStyle- , javaCommentStyle- , haskellCommentStyle- , buildWhiteSpaceParser- ) where--import Data.Char (isSpace)-import Control.Applicative-import Data.List (nub)-import Text.Trifecta.Parser.Class-import Text.Trifecta.Parser.Char-import Text.Trifecta.Parser.Combinators--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 MonadTokenParser-buildWhiteSpaceParser :: MonadParser m => CommentStyle -> m ()-buildWhiteSpaceParser (CommentStyle startStyle endStyle lineStyle nestingStyle)- | noLine && noMulti = skipMany (simpleSpace <?> "")- | noLine = skipMany (simpleSpace <|> multiLineComment <?> "")- | noMulti = skipMany (simpleSpace <|> oneLineComment <?> "")- | otherwise = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")- where- noLine = null lineStyle- noMulti = null startStyle- simpleSpace = skipSome (satisfy isSpace)- oneLineComment = do- _ <- try $ string lineStyle- skipMany (satisfyAscii (/= '\n')) -- TODO: use skipping/restOfLine and fiddle with the last byte- return ()- multiLineComment = 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/Parser/Token/Style.hs view
@@ -10,89 +10,62 @@ -- ----------------------------------------------------------------------------- module Text.Trifecta.Parser.Token.Style- ( Style(..)- - -- identifier styles- , emptyIdents, haskellIdents, haskell98Idents-- -- operator styles- , emptyOps, haskellOps, haskell98Ops-- -- reading identifiers- , ident- , reserved- , reservedByteString+ ( CommentStyle(..)+ , emptyCommentStyle+ , javaCommentStyle+ , haskellCommentStyle+ , buildWhiteSpaceParser ) 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 Data.Char (isSpace) import Control.Applicative-import Control.Monad (when)+import Data.List (nub) import Text.Trifecta.Parser.Class import Text.Trifecta.Parser.Char import Text.Trifecta.Parser.Combinators-import Text.Trifecta.Parser.Token.Class -data Style m = Style- { styleName :: String- , styleStart :: m ()- , styleLetter :: m ()- , styleReserved :: HashSet ByteString- }---- | parse a reserved operator or identifier-reserved :: MonadTokenParser m => Style m -> String -> m ()-reserved s name = reservedByteString s $! UTF8.fromString name---- | parse a reserved operator or identifier specified by bytestring-reservedByteString :: MonadTokenParser m => Style m -> ByteString -> m ()-reservedByteString s name = lexeme $ try $ do- _ <- byteString name - notFollowedBy (styleLetter s) <?> "end of " ++ show name---- | parse an non-reserved identifier or symbol-ident :: MonadTokenParser m => Style m -> m ByteString-ident s = lexeme $ try $ do- name <- sliced (styleStart s *> skipMany (styleLetter s)) <?> styleName s- when (member name (styleReserved s)) $ unexpected $ "reserved " ++ styleName s ++ " " ++ show name- return name--set :: [String] -> HashSet ByteString-set = HashSet.fromList . fmap UTF8.fromString--emptyOps, haskell98Ops, haskellOps :: MonadTokenParser m => Style m-emptyOps = Style- { styleName = "operator"- , styleStart = styleLetter emptyOps- , styleLetter = () <$ oneOf ":!#$%&*+./<=>?@\\^|-~"- , styleReserved = mempty- }-haskell98Ops = emptyOps - { styleReserved = set ["::","..","=","\\","|","<-","->","@","~","=>"]- }-haskellOps = haskell98Ops--emptyIdents, haskell98Idents, haskellIdents :: MonadTokenParser m => Style m-emptyIdents = Style- { styleName = "identifier"- , styleStart = () <$ (letter <|> char '_')- , styleLetter = () <$ (alphaNum <|> oneOf "_'")- , styleReserved = set [] }+data CommentStyle = CommentStyle + { commentStart :: String+ , commentEnd :: String+ , commentLine :: String+ , commentNesting :: Bool+ } -haskell98Idents = emptyIdents- { styleReserved = set haskell98ReservedIdents }-haskellIdents = haskell98Idents- { styleLetter = styleLetter haskell98Idents <|> () <$ char '#'- , styleReserved = set $ haskell98ReservedIdents ++- ["foreign","import","export","primitive","_ccall_","_casm_" ,"forall"]- }+emptyCommentStyle, javaCommentStyle, haskellCommentStyle :: CommentStyle+emptyCommentStyle = CommentStyle "" "" "" True+javaCommentStyle = CommentStyle "/*" "*/" "//" True+haskellCommentStyle = CommentStyle "{-" "-}" "--" True -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"- ]+-- | Use this to easily build the definition of whiteSpace for your MonadTokenParser+buildWhiteSpaceParser :: MonadParser m => CommentStyle -> m ()+buildWhiteSpaceParser (CommentStyle startStyle endStyle lineStyle nestingStyle)+ | noLine && noMulti = skipMany (simpleSpace <?> "")+ | noLine = skipMany (simpleSpace <|> multiLineComment <?> "")+ | noMulti = skipMany (simpleSpace <|> oneLineComment <?> "")+ | otherwise = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")+ where+ noLine = null lineStyle+ noMulti = null startStyle+ simpleSpace = skipSome (satisfy isSpace)+ oneLineComment = do+ _ <- try $ string lineStyle+ skipMany (satisfyAscii (/= '\n')) -- TODO: use skipping/restOfLine and fiddle with the last byte+ return ()+ multiLineComment = 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/Path.hs
@@ -1,103 +0,0 @@-{-# LANGUAGE TypeFamilies, FlexibleInstances, BangPatterns #-}-module Text.Trifecta.Path- ( FileName- , Path(..), History(..)- , file- , snocPath- , path- , appendPath- , comparablePath- -- * Internals- , MaybeFileName(..)- , maybeFileName- ) where--import Data.Hashable-import Data.Interned-import Data.Interned.String-import Data.Function (on)-import Data.Semigroup-import Data.IntSet as IntSet--type FileName = InternedString--data Path = Path {-# UNPACK #-} !Id !IntSet !History !MaybeFileName {-# UNPACK #-} !Int [Int]- deriving Show--pathIds :: Path -> IntSet-pathIds (Path _ is _ _ _ _) = is--comparablePath :: Path -> Path -> Bool-comparablePath x y = identity x `IntSet.member` pathIds y- || identity y `IntSet.member` pathIds x--instance Eq Path where- (==) = (==) `on` identity--instance Ord Path where- compare = compare `on` identity--data History = Continue !Path {-# UNPACK #-} !Int | Complete deriving (Eq, Show)--data MaybeFileName = JustFileName !FileName | NothingFileName deriving (Eq, Show)--maybeFileName :: r -> (FileName -> r) -> MaybeFileName -> r-maybeFileName n _ NothingFileName = n-maybeFileName _ f (JustFileName a) = f a--file :: String -> Path -file !n = path Complete (JustFileName (intern n)) 0 []--snocPath :: Path -> Int -> MaybeFileName -> Int -> [Int] -> Path-snocPath d l jf l' flags = path (Continue d l) jf l' flags--path :: History -> MaybeFileName -> Int -> [Int] -> Path-path !h !mf l flags = intern (UPath h mf l flags)--appendPath :: Path -> Int -> Path -> Path-appendPath p dl (Path _ _ Complete mf l flags) = snocPath p dl mf l flags-appendPath p dl (Path _ _ (Continue p' dl') mf l flags) = snocPath (appendPath p dl p') dl' mf l flags--instance Semigroup Path where- p <> p' = appendPath p 0 p'--data UninternedPath = UPath !History !MaybeFileName {-# UNPACK #-} !Int [Int]-data DHistory = DContinue {-# UNPACK #-} !Id {-# UNPACK #-} !Int | DComplete deriving Eq--instance Hashable DHistory where- hash (DContinue x y) = y `hashWithSalt` x- hash DComplete = 0--instance Hashable Path where- hash = hash . identity--instance Interned Path where- type Uninterned Path = UninternedPath- data Description Path = DPath !(Maybe Id) {-# UNPACK #-} !Int [Int] !DHistory deriving Eq- describe (UPath h mf l flags) = DPath mi l flags $ case h of- Continue p dl -> DContinue (identity p) dl- Complete -> DComplete - where - mi = case mf of - JustFileName f -> Just (identity f)- NothingFileName -> Nothing- - identify i (UPath h mf l flags) = Path i m h mf l flags - where - m = case h of - Complete -> IntSet.singleton i- Continue (Path _ m' _ _ _ _) _ -> IntSet.insert i m'- - identity (Path i _ _ _ _ _) = i- cache = pathCache--instance Uninternable Path where- unintern (Path _ _ h mf l flags) = UPath h mf l flags--instance Hashable (Description Path) where- hash (DPath mi l flags dh) = l `hashWithSalt` mi `hashWithSalt` flags `hashWithSalt` dh--pathCache :: Cache Path-pathCache = mkCache-{-# NOINLINE pathCache #-}-
− Text/Trifecta/Render/Caret.hs
@@ -1,104 +0,0 @@-module Text.Trifecta.Render.Caret- ( Caret(..)- , HasCaret(..)- , Careted(..)- , careted- -- * Internals- , drawCaret- , addCaret- , caretEffects- ) 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.Traversable-import Prelude hiding (span)-import System.Console.Terminfo.Color-import System.Console.Terminfo.PrettyPrint-import Text.Trifecta.Bytes-import Text.Trifecta.Delta-import Text.Trifecta.Parser.Class-import Text.Trifecta.Render.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 (column p) "^"--addCaret :: Delta -> Render -> Render-addCaret p r = drawCaret p .# r--class HasCaret t where- caret :: t -> Caret--instance HasCaret Caret where- caret = id--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 $ surface d bs--instance Semigroup Caret where- a <> _ = a--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 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 = render . caret--instance HasCaret (Careted a) where- caret (_ :^ c) = c--instance Hashable a => Hashable (Careted a) where- -careted :: MonadParser m => m a -> m (Careted a)-careted p = do- m <- mark- l <- line- a <- p- return $ a :^ Caret m l
− Text/Trifecta/Render/Fixit.hs
@@ -1,57 +0,0 @@-module Text.Trifecta.Render.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 Text.Trifecta.Bytes-import Text.Trifecta.Delta-import Text.Trifecta.Render.Prim-import Text.Trifecta.Render.Span-import Text.Trifecta.Render.Caret-import Text.Trifecta.Parser.Class-import Text.Trifecta.Util-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 (column l) rpl) d - $ drawSpan s e d a- where l = argmin bytes s e--addFixit :: Delta -> Delta -> String -> Render -> Render-addFixit s e rpl r = drawFixit s e rpl .# r--data Fixit = Fixit - { fixitSpan :: {-# UNPACK #-} !Span- , fixitReplacement :: {-# UNPACK #-} !ByteString - } deriving (Eq,Ord,Show)--instance HasSpan Fixit where- span (Fixit s _) = s--instance HasDelta Fixit where- delta = delta . caret--instance HasCaret Fixit where- caret = caret . span--instance Hashable Fixit where- hash (Fixit s b) = hash s `hashWithSalt` b--instance Renderable Fixit where- render (Fixit (Span s e bs) r) = addFixit s e (UTF8.toString r) $ surface s bs--fixit :: MonadParser m => m Strict.ByteString -> m Fixit-fixit p = (\(r :~ s) -> Fixit s r) <$> spanned p
− Text/Trifecta/Render/Prim.hs
@@ -1,191 +0,0 @@-{-# LANGUAGE TypeSynonymInstances #-}--- | Diagnostics rendering-module Text.Trifecta.Render.Prim - ( Render(..)- , Renderable(..)- , Source(..)- , Rendered(..)- , surface- , nullRender- , emptyRender- -- * Lower level drawing primitives- , Lines- , draw- , ifNear- , (.#)- ) where--import Control.Applicative-import Control.Comonad-import Control.Monad.State-import Data.Array-import Data.ByteString hiding (groupBy, empty, any)-import Data.Foldable-import Data.Monoid-import Data.Function (on)-import Data.Functor.Bind-import Data.List (groupBy)-import Data.Semigroup-import Data.Semigroup.Foldable-import Data.Semigroup.Traversable-import Data.Traversable-import Prelude as P-import Prelude hiding (span)-import System.Console.Terminfo.PrettyPrint-import Text.PrettyPrint.Free hiding (column)-import Text.Trifecta.Bytes-import Text.Trifecta.Delta-import qualified Data.ByteString.UTF8 as UTF8 --outOfRangeEffects :: [ScopedEffect] -> [ScopedEffect]-outOfRangeEffects xs = soft Bold : xs--type Lines = Array (Int,Int) ([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 -> Int -> 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--data Render = Render - { rDelta :: !Delta -- focus, the render will keep this visible- , rLineLen :: {-# UNPACK #-} !Int -- actual line length- , rLine :: Lines -> Lines- , rDraw :: Delta -> Lines -> Lines- }--instance Show Render where- showsPrec d (Render p ll _ _) = showParen (d > 10) $ - showString "Render " . showsPrec 11 p . showChar ' ' . showsPrec 11 ll . showString " ... ..."--nullRender :: Render -> Bool-nullRender (Render (Columns 0 0) 0 _ _) = True-nullRender _ = False--emptyRender :: Render -emptyRender = surface (Columns 0 0) ""--instance Semigroup Render where- -- an unprincipled hack- Render (Columns 0 0) 0 _ f <> Render del len doc g = Render del len doc $ \d l -> f d (g d l)- Render del len doc f <> Render _ _ _ g = Render del len doc $ \d l -> f d (g d l)--instance Monoid Render where- mappend = (<>) - mempty = emptyRender- -ifNear :: Delta -> (Lines -> Lines) -> Delta -> Lines -> Lines-ifNear d f d' l | near d d' = f l - | otherwise = l--instance HasDelta Render where- delta = rDelta--class Renderable t where- render :: t -> Render --instance Renderable Render where- render = id--class Source t where- source :: t -> (Int, Lines -> Lines)--instance Source String where- source s = (P.length s', draw [] 0 0 s') where - s' = go 0 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-surface :: Source s => Delta -> s -> Render-surface del s = case source s of - (len, doc) -> Render del len doc (\_ l -> l)--(.#) :: (Delta -> Lines -> Lines) -> Render -> Render-f .# Render d ll s g = Render d ll s $ \e l -> f e $ g e l --instance Pretty Render where- pretty r = prettyTerm r >>= const empty--instance PrettyTerm Render where- prettyTerm (Render d ll l f) = nesting $ \k -> columns $ \n -> go (n - k) where- go cols = align (vsep (P.map ln [t..b])) where - (lo, hi) = window (column d) ll (cols - 2)- a = f d $ l $ array ((0,lo),(-1,hi)) []- ((t,_),(b,_)) = bounds a- ln y = hcat - $ P.map (\g -> P.foldr with (string (P.map snd g)) (fst (P.head g)))- $ groupBy ((==) `on` fst) - [ a ! (y,i) | i <- [lo..hi] ] --window :: Int -> Int -> Int -> (Int, Int)-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 :@ Render- 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/Render/Span.hs
@@ -1,124 +0,0 @@-module Text.Trifecta.Render.Span- ( Span(..)- , HasSpan(..)- , Spanned(..)- , spanned- -- * Internals- , spanEffects- , drawSpan- , addSpan- ) where--import Control.Applicative-import Data.Hashable-import Data.Semigroup-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.Bytes-import Text.Trifecta.Delta-import Text.Trifecta.Render.Prim-import Text.Trifecta.Render.Caret-import Text.Trifecta.Util-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) (P.replicate (max (column h - column l + 1) 0) '~') a- | nl = go (column l) (P.replicate (max (snd (snd (bounds a)) - column l + 2) 0) '~') a- | nh = go (-1) (P.replicate (max (column h + 1) 0) '~') a- | otherwise = a- where- go = draw spanEffects 1- l = argmin bytes s e- h = argmax bytes s e- nl = near l d- nh = near h d---- |--- > int main(int argc, char ** argv) { int; }--- > ^~~-addSpan :: Delta -> Delta -> Render -> Render-addSpan s e r = drawSpan s e .# r--data Span = Span !Delta !Delta {-# UNPACK #-} !ByteString deriving (Eq,Ord,Show)--instance HasCaret Span where- caret (Span s _ b) = Caret s b--instance Renderable Span where- render (Span s e bs) = addSpan s e $ surface s bs--class HasSpan t where- span :: t -> Span--instance HasSpan Span where- span = id--instance Semigroup Span where- Span s _ b <> Span _ e _ = Span s e b---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 HasSpan (Spanned a) where- span (_ :~ c) = c--instance Renderable (Spanned a) where- render = render . span--instance HasCaret (Spanned a) where- caret = caret . span--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--spanned :: MonadParser m => m a -> m (Spanned a)-spanned p = do- m <- mark- l <- line- a <- p- r <- mark- return $ a :~ Span m r l
− Text/Trifecta/Rope.hs
@@ -1,83 +0,0 @@-{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, BangPatterns, PatternGuards #-}-module Text.Trifecta.Rope- ( Rope(..)- , rope- , strands- , grabRest- , grabLine- ) where--import Data.Monoid-import Data.Semigroup-import Data.Semigroup.Reducer-import qualified Data.ByteString as Strict-import qualified Data.ByteString.Lazy as Lazy-import Data.FingerTree as FingerTree-import Data.Foldable (toList)-import Text.Trifecta.Hunk-import Text.Trifecta.Path-import Text.Trifecta.Delta-import Text.Trifecta.Bytes-import Text.Trifecta.Strand-import Text.Trifecta.Util as Util--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 (toList r) (delta l) (bytes i - bytes l) where- trim (PathStrand p : xs) j k = trim xs (j <> delta p) k- trim (HunkStrand (Hunk _ _ h) : xs) j 0 = go j h xs- trim (HunkStrand (Hunk _ _ h) : xs) _ k = go i (Strict.drop k h) xs- trim [] _ _ = kf- go j h s = ks j $ Lazy.fromChunks $ h : [ a | HunkStrand (Hunk _ _ 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 (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 Hunk Rope where- unit s = Rope (delta s) (singleton (HunkStrand s))- cons s (Rope mt t) = Rope (delta s `mappend` mt) (HunkStrand s <| t)- snoc (Rope mt t) s = Rope (mt `mappend` delta s) (t |> HunkStrand s)- -instance Reducer Path Rope where- unit s = Rope (delta s) (singleton (PathStrand s))- cons s (Rope mt t) = Rope (delta s `mappend` mt) (PathStrand s <| t)- snoc (Rope mt t) s = Rope (mt `mappend` delta s) (t |> PathStrand s)--instance Reducer Strict.ByteString Rope where- unit = unit . hunk- cons = cons . hunk - snoc r = snoc r . hunk
+ Text/Trifecta/Rope/Bytes.hs view
@@ -0,0 +1,15 @@+module Text.Trifecta.Rope.Bytes+ ( HasBytes(..)+ ) where++import Data.ByteString as Strict+import Data.FingerTree++class HasBytes t where+ bytes :: t -> Int++instance HasBytes ByteString where+ bytes = Strict.length++instance (Measured v a, HasBytes v) => HasBytes (FingerTree v a) where+ bytes = bytes . measure
+ Text/Trifecta/Rope/Delta.hs view
@@ -0,0 +1,155 @@+module Text.Trifecta.Rope.Delta + ( Delta(..) + , HasDelta(..)+ , nextTab+ , rewind+ , near+ , column+ , columnByte+ ) where++import Control.Applicative+import Data.Monoid+import Data.Semigroup+import Data.Hashable+import Data.Word+import Data.Interned+import Data.Foldable+import Data.FingerTree hiding (empty)+import Data.ByteString hiding (empty)+import Text.Trifecta.Rope.Path+import Text.Trifecta.Rope.Bytes+import Text.PrettyPrint.Free hiding (column)+import System.Console.Terminfo.PrettyPrint++data Delta+ = Columns {-# UNPACK #-} !Int -- the number of characters+ {-# UNPACK #-} !Int -- the number of bytes+ | Tab {-# UNPACK #-} !Int -- the number of characters before the tab+ {-# UNPACK #-} !Int -- the number of characters after the tab+ {-# UNPACK #-} !Int -- the number of bytes+ | Lines {-# UNPACK #-} !Int -- the number of newlines contained+ {-# UNPACK #-} !Int -- the number of characters since the last newline+ {-# UNPACK #-} !Int -- number of bytes+ {-# UNPACK #-} !Int -- the number of bytes since the last newline+ | Directed !Path -- the sequence of #line directives since the start of the file+ {-# UNPACK #-} !Int -- the number of lines since the last line directive+ {-# UNPACK #-} !Int -- the number of characters since the last newline+ {-# UNPACK #-} !Int -- number of bytes+ {-# UNPACK #-} !Int -- the number of bytes since the last newline+ deriving (Eq, Ord, Show)++columnByte :: Delta -> Int+columnByte (Columns _ b) = b+columnByte (Tab _ _ b) = b+columnByte (Lines _ _ _ b) = b+columnByte (Directed _ _ _ _ b) = b++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 "-" 1 c+ Tab x y _ -> k "-" 1 (nextTab x + y)+ Lines l c _ _ -> k "-" l c+ Directed (Path _ _ _ fn _ _) l c _ _ -> k (maybeFileName "-" unintern fn) l c -- TODO: add include path+ where + k fn ln cn = bold (string fn) + <> char ':' + <> bold (int ln) + <> char ':' + <> bold (int (cn + 1))++column :: HasDelta t => t -> Int+column t = case delta t of + Columns c _ -> c+ Tab b a _ -> nextTab b + a+ Lines _ c _ _ -> c+ Directed _ _ c _ _ -> c++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 a <> Lines m d t' b = Directed p (l + m) d (t + t') (a + b)+ Directed p l _ t _ <> Directed p' l' c' t' b = Directed (appendPath p l p') l' c' (t + t') b+ +nextTab :: Int -> Int+nextTab x = x + (8 - mod x 8)++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 ++near :: (HasDelta s, HasDelta t) => s -> t -> Bool+near s t = case (delta s, delta t) of+ (Directed p l _ _ _, Directed p' l' _ _ _) -> p == p' && l == l'+ (Lines l _ _ _, Lines l' _ _ _) -> l == l'+ (Columns _ _, Columns _ _) -> True+ (Columns _ _, Tab _ _ _) -> True+ (Tab _ _ _, Columns _ _) -> True+ (Tab _ _ _, Tab _ _ _) -> True+ _ -> False++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 HasDelta Path where+ delta p = Directed p 0 0 0 0++instance (Measured v a, HasDelta v) => HasDelta (FingerTree v a) where+ delta = delta . measure
+ Text/Trifecta/Rope/Hunk.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}+module Text.Trifecta.Rope.Hunk + ( Hunk(..)+ , hunk+ ) where++import Data.ByteString+import qualified Data.ByteString.UTF8 as UTF8+import Data.FingerTree as FingerTree+import Data.Function (on)+import Data.Hashable+import Data.Interned+import Data.String+import Text.Trifecta.Rope.Delta++data Hunk = Hunk {-# UNPACK #-} !Id !Delta {-# UNPACK #-} !ByteString+ deriving Show++hunk :: ByteString -> Hunk+hunk = intern ++-- instance Show Hunk where showsPrec d (Hunk _ _ b) = showsPrec d b++instance IsString Hunk where+ fromString = hunk . UTF8.fromString++instance Eq Hunk where+ (==) = (==) `on` identity++instance Hashable Hunk where+ hash = hash . identity++instance Ord Hunk where+ compare = compare `on` identity++instance HasDelta Hunk where+ delta (Hunk _ d _) = d++instance Interned Hunk where+ type Uninterned Hunk = ByteString+ data Description Hunk = Describe {-# UNPACK #-} !ByteString deriving (Eq)+ describe = Describe+ identify i bs = Hunk i (delta bs) bs+ identity (Hunk i _ _) = i+ cache = hunkCache++instance Uninternable Hunk where+ unintern (Hunk _ _ bs) = bs++instance Hashable (Description Hunk) where+ hash (Describe bs) = hash bs++hunkCache :: Cache Hunk+hunkCache = mkCache +{-# NOINLINE hunkCache #-}++instance Measured Delta Hunk where+ measure = delta
+ Text/Trifecta/Rope/Path.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE TypeFamilies, FlexibleInstances, BangPatterns #-}+module Text.Trifecta.Rope.Path+ ( FileName+ , Path(..), History(..)+ , file+ , snocPath+ , path+ , appendPath+ , comparablePath+ -- * Internals+ , MaybeFileName(..)+ , maybeFileName+ ) where++import Data.Hashable+import Data.Interned+import Data.Interned.String+import Data.Function (on)+import Data.Semigroup+import Data.IntSet as IntSet++type FileName = InternedString++data Path = Path {-# UNPACK #-} !Id !IntSet !History !MaybeFileName {-# UNPACK #-} !Int [Int]+ deriving Show++pathIds :: Path -> IntSet+pathIds (Path _ is _ _ _ _) = is++comparablePath :: Path -> Path -> Bool+comparablePath x y = identity x `IntSet.member` pathIds y+ || identity y `IntSet.member` pathIds x++instance Eq Path where+ (==) = (==) `on` identity++instance Ord Path where+ compare = compare `on` identity++data History = Continue !Path {-# UNPACK #-} !Int | Complete deriving (Eq, Show)++data MaybeFileName = JustFileName !FileName | NothingFileName deriving (Eq, Show)++maybeFileName :: r -> (FileName -> r) -> MaybeFileName -> r+maybeFileName n _ NothingFileName = n+maybeFileName _ f (JustFileName a) = f a++file :: String -> Path +file !n = path Complete (JustFileName (intern n)) 0 []++snocPath :: Path -> Int -> MaybeFileName -> Int -> [Int] -> Path+snocPath d l jf l' flags = path (Continue d l) jf l' flags++path :: History -> MaybeFileName -> Int -> [Int] -> Path+path !h !mf l flags = intern (UPath h mf l flags)++appendPath :: Path -> Int -> Path -> Path+appendPath p dl (Path _ _ Complete mf l flags) = snocPath p dl mf l flags+appendPath p dl (Path _ _ (Continue p' dl') mf l flags) = snocPath (appendPath p dl p') dl' mf l flags++instance Semigroup Path where+ p <> p' = appendPath p 0 p'++data UninternedPath = UPath !History !MaybeFileName {-# UNPACK #-} !Int [Int]+data DHistory = DContinue {-# UNPACK #-} !Id {-# UNPACK #-} !Int | DComplete deriving Eq++instance Hashable DHistory where+ hash (DContinue x y) = y `hashWithSalt` x+ hash DComplete = 0++instance Hashable Path where+ hash = hash . identity++instance Interned Path where+ type Uninterned Path = UninternedPath+ data Description Path = DPath !(Maybe Id) {-# UNPACK #-} !Int [Int] !DHistory deriving Eq+ describe (UPath h mf l flags) = DPath mi l flags $ case h of+ Continue p dl -> DContinue (identity p) dl+ Complete -> DComplete + where + mi = case mf of + JustFileName f -> Just (identity f)+ NothingFileName -> Nothing+ + identify i (UPath h mf l flags) = Path i m h mf l flags + where + m = case h of + Complete -> IntSet.singleton i+ Continue (Path _ m' _ _ _ _) _ -> IntSet.insert i m'+ + identity (Path i _ _ _ _ _) = i+ cache = pathCache++instance Uninternable Path where+ unintern (Path _ _ h mf l flags) = UPath h mf l flags++instance Hashable (Description Path) where+ hash (DPath mi l flags dh) = l `hashWithSalt` mi `hashWithSalt` flags `hashWithSalt` dh++pathCache :: Cache Path+pathCache = mkCache+{-# NOINLINE pathCache #-}+
+ Text/Trifecta/Rope/Prim.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, BangPatterns, PatternGuards #-}+module Text.Trifecta.Rope.Prim+ ( Rope(..)+ , rope+ , strands+ , grabRest+ , grabLine+ ) where++import Data.Monoid+import Data.Semigroup+import Data.Semigroup.Reducer+import qualified Data.ByteString as Strict+import qualified Data.ByteString.Lazy as Lazy+import Data.FingerTree as FingerTree+import Data.Foldable (toList)+import Text.Trifecta.Rope.Hunk+import Text.Trifecta.Rope.Path+import Text.Trifecta.Rope.Delta+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Strand+import Text.Trifecta.Util as Util++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 (toList r) (delta l) (bytes i - bytes l) where+ trim (PathStrand p : xs) j k = trim xs (j <> delta p) k+ trim (HunkStrand (Hunk _ _ h) : xs) j 0 = go j h xs+ trim (HunkStrand (Hunk _ _ h) : xs) _ k = go i (Strict.drop k h) xs+ trim [] _ _ = kf+ go j h s = ks j $ Lazy.fromChunks $ h : [ a | HunkStrand (Hunk _ _ 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 (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 Hunk Rope where+ unit s = Rope (delta s) (singleton (HunkStrand s))+ cons s (Rope mt t) = Rope (delta s `mappend` mt) (HunkStrand s <| t)+ snoc (Rope mt t) s = Rope (mt `mappend` delta s) (t |> HunkStrand s)+ +instance Reducer Path Rope where+ unit s = Rope (delta s) (singleton (PathStrand s))+ cons s (Rope mt t) = Rope (delta s `mappend` mt) (PathStrand s <| t)+ snoc (Rope mt t) s = Rope (mt `mappend` delta s) (t |> PathStrand s)++instance Reducer Strict.ByteString Rope where+ unit = unit . hunk+ cons = cons . hunk + snoc r = snoc r . hunk
+ Text/Trifecta/Rope/Strand.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}+module Text.Trifecta.Rope.Strand+ ( Strand(..)+ ) where++import Data.Interned+import Data.Hashable+import Data.ByteString as Strict+import Data.FingerTree as FingerTree+import Text.Trifecta.Rope.Hunk+import Text.Trifecta.Rope.Path+import Text.Trifecta.Rope.Bytes+import Text.Trifecta.Rope.Delta++data Strand+ = HunkStrand !Hunk+ | PathStrand !Path+ deriving Show++--instance Show Strand where+-- showsPrec d (HunkStrand h) = showsPrec d h+-- showsPrec d (PathStrand p) = showsPrec d p++instance Measured Delta Strand where+ measure (HunkStrand s) = delta s+ measure (PathStrand p) = delta p++instance Hashable Strand where+ hash (HunkStrand h) = hashWithSalt 0 h+ hash (PathStrand p) = hashWithSalt 0 p++instance HasDelta Strand where+ delta = measure++instance HasBytes Strand where+ bytes (HunkStrand h) = Strict.length (unintern h)+ bytes _ = 0
− Text/Trifecta/Strand.hs
@@ -1,37 +0,0 @@-{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}-module Text.Trifecta.Strand- ( Strand(..)- ) where--import Data.Interned-import Data.Hashable-import Data.ByteString as Strict-import Data.FingerTree as FingerTree-import Text.Trifecta.Hunk-import Text.Trifecta.Path-import Text.Trifecta.Bytes-import Text.Trifecta.Delta--data Strand- = HunkStrand !Hunk- | PathStrand !Path- deriving Show----instance Show Strand where--- showsPrec d (HunkStrand h) = showsPrec d h--- showsPrec d (PathStrand p) = showsPrec d p--instance Measured Delta Strand where- measure (HunkStrand s) = delta s- measure (PathStrand p) = delta p--instance Hashable Strand where- hash (HunkStrand h) = hashWithSalt 0 h- hash (PathStrand p) = hashWithSalt 0 p--instance HasDelta Strand where- delta = measure--instance HasBytes Strand where- bytes (HunkStrand h) = Strict.length (unintern h)- bytes _ = 0
− Text/Trifecta/Util/MaybePair.hs
@@ -1,62 +0,0 @@-module Text.Trifecta.Util.MaybePair- ( MaybePair(..)- ) where--import Control.Applicative-import Data.Semigroup-import Data.Monoid-import Data.Functor.Apply-import Data.Functor.Plus-import Data.Bifunctor-import Data.Bifoldable-import Data.Bitraversable-import Data.Foldable-import Data.Traversable--data MaybePair a b = JustPair a b | NothingPair- deriving (Eq,Ord,Show,Read)--instance (Semigroup a, Semigroup b) => Semigroup (MaybePair a b) where- a <> NothingPair = a- NothingPair <> b = b- JustPair a b <> JustPair c d = JustPair (a <> c) (b <> d)--instance (Semigroup a, Semigroup b) => Monoid (MaybePair a b) where- mappend = (<>) - mempty = NothingPair--instance Bifunctor MaybePair where- bimap f g (JustPair a b) = JustPair (f a) (g b)- bimap _ _ NothingPair = NothingPair- -instance Functor (MaybePair a) where- fmap f (JustPair a b) = JustPair a (f b)- fmap _ NothingPair = NothingPair--instance Semigroup a => Apply (MaybePair a) where- JustPair a b <.> JustPair c d = JustPair (a <> c) (b d)- _ <.> _ = NothingPair--instance Semigroup a => Alt (MaybePair a) where- a <!> NothingPair = a- NothingPair <!> b = b- JustPair a b <!> JustPair c _ = JustPair (a <> c) b--instance Semigroup a => Plus (MaybePair a) where- zero = NothingPair--instance Foldable (MaybePair a) where- foldMap f (JustPair _ b) = f b- foldMap _ NothingPair = mempty--instance Traversable (MaybePair a) where- traverse f (JustPair a b) = JustPair a <$> f b- traverse _ NothingPair = pure NothingPair--instance Bifoldable MaybePair where- bifoldMap f g (JustPair a b) = f a `mappend` g b- bifoldMap _ _ NothingPair = mempty--instance Bitraversable MaybePair where- bitraverse f g (JustPair a b) = JustPair <$> f a <*> g b- bitraverse _ _ NothingPair = pure NothingPair
trifecta.cabal view
@@ -1,6 +1,6 @@ name: trifecta category: Text, Parsing, Diagnostics, Pretty Printer, Logging-version: 0.16.1+version: 0.17 license: BSD3 cabal-version: >= 1.6 license-file: LICENSE@@ -8,9 +8,9 @@ maintainer: Edward A. Kmett <ekmett@gmail.com> stability: experimental homepage: http://github.com/ekmett/trifecta/-copyright: Copyright (C) 2011 Edward A. Kmett+copyright: Copyright (C) 2010-2011 Edward A. Kmett synopsis: A modern parser combinator library with convenient diagnostics-description: A modern parser combinator library with slicing and Clang-style colored diagnostics+description: A modern unicode-aware parser combinator library with slicing and Clang-style colored diagnostics build-type: Simple source-repository head@@ -20,36 +20,48 @@ library exposed-modules: Text.Trifecta- Text.Trifecta.Bytes- Text.Trifecta.Delta+ Text.Trifecta.CharSet+ Text.Trifecta.CharSet.Prim+ Text.Trifecta.CharSet.Common+ Text.Trifecta.CharSet.Posix.Ascii+ Text.Trifecta.CharSet.Posix.Unicode+ Text.Trifecta.CharSet.Unicode+ Text.Trifecta.CharSet.Unicode.Block+ Text.Trifecta.CharSet.Unicode.Category+ Text.Trifecta.Rope.Bytes+ Text.Trifecta.Rope.Delta+ Text.Trifecta.Rope.Hunk+ Text.Trifecta.Rope.Path+ Text.Trifecta.Rope.Prim+ Text.Trifecta.Rope.Strand Text.Trifecta.Diagnostic+ Text.Trifecta.Diagnostic.Prim Text.Trifecta.Diagnostic.Level- Text.Trifecta.Hunk+ Text.Trifecta.Diagnostic.Err+ Text.Trifecta.Diagnostic.Err.State+ Text.Trifecta.Diagnostic.Rendering+ Text.Trifecta.Diagnostic.Rendering.Prim+ Text.Trifecta.Diagnostic.Rendering.Caret+ Text.Trifecta.Diagnostic.Rendering.Fixit+ Text.Trifecta.Diagnostic.Rendering.Span Text.Trifecta.Parser.It Text.Trifecta.Parser.Char Text.Trifecta.Parser.Class- Text.Trifecta.Parser.Err- Text.Trifecta.Parser.Err.State Text.Trifecta.Parser.Prim Text.Trifecta.Parser.Result Text.Trifecta.Parser.Combinators Text.Trifecta.Parser.Step+ Text.Trifecta.Parser.Token Text.Trifecta.Parser.Token.Class Text.Trifecta.Parser.Token.Combinators- Text.Trifecta.Parser.Token.Prim Text.Trifecta.Parser.Token.Style+ Text.Trifecta.Parser.Token.Identifier+ Text.Trifecta.Parser.Token.Identifier.Style Text.Trifecta.Parser.Expr- Text.Trifecta.Path- Text.Trifecta.Render.Prim- Text.Trifecta.Render.Caret- Text.Trifecta.Render.Fixit- Text.Trifecta.Render.Span- Text.Trifecta.Rope- Text.Trifecta.Strand- Text.Trifecta.Util.MaybePair other-modules: Text.Trifecta.Util+ Text.Trifecta.CharSet.AsciiSet ghc-options: -Wall