HaRe-0.6: tools/base/parse2/ParseMonad.hs
{-+
This module defines the parser monad, and the function #parseFile#, which is
the only way to invoke a parser.
-}
module ParseMonad(thenPM,PM,HToken,returnPM,parseError,getSrcLoc,
State,get,set,setreturn,eof,eoftoken,
parseFile,parseTokens) where
import HsTokens(Token(GotEOF))
import HsLexerPass1(lexerPass1Only,lexerPass0,Pos(..),line,column)
import MUtils
import SrcLoc1
import SrcLocPretty
import PrettyPrint(pp)
import Control.Monad.Error
--import Control.Monad(liftM,MonadPlus(..))
import Monad
import ExceptM()
--import IOExts(trace) -- for debugging only
default(Int)
type HToken = (Token,(SrcLoc,String))
--type Pos = (Int,Int)
type Error = String
type LayoutContext = Int
type State = ([HToken],[LayoutContext])
-- Parser monad type:
newtype PM a = PM {unPM::(State->Either ParseMonad.Error (a,State))}
returnPM x = PM $ Right . (,) x
PM p1 `thenPM` xp2 = PM $ \ts -> p1 ts >>= uncurry (unPM . xp2) -- =<< p1 ts
failPM msg = PM $ \ _ -> Left msg
{-
emapPM f (PM p) = PM $ \ ts -> case p ts of
Right ans -> Right ans
Left err -> Left (f err)
-}
get = PM $ \ st -> Right (st,st)
set st = PM $ \ _ -> Right ((),st)
setreturn x st = PM $ \ _ -> Right (x,st)
instance Monad PM where
return=returnPM
(>>=) = thenPM
fail = parseError
{-instance Monad (Either String) where
(Left a) >>= _ = Left a
(Right b) >>= f = f b
return = Right
fail a = Left a -}
instance Functor PM where fmap = liftM
instance MonadPlus PM where
mzero = fail "parser failed"
PM p1 `mplus` PM p2 = PM $ \ s -> case p1 s of
y@(Right _) -> y
Left _ -> p2 s
getSrcLoc = fst.snd # peek
peek = tok1 # get
where
tok1 (ts,_) = case ts of
t:_ -> t
[] -> eoftoken
parseError msg = err =<< peek
where err (t,(p,s)) =
failPM $ pos++": "++msg
where pos = if p==eof
then "at end of file"
else pp p++", before "++s
parseFile pm f = parseTokens pm f . lexerPass0
parseTokens (PM p) f ts =
case p (map convPos $ lexerPass1Only ts,initial_layout_context_stack) of
Left err -> fail ({-f++": "++-}err)
Right (x,_) -> return x
where
convPos (t,(Pos n l c,s)) = {-seq loc-} (t,(loc,s))
where loc = SrcLoc f n l c
eoftoken = (GotEOF,(eof,""))
eof = SrcLoc "?" 0 (-1) (-1) -- hmm
initial_layout_context_stack = []