[project @ 2003-07-31 10:48:50 by panne]
[ghc-base.git] / Text / ParserCombinators / Parsec / Combinator.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module      :  Text.ParserCombinators.Parsec.Combinator
4 -- Copyright   :  (c) Daan Leijen 1999-2001
5 -- License     :  BSD-style (see the file libraries/base/LICENSE)
6 -- 
7 -- Maintainer  :  daan@cs.uu.nl
8 -- Stability   :  provisional
9 -- Portability :  portable
10 --
11 -- Commonly used generic combinators
12 -- 
13 -----------------------------------------------------------------------------
14
15 module Text.ParserCombinators.Parsec.Combinator
16                         ( choice
17                         , count
18                         , between
19                         , option, optional
20                         , skipMany1
21                         , many1
22                         , sepBy, sepBy1
23                         , endBy, endBy1
24                         , sepEndBy, sepEndBy1
25                         , chainl, chainl1
26                         , chainr, chainr1
27                         , eof, notFollowedBy
28                         
29                         -- tricky combinators
30                         , manyTill, lookAhead, anyToken
31                         ) where
32
33 import Control.Monad
34 import Text.ParserCombinators.Parsec.Prim
35
36
37 ----------------------------------------------------------------
38 --
39 ----------------------------------------------------------------
40 choice :: [GenParser tok st a] -> GenParser tok st a
41 choice ps           = foldr (<|>) mzero ps
42
43 option :: a -> GenParser tok st a -> GenParser tok st a
44 option x p          = p <|> return x
45
46 optional :: GenParser tok st a -> GenParser tok st ()
47 optional p          = do{ p; return ()} <|> return ()
48
49 between :: GenParser tok st open -> GenParser tok st close 
50             -> GenParser tok st a -> GenParser tok st a
51 between open close p
52                     = do{ open; x <- p; close; return x }
53                 
54                 
55 skipMany1 :: GenParser tok st a -> GenParser tok st ()
56 skipMany1 p         = do{ p; skipMany p }
57 {-
58 skipMany p          = scan
59                     where
60                       scan  = do{ p; scan } <|> return ()
61 -}
62
63 many1 :: GenParser tok st a -> GenParser tok st [a]
64 many1 p             = do{ x <- p; xs <- many p; return (x:xs) }
65 {-
66 many p              = scan id
67                     where
68                       scan f    = do{ x <- p
69                                     ; scan (\tail -> f (x:tail))
70                                     }
71                                 <|> return (f [])
72 -}
73
74 sepBy1,sepBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a]
75 sepBy p sep         = sepBy1 p sep <|> return []
76 sepBy1 p sep        = do{ x <- p
77                         ; xs <- many (sep >> p)
78                         ; return (x:xs)
79                         }
80
81 sepEndBy1, sepEndBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a]
82 sepEndBy1 p sep     = do{ x <- p
83                         ; do{ sep
84                             ; xs <- sepEndBy p sep
85                             ; return (x:xs)
86                             }
87                           <|> return [x]
88                         }
89         
90 sepEndBy p sep      = sepEndBy1 p sep <|> return []
91
92
93 endBy1,endBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a]
94 endBy1 p sep        = many1 (do{ x <- p; sep; return x })
95 endBy p sep         = many (do{ x <- p; sep; return x })
96
97 count :: Int -> GenParser tok st a -> GenParser tok st [a]
98 count n p           | n <= 0    = return []
99                     | otherwise = sequence (replicate n p)
100
101
102 chainr p op x       = chainr1 p op <|> return x
103 chainl p op x       = chainl1 p op <|> return x
104
105 chainr1,chainl1 :: GenParser tok st a -> GenParser tok st (a -> a -> a) -> GenParser tok st a
106 chainl1 p op        = do{ x <- p; rest x }
107                     where
108                       rest x    = do{ f <- op
109                                     ; y <- p
110                                     ; rest (f x y)
111                                     }
112                                 <|> return x
113                               
114 chainr1 p op        = scan
115                     where
116                       scan      = do{ x <- p; rest x }
117                       
118                       rest x    = do{ f <- op
119                                     ; y <- scan
120                                     ; return (f x y)
121                                     }
122                                 <|> return x
123
124 -----------------------------------------------------------
125 -- Tricky combinators
126 -----------------------------------------------------------
127 anyToken :: Show tok => GenParser tok st tok
128 anyToken            = tokenPrim show (\pos tok toks -> pos) Just
129
130 eof :: Show tok => GenParser tok st ()
131 eof                 = notFollowedBy anyToken <?> "end of input"   
132
133 notFollowedBy :: Show tok => GenParser tok st tok -> GenParser tok st ()   
134 notFollowedBy p     = try (do{ c <- p; unexpected (show [c]) }
135                            <|> return ()
136                           )
137
138 manyTill :: GenParser tok st a -> GenParser tok st end -> GenParser tok st [a]
139 manyTill p end      = scan
140                     where
141                       scan  = do{ end; return [] }
142                             <|>
143                               do{ x <- p; xs <- scan; return (x:xs) }
144
145
146 lookAhead :: GenParser tok st a -> GenParser tok st a
147 lookAhead p         = do{ state <- getParserState
148                         ; x <- p
149                         ; setParserState state
150                         ; return x
151                         }