1 -----------------------------------------------------------------------------
3 -- Module : Text.ParserCombinators.Parsec.Prim
4 -- Copyright : (c) Daan Leijen 1999-2001
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : daan@cs.uu.nl
8 -- Stability : provisional
9 -- Portability : portable
11 -- The primitive parser combinators.
13 -----------------------------------------------------------------------------
15 module Text.ParserCombinators.Parsec.Prim
16 ( -- operators: label a parser, alternative
21 , runParser, parse, parseFromFile, parseTest
24 -- instance Functor Parser : fmap
25 -- instance Monad Parser : return, >>=, fail
26 -- instance MonadPlus Parser : mzero (pzero), mplus (<|>)
27 , token, tokens, tokenPrim
28 , try, label, labels, unexpected, pzero
30 -- primitive because of space behaviour
33 -- user state manipulation
34 , getState, setState, updateState
37 , getPosition, setPosition
39 , getParserState, setParserState
43 import Text.ParserCombinators.Parsec.Pos
44 import Text.ParserCombinators.Parsec.Error
47 {-# INLINE parsecMap #-}
48 {-# INLINE parsecReturn #-}
49 {-# INLINE parsecBind #-}
50 {-# INLINE parsecZero #-}
51 {-# INLINE parsecPlus #-}
53 {-# INLINE tokenPrim #-}
55 -----------------------------------------------------------
57 -- <?> gives a name to a parser (which is used in error messages)
58 -- <|> is the choice operator
59 -----------------------------------------------------------
63 (<?>) :: GenParser tok st a -> String -> GenParser tok st a
64 p <?> msg = label p msg
66 (<|>) :: GenParser tok st a -> GenParser tok st a -> GenParser tok st a
67 p1 <|> p2 = mplus p1 p2
70 -----------------------------------------------------------
71 -- User state combinators
72 -----------------------------------------------------------
73 getState :: GenParser tok st st
74 getState = do{ state <- getParserState
75 ; return (stateUser state)
78 setState :: st -> GenParser tok st ()
79 setState st = do{ updateParserState (\(State input pos _) -> State input pos st)
83 updateState :: (st -> st) -> GenParser tok st ()
84 updateState f = do{ updateParserState (\(State input pos user) -> State input pos (f user))
89 -----------------------------------------------------------
90 -- Parser state combinators
91 -----------------------------------------------------------
92 getPosition :: GenParser tok st SourcePos
93 getPosition = do{ state <- getParserState; return (statePos state) }
95 getInput :: GenParser tok st [tok]
96 getInput = do{ state <- getParserState; return (stateInput state) }
99 setPosition :: SourcePos -> GenParser tok st ()
100 setPosition pos = do{ updateParserState (\(State input _ user) -> State input pos user)
104 setInput :: [tok] -> GenParser tok st ()
105 setInput input = do{ updateParserState (\(State _ pos user) -> State input pos user)
109 getParserState :: GenParser tok st (State tok st)
110 getParserState = updateParserState id
112 setParserState :: State tok st -> GenParser tok st (State tok st)
113 setParserState st = updateParserState (const st)
118 -----------------------------------------------------------
119 -- Parser definition.
120 -- GenParser tok st a:
121 -- General parser for tokens of type "tok",
122 -- a user state "st" and a result type "a"
123 -----------------------------------------------------------
124 type Parser a = GenParser Char () a
126 newtype GenParser tok st a = Parser (State tok st -> Consumed (Reply tok st a))
129 data Consumed a = Consumed a --input is consumed
130 | Empty !a --no input is consumed
132 data Reply tok st a = Ok a (State tok st) ParseError --parsing succeeded with "a"
133 | Error ParseError --parsing failed
135 data State tok st = State { stateInput :: [tok]
136 , statePos :: SourcePos
141 -----------------------------------------------------------
143 -----------------------------------------------------------
144 parseFromFile :: Parser a -> SourceName -> IO (Either ParseError a)
145 parseFromFile p fname
146 = do{ input <- readFile fname
147 ; return (parse p fname input)
150 parseTest :: Show a => GenParser tok () a -> [tok] -> IO ()
152 = case (runParser p () "" input) of
153 Left err -> do{ putStr "parse error at "
159 parse :: GenParser tok () a -> SourceName -> [tok] -> Either ParseError a
161 = runParser p () name input
164 runParser :: GenParser tok st a -> st -> SourceName -> [tok] -> Either ParseError a
165 runParser p st name input
166 = case parserReply (runP p (State input (initialPos name) st)) of
168 Error err -> Left err
172 Consumed reply -> reply
176 -----------------------------------------------------------
178 -----------------------------------------------------------
179 instance Functor (GenParser tok st) where
180 fmap f p = parsecMap f p
182 parsecMap :: (a -> b) -> GenParser tok st a -> GenParser tok st b
183 parsecMap f (Parser p)
186 Consumed reply -> Consumed (mapReply reply)
187 Empty reply -> Empty (mapReply reply)
192 Ok x state err -> let fx = f x
193 in seq fx (Ok fx state err)
194 Error err -> Error err
197 -----------------------------------------------------------
198 -- Monad: return, sequence (>>=) and fail
199 -----------------------------------------------------------
200 instance Monad (GenParser tok st) where
201 return x = parsecReturn x
202 p >>= f = parsecBind p f
203 fail msg = parsecFail msg
205 parsecReturn :: a -> GenParser tok st a
207 = Parser (\state -> Empty (Ok x state (unknownError state)))
209 parsecBind :: GenParser tok st a -> (a -> GenParser tok st b) -> GenParser tok st b
210 parsecBind (Parser p) f
216 Ok x state1 err1 -> case runP (f x) state1 of
217 Empty reply2 -> mergeErrorReply err1 reply2
218 Consumed reply2 -> reply2
219 Error err1 -> Error err1
223 Ok x state1 err1 -> case runP (f x) state1 of
224 Empty reply2 -> Empty (mergeErrorReply err1 reply2)
226 Error err1 -> Empty (Error err1)
229 mergeErrorReply err1 reply
231 Ok x state err2 -> Ok x state (mergeError err1 err2)
232 Error err2 -> Error (mergeError err1 err2)
235 parsecFail :: String -> GenParser tok st a
238 Empty (Error (newErrorMessage (Message msg) (statePos state))))
241 -----------------------------------------------------------
242 -- MonadPlus: alternative (mplus) and mzero
243 -----------------------------------------------------------
244 instance MonadPlus (GenParser tok st) where
246 mplus p1 p2 = parsecPlus p1 p2
249 pzero :: GenParser tok st a
252 parsecZero :: GenParser tok st a
254 = Parser (\state -> Empty (Error (unknownError state)))
256 parsecPlus :: GenParser tok st a -> GenParser tok st a -> GenParser tok st a
257 parsecPlus (Parser p1) (Parser p2)
260 Empty (Error err) -> case (p2 state) of
261 Empty reply -> Empty (mergeErrorReply err reply)
268 -- variant that favors a consumed reply over an empty one, even it is not the first alternative.
269 empty@(Empty reply) -> case reply of
272 Empty reply -> Empty (mergeErrorReply err reply)
282 -----------------------------------------------------------
283 -- Primitive Parsers:
284 -- try, token(Prim), label, unexpected and updateState
285 -----------------------------------------------------------
286 try :: GenParser tok st a -> GenParser tok st a
288 = Parser (\state@(State input pos user) ->
290 Consumed (Error err) -> Empty (Error (setErrorPos pos err))
291 Consumed ok -> Consumed ok -- was: Empty ok
296 token :: (tok -> String) -> (tok -> SourcePos) -> (tok -> Maybe a) -> GenParser tok st a
297 token show tokpos test
298 = tokenPrim show nextpos test
300 nextpos _ _ (tok:toks) = tokpos tok
301 nextpos _ tok [] = tokpos tok
303 tokenPrim :: (tok -> String) -> (SourcePos -> tok -> [tok] -> SourcePos) -> (tok -> Maybe a) -> GenParser tok st a
304 tokenPrim show nextpos test
305 = Parser (\state@(State input pos user) ->
307 (c:cs) -> case test c of
308 Just x -> let newpos = nextpos pos c cs
309 newstate = State cs newpos user
310 in seq newpos $ seq newstate $
311 Consumed (Ok x newstate (newErrorUnknown newpos))
312 Nothing -> Empty (sysUnExpectError (show c) pos)
313 [] -> Empty (sysUnExpectError "" pos)
317 label :: GenParser tok st a -> String -> GenParser tok st a
321 labels :: GenParser tok st a -> [String] -> GenParser tok st a
322 labels (Parser p) msgs
325 Empty reply -> Empty $
327 Error err -> Error (setExpectErrors err msgs)
328 Ok x state1 err | errorIsUnknown err -> reply
329 | otherwise -> Ok x state1 (setExpectErrors err msgs)
334 updateParserState :: (State tok st -> State tok st) -> GenParser tok st (State tok st)
336 = Parser (\state -> let newstate = f state
338 Empty (Ok state newstate (unknownError newstate)))
341 unexpected :: String -> GenParser tok st a
343 = Parser (\state -> Empty (Error (newErrorMessage (UnExpect msg) (statePos state))))
346 setExpectErrors err [] = setErrorMessage (Expect "") err
347 setExpectErrors err [msg] = setErrorMessage (Expect msg) err
348 setExpectErrors err (msg:msgs) = foldr (\msg err -> addErrorMessage (Expect msg) err)
349 (setErrorMessage (Expect msg) err) msgs
351 sysUnExpectError msg pos = Error (newErrorMessage (SysUnExpect msg) pos)
352 unknownError state = newErrorUnknown (statePos state)
354 -----------------------------------------------------------
355 -- Parsers unfolded for space:
356 -- if many and skipMany are not defined as primitives,
357 -- they will overflow the stack on large inputs
358 -----------------------------------------------------------
359 many :: GenParser tok st a -> GenParser tok st [a]
361 = do{ xs <- manyAccum (:) p
362 ; return (reverse xs)
365 skipMany :: GenParser tok st a -> GenParser tok st ()
367 = do{ manyAccum (\x xs -> []) p
371 manyAccum :: (a -> [a] -> [a]) -> GenParser tok st a -> GenParser tok st [a]
372 manyAccum accum (Parser p)
374 let walk xs state r = case r of
375 Empty (Error err) -> Ok xs state err
376 Empty ok -> error "Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string."
377 Consumed (Error err) -> Error err
378 Consumed (Ok x state' err) -> let ys = accum x xs
379 in seq ys (walk ys state' (p state'))
381 Empty reply -> case reply of
382 Ok x state' err -> error "Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string."
383 Error err -> Empty (Ok [] state err)
384 consumed -> Consumed $ walk [] state consumed)
388 -----------------------------------------------------------
389 -- Parsers unfolded for speed:
391 -----------------------------------------------------------
393 {- specification of @tokens@:
394 tokens showss nextposs s
398 scan (c:cs) = do{ token show nextpos c <?> shows s; scan cs }
401 nextpos pos c = nextposs pos [c]
404 tokens :: Eq tok => ([tok] -> String) -> (SourcePos -> [tok] -> SourcePos) -> [tok] -> GenParser tok st [tok]
405 tokens shows nextposs s
406 = Parser (\state@(State input pos user) ->
408 ok cs = let newpos = nextposs pos s
409 newstate = State cs newpos user
410 in seq newpos $ seq newstate $
411 (Ok s newstate (newErrorUnknown newpos))
413 errEof = Error (setErrorMessage (Expect (shows s))
414 (newErrorMessage (SysUnExpect "") pos))
415 errExpect c = Error (setErrorMessage (Expect (shows s))
416 (newErrorMessage (SysUnExpect (shows [c])) pos))
420 walk (x:xs) (c:cs)| x == c = walk xs cs
421 | otherwise = errExpect c
423 walk1 [] cs = Empty (ok cs)
424 walk1 xs [] = Empty (errEof)
425 walk1 (x:xs) (c:cs)| x == c = Consumed (walk xs cs)
426 | otherwise = Empty (errExpect c)