1 -----------------------------------------------------------------------------
3 -- Module : Data.Generics.Text
4 -- Copyright : (c) The University of Glasgow, CWI 2001--2003
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : experimental
9 -- Portability : non-portable
11 -- \"Scrap your boilerplate\" --- Generic programming in Haskell
12 -- See <http://www.cs.vu.nl/boilerplate/>. The present module provides
13 -- generic operations for text serialisation of terms.
15 -----------------------------------------------------------------------------
17 module Data.Generics.Text (
24 ------------------------------------------------------------------------------
30 import Data.Generics.Basics
31 import Data.Generics.Aliases
32 import Text.ParserCombinators.ReadP
35 ------------------------------------------------------------------------------
38 -- | Generic show: an alternative to \"deriving Show\"
39 gshow :: Data a => a -> String
41 -- This is a prefix-show using surrounding "(" and ")",
42 -- where we recurse into subterms with gmapQ.
46 ++ conString (toConstr t)
47 ++ concat (gmapQ ((++) " " . gshow) t)
49 ) `extQ` (show :: String -> String)
53 -- | Generic read: an alternative to \"deriving Read\"
54 gread :: Data a => ReadS a
58 This is a read operation which insists on prefix notation. (The
59 Haskell 98 read deals with infix operators subject to associativity
60 and precedence as well.) We use gunfoldM to "parse" the input. To be
61 precise, gunfoldM is used for all types except String. The
62 type-specific case for String uses basic String read.
66 gread = readP_to_S gread'
70 gread' :: Data a => ReadP a
71 gread' = gdefault `extB` scase
76 -- A specific case for strings
78 scase = readS_to_P reads
81 -- The generic default for gread
82 -- gdefault :: Data a => ReadP a
86 skipSpaces -- Discard leading space
88 skipSpaces -- Discard following space
91 str <- parseConstr -- Get a lexeme for the constructor
92 con <- str2con str -- Convert it to a Constr (may fail)
93 x <- gunfoldM con gread' -- Read the children
96 skipSpaces -- Discard leading space
98 skipSpaces -- Discard following space
104 -- Get the datatype for the type at hand;
105 -- use gdefault to provide the type at hand.
106 myDataTypeOf :: Data a => ReadP a -> DataType
107 myDataTypeOf (_::ReadP a) = dataTypeOf (undefined::a)
109 -- Turn string into constructor driven by gdefault's type,
110 -- failing in the monad if it isn't a constructor of this data type
111 str2con :: String -> ReadP Constr
112 str2con = maybe mzero return
113 . stringCon (myDataTypeOf gdefault)
115 -- Get a Constr's string at the front of an input string
116 parseConstr :: ReadP String
118 string "[]" -- Compound lexeme "[]"
119 <++ infixOp -- Infix operator in parantheses
120 <++ readS_to_P lex -- Ordinary constructors and literals
122 -- Handle infix operators such as (:)
123 infixOp :: ReadP String
124 infixOp = do c1 <- char '('
125 str <- munch1 (not . (==) ')')
127 return $ [c1] ++ str ++ [c2]