[project @ 2003-07-31 17:45:22 by ross]
[ghc-base.git] / Text / ParserCombinators / Parsec / Prim.hs
diff --git a/Text/ParserCombinators/Parsec/Prim.hs b/Text/ParserCombinators/Parsec/Prim.hs
deleted file mode 100644 (file)
index 4889717..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Text.ParserCombinators.Parsec.Prim
--- Copyright   :  (c) Daan Leijen 1999-2001
--- License     :  BSD-style (see the file libraries/base/LICENSE)
--- 
--- Maintainer  :  daan@cs.uu.nl
--- Stability   :  provisional
--- Portability :  portable
---
--- The primitive parser combinators.
--- 
------------------------------------------------------------------------------
-
-module Text.ParserCombinators.Parsec.Prim
-                   ( -- operators: label a parser, alternative
-                     (<?>), (<|>)
-
-                   -- basic types
-                   , Parser, GenParser
-                   , runParser, parse, parseFromFile, parseTest
-                   
-                   -- primitive parsers:
-                   -- instance Functor Parser     : fmap
-                   -- instance Monad Parser       : return, >>=, fail
-                   -- instance MonadPlus Parser   : mzero (pzero), mplus (<|>)
-                   , token, tokens, tokenPrim
-                   , try, label, labels, unexpected, pzero
-
-                   -- primitive because of space behaviour
-                   , many, skipMany
-                                
-                   -- user state manipulation
-                   , getState, setState, updateState
-
-                   -- state manipulation
-                   , getPosition, setPosition
-                   , getInput, setInput                   
-                   , getParserState, setParserState 
-                 ) where
-
-import Prelude
-import Text.ParserCombinators.Parsec.Pos
-import Text.ParserCombinators.Parsec.Error
-import Control.Monad
-
-{-# INLINE parsecMap    #-}
-{-# INLINE parsecReturn #-}
-{-# INLINE parsecBind   #-}
-{-# INLINE parsecZero   #-}
-{-# INLINE parsecPlus   #-}
-{-# INLINE token        #-}
-{-# INLINE tokenPrim    #-}
-
------------------------------------------------------------
--- Operators:
--- <?>  gives a name to a parser (which is used in error messages)
--- <|>  is the choice operator
------------------------------------------------------------
-infix  0 <?>
-infixr 1 <|>
-
-(<?>) :: GenParser tok st a -> String -> GenParser tok st a
-p <?> msg           = label p msg
-
-(<|>) :: GenParser tok st a -> GenParser tok st a -> GenParser tok st a
-p1 <|> p2           = mplus p1 p2
-
-
------------------------------------------------------------
--- User state combinators
------------------------------------------------------------
-getState :: GenParser tok st st
-getState        = do{ state <- getParserState
-                    ; return (stateUser state)
-                    }
-
-setState :: st -> GenParser tok st ()
-setState st     = do{ updateParserState (\(State input pos _) -> State input pos st)
-                    ; return ()
-                    }
-
-updateState :: (st -> st) -> GenParser tok st ()
-updateState f   = do{ updateParserState (\(State input pos user) -> State input pos (f user))
-                    ; return ()
-                    }
-
-
------------------------------------------------------------
--- Parser state combinators
------------------------------------------------------------
-getPosition :: GenParser tok st SourcePos
-getPosition         = do{ state <- getParserState; return (statePos state) }
-
-getInput :: GenParser tok st [tok]
-getInput            = do{ state <- getParserState; return (stateInput state) }
-
-
-setPosition :: SourcePos -> GenParser tok st ()
-setPosition pos     = do{ updateParserState (\(State input _ user) -> State input pos user)
-                        ; return ()
-                        }
-                        
-setInput :: [tok] -> GenParser tok st ()
-setInput input      = do{ updateParserState (\(State _ pos user) -> State input pos user)
-                        ; return ()
-                        }
-
-getParserState     :: GenParser tok st (State tok st)
-getParserState      =  updateParserState id    
-
-setParserState     :: State tok st -> GenParser tok st (State tok st)
-setParserState st   = updateParserState (const st)
-
-
-
-
------------------------------------------------------------
--- Parser definition.
--- GenParser tok st a:
---  General parser for tokens of type "tok", 
---  a user state "st" and a result type "a"
------------------------------------------------------------
-type Parser a           = GenParser Char () a
-
-newtype GenParser tok st a = Parser (State tok st -> Consumed (Reply tok st a))
-runP (Parser p)            = p
-
-data Consumed a         = Consumed a                --input is consumed
-                        | Empty !a                  --no input is consumed
-                    
-data Reply tok st a     = Ok a (State tok st) ParseError      --parsing succeeded with "a"
-                        | Error ParseError                    --parsing failed
-
-data State tok st       = State { stateInput :: [tok]
-                                , statePos   :: SourcePos
-                                , stateUser  :: !st
-                                }
-
-
------------------------------------------------------------
--- run a parser
------------------------------------------------------------
-parseFromFile :: Parser a -> SourceName -> IO (Either ParseError a)
-parseFromFile p fname
-    = do{ input <- readFile fname
-        ; return (parse p fname input)
-        }
-
-parseTest :: Show a => GenParser tok () a -> [tok] -> IO ()
-parseTest p input
-    = case (runParser p () "" input) of
-        Left err -> do{ putStr "parse error at "
-                      ; print err
-                      }
-        Right x  -> print x
-
-
-parse :: GenParser tok () a -> SourceName -> [tok] -> Either ParseError a
-parse p name input
-    = runParser p () name input
-
-
-runParser :: GenParser tok st a -> st -> SourceName -> [tok] -> Either ParseError a
-runParser p st name input
-    = case parserReply (runP p (State input (initialPos name) st)) of
-        Ok x _ _    -> Right x
-        Error err   -> Left err
-
-parserReply result     
-    = case result of
-        Consumed reply -> reply
-        Empty reply    -> reply
-
-
------------------------------------------------------------
--- Functor: fmap
------------------------------------------------------------
-instance Functor (GenParser tok st) where
-  fmap f p  = parsecMap f p
-
-parsecMap :: (a -> b) -> GenParser tok st a -> GenParser tok st b
-parsecMap f (Parser p)
-    = Parser (\state -> 
-        case (p state) of
-          Consumed reply -> Consumed (mapReply reply)
-          Empty    reply -> Empty    (mapReply reply)
-      )
-    where
-      mapReply reply
-        = case reply of
-            Ok x state err -> let fx = f x 
-                              in seq fx (Ok fx state err)
-            Error err      -> Error err
-           
-
------------------------------------------------------------
--- Monad: return, sequence (>>=) and fail
------------------------------------------------------------    
-instance Monad (GenParser tok st) where
-  return x   = parsecReturn x  
-  p >>= f    = parsecBind p f
-  fail msg   = parsecFail msg
-
-parsecReturn :: a -> GenParser tok st a
-parsecReturn x
-  = Parser (\state -> Empty (Ok x state (unknownError state)))   
-
-parsecBind :: GenParser tok st a -> (a -> GenParser tok st b) -> GenParser tok st b
-parsecBind (Parser p) f
-    = Parser (\state ->
-        case (p state) of                 
-          Consumed reply1 
-            -> Consumed $
-               case (reply1) of
-                 Ok x state1 err1 -> case runP (f x) state1 of
-                                       Empty reply2    -> mergeErrorReply err1 reply2
-                                       Consumed reply2 -> reply2
-                 Error err1       -> Error err1
-
-          Empty reply1    
-            -> case (reply1) of
-                 Ok x state1 err1 -> case runP (f x) state1 of
-                                       Empty reply2 -> Empty (mergeErrorReply err1 reply2)
-                                       other        -> other                                                    
-                 Error err1       -> Empty (Error err1)
-      )                                                              
-
-mergeErrorReply err1 reply
-  = case reply of
-      Ok x state err2 -> Ok x state (mergeError err1 err2)
-      Error err2      -> Error (mergeError err1 err2)
-
-
-parsecFail :: String -> GenParser tok st a
-parsecFail msg
-  = Parser (\state -> 
-      Empty (Error (newErrorMessage (Message msg) (statePos state))))
-
-
------------------------------------------------------------
--- MonadPlus: alternative (mplus) and mzero
------------------------------------------------------------
-instance MonadPlus (GenParser tok st) where
-  mzero         = parsecZero
-  mplus p1 p2   = parsecPlus p1 p2
-      
-
-pzero :: GenParser tok st a
-pzero = parsecZero
-
-parsecZero :: GenParser tok st a
-parsecZero
-    = Parser (\state -> Empty (Error (unknownError state)))
-
-parsecPlus :: GenParser tok st a -> GenParser tok st a -> GenParser tok st a
-parsecPlus (Parser p1) (Parser p2)
-    = Parser (\state ->
-        case (p1 state) of        
-          Empty (Error err) -> case (p2 state) of
-                                 Empty reply -> Empty (mergeErrorReply err reply)
-                                 consumed    -> consumed
-          other             -> other
-      )
-
-
-{- 
--- variant that favors a consumed reply over an empty one, even it is not the first alternative.
-          empty@(Empty reply) -> case reply of
-                                   Error err ->
-                                     case (p2 state) of
-                                       Empty reply -> Empty (mergeErrorReply err reply)
-                                       consumed    -> consumed
-                                   ok ->
-                                     case (p2 state) of
-                                       Empty reply -> empty
-                                       consumed    -> consumed
-          consumed  -> consumed
--}
-
-
------------------------------------------------------------
--- Primitive Parsers: 
---  try, token(Prim), label, unexpected and updateState
------------------------------------------------------------
-try :: GenParser tok st a -> GenParser tok st a
-try (Parser p)
-    = Parser (\state@(State input pos user) ->     
-        case (p state) of
-          Consumed (Error err)  -> Empty (Error (setErrorPos pos err))
-          Consumed ok           -> Consumed ok    -- was: Empty ok
-          empty                 -> empty
-      )
-
-     
-token :: (tok -> String) -> (tok -> SourcePos) -> (tok -> Maybe a) -> GenParser tok st a    
-token show tokpos test
-  = tokenPrim show nextpos test
-  where
-    nextpos _ _   (tok:toks)  = tokpos tok
-    nextpos _ tok []          = tokpos tok
-
-tokenPrim :: (tok -> String) -> (SourcePos -> tok -> [tok] -> SourcePos) -> (tok -> Maybe a) -> GenParser tok st a
-tokenPrim show nextpos test
-    = Parser (\state@(State input pos user) -> 
-        case input of
-          (c:cs) -> case test c of
-                      Just x  -> let newpos   = nextpos pos c cs
-                                     newstate = State cs newpos user
-                                 in seq newpos $ seq newstate $ 
-                                    Consumed (Ok x newstate (newErrorUnknown newpos))
-                      Nothing -> Empty (sysUnExpectError (show c) pos)
-          []     -> Empty (sysUnExpectError "" pos)
-      )
-
-
-label :: GenParser tok st a -> String -> GenParser tok st a    
-label p msg
-  = labels p [msg]
-
-labels :: GenParser tok st a -> [String] -> GenParser tok st a
-labels (Parser p) msgs
-    = Parser (\state -> 
-        case (p state) of
-          Empty reply -> Empty $ 
-                         case (reply) of
-                           Error err        -> Error (setExpectErrors err msgs)
-                           Ok x state1 err  | errorIsUnknown err -> reply
-                                            | otherwise -> Ok x state1 (setExpectErrors err msgs)
-          other       -> other
-      )
-
-
-updateParserState :: (State tok st -> State tok st) -> GenParser tok st (State tok st)
-updateParserState f 
-    = Parser (\state -> let newstate = f state
-                        in seq newstate $
-                           Empty (Ok state newstate (unknownError newstate)))
-    
-    
-unexpected :: String -> GenParser tok st a
-unexpected msg
-    = Parser (\state -> Empty (Error (newErrorMessage (UnExpect msg) (statePos state))))
-    
-
-setExpectErrors err []         = setErrorMessage (Expect "") err
-setExpectErrors err [msg]      = setErrorMessage (Expect msg) err
-setExpectErrors err (msg:msgs) = foldr (\msg err -> addErrorMessage (Expect msg) err) 
-                                       (setErrorMessage (Expect msg) err) msgs
-
-sysUnExpectError msg pos  = Error (newErrorMessage (SysUnExpect msg) pos)
-unknownError state        = newErrorUnknown (statePos state)
-
------------------------------------------------------------
--- Parsers unfolded for space:
--- if many and skipMany are not defined as primitives,
--- they will overflow the stack on large inputs
------------------------------------------------------------    
-many :: GenParser tok st a -> GenParser tok st [a]
-many p
-  = do{ xs <- manyAccum (:) p
-      ; return (reverse xs)
-      }
-
-skipMany :: GenParser tok st a -> GenParser tok st ()
-skipMany p
-  = do{ manyAccum (\x xs -> []) p
-      ; return ()
-      }
-
-manyAccum :: (a -> [a] -> [a]) -> GenParser tok st a -> GenParser tok st [a]
-manyAccum accum (Parser p)
-  = Parser (\state -> 
-    let walk xs state r = case r of
-                           Empty (Error err)          -> Ok xs state err
-                           Empty ok                   -> error "Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string."
-                           Consumed (Error err)       -> Error err
-                           Consumed (Ok x state' err) -> let ys = accum x xs
-                                                         in seq ys (walk ys state' (p state'))
-    in case (p state) of
-         Empty reply  -> case reply of
-                           Ok x state' err -> error "Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string."
-                           Error err       -> Empty (Ok [] state err)
-         consumed     -> Consumed $ walk [] state consumed)
-
-
-
------------------------------------------------------------
--- Parsers unfolded for speed: 
---  tokens
------------------------------------------------------------    
-
-{- specification of @tokens@:
-tokens showss nextposs s
-  = scan s
-  where
-    scan []       = return s
-    scan (c:cs)   = do{ token show nextpos c <?> shows s; scan cs }                      
-
-    show c        = shows [c]
-    nextpos pos c = nextposs pos [c]
--}
-
-tokens :: Eq tok => ([tok] -> String) -> (SourcePos -> [tok] -> SourcePos) -> [tok] -> GenParser tok st [tok]
-tokens shows nextposs s
-    = Parser (\state@(State input pos user) -> 
-       let
-        ok cs             = let newpos   = nextposs pos s
-                                newstate = State cs newpos user
-                            in seq newpos $ seq newstate $ 
-                               (Ok s newstate (newErrorUnknown newpos))
-                               
-        errEof            = Error (setErrorMessage (Expect (shows s))
-                                     (newErrorMessage (SysUnExpect "") pos))
-        errExpect c       = Error (setErrorMessage (Expect (shows s))
-                                     (newErrorMessage (SysUnExpect (shows [c])) pos))
-
-        walk [] cs        = ok cs
-        walk xs []        = errEof
-        walk (x:xs) (c:cs)| x == c        = walk xs cs
-                          | otherwise     = errExpect c
-
-        walk1 [] cs        = Empty (ok cs)
-        walk1 xs []        = Empty (errEof)
-        walk1 (x:xs) (c:cs)| x == c        = Consumed (walk xs cs)
-                           | otherwise     = Empty (errExpect c)
-
-       in walk1 s input)
-
-