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 ------------------------------------------------------------------------------
32 import Data.Generics.Basics
33 import Data.Generics.Aliases
34 import Text.ParserCombinators.ReadP
36 ------------------------------------------------------------------------------
39 -- | Generic show: an alternative to \"deriving Show\"
40 gshow :: Data a => a -> String
42 -- This is a prefix-show using surrounding "(" and ")",
43 -- where we recurse into subterms with gmapQ.
47 ++ conString (toConstr t)
48 ++ concat (gmapQ ((++) " " . gshow) t)
50 ) `extQ` (show :: String -> String)
54 -- | Generic read: an alternative to \"deriving Read\"
55 gread :: Data a => ReadS a
59 This is a read operation which insists on prefix notation. (The
60 Haskell 98 read deals with infix operators subject to associativity
61 and precedence as well.) We use gunfoldR to "parse" the input. To be
62 precise, gunfoldR is used for all types except String. The
63 type-specific case for String uses basic String read.
67 gread = readP_to_S gread'
71 gread' :: Data a => ReadP a
72 gread' = gdefault `extR` scase
77 -- A specific case for strings
79 scase = readS_to_P reads
82 -- The generic default for gread
83 -- gdefault :: Data a => ReadP a
87 skipSpaces -- Discard leading space
89 skipSpaces -- Discard following space
92 str <- parseConstr -- Get a lexeme for the constructor
93 con <- str2con str -- Convert it to a Constr (may fail)
94 x <- gunfoldR con gread' -- Read the children
97 skipSpaces -- Discard leading space
99 skipSpaces -- Discard following space
105 -- Get the datatype for the type at hand;
106 -- use gdefault to provide the type at hand.
107 myDataTypeOf :: Data a => ReadP a -> DataType
108 myDataTypeOf (_::ReadP a) = dataTypeOf (undefined::a)
110 -- Turn string into constructor driven by gdefault's type,
111 -- failing in the monad if it isn't a constructor of this data type
112 str2con :: String -> ReadP Constr
113 str2con = maybe mzero return
114 . stringCon (myDataTypeOf gdefault)
116 -- Get a Constr's string at the front of an input string
117 parseConstr :: ReadP String
119 string "[]" -- Compound lexeme "[]"
120 <++ infixOp -- Infix operator in parantheses
121 <++ readS_to_P lex -- Ordinary constructors and literals
123 -- Handle infix operators such as (:)
124 infixOp :: ReadP String
125 infixOp = do c1 <- char '('
126 str <- munch1 (not . (==) ')')
128 return $ [c1] ++ str ++ [c2]