ParseMonad.hs

This module defines the parser monad, and the function parseFile, which is the only way to invoke a parser.

module ParseMonad(PM,HToken,thenPM,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 SrcLoc
import SrcLocPretty
import PrettyPrint(pp)
import Monad(liftM,MonadPlus(..))
--import ExceptM()
import Control.Monad.Error()
 --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 Error (a,State))}

returnPM x = PM $ Right . (,) x
PM p1 `thenPM` xp2 = PM $ \ 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 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 = []

Plain-text version of ParseMonad.hs | Valid HTML?