parseAbbBind forLetrec
    = do var <- identifier <|> symbol "_"
         -- For a letrec, we need to temporarily add a binding, so that
         -- we can lookup this variable while parsing the body.  
         -- Note that both setState calls use the original Context
         ctx <- getState
         when forLetrec $ setState $ appendBinding var NameBind ctx
         binding <- getBinding var
         setState $ appendBinding var binding ctx
         return $ TmBind var binding
    where getBinding var = if (isUpper $ var !! 0)
                           then (try $ completeTyAbbBind var) <|>
                                (return TyVarBind)
                           else withType <|> withoutType
          withoutType    = do symbol "="
                              t <- parseTerm
                              liftM (TmAbbBind t) (getType t)
          withType       = do symbol ":"
                              ty <- parseType
                              symbol "="
                              liftM ((flip TmAbbBind) (Just ty)) parseTerm
          completeTyAbbBind var 
                         = do symbol "="
                              ty <- parseType
                              return $ TyAbbBind ty
          getType t      = do ctx <- getState
                              case evalState (runErrorT (typeof t)) ctx of
                                Left err -> return Nothing
                                Right ty -> return $ Just ty
parseAbbBind forLetrec
    = do var <- identifier <|> symbol "_"
         -- For a letrec, we need to temporarily add a binding, so that
         -- we can lookup this variable while parsing the body.  
         -- Note that both setState calls use the original Context
         ctx <- getState
         when forLetrec $ setState $ appendBinding var NameBind ctx
         binding <- getBinding var
         setState $ appendBinding var binding ctx
         return $ TmBind var binding
    where getBinding var = if (isUpper $ var !! 0)
                           then (try $ completeTyAbbBind var) <|>
                                (return TyVarBind)
                           else withType <|> withoutType
          withoutType    = do symbol "="
                              t <- parseTerm
                              liftM (TmAbbBind t) (getType t)
          withType       = do symbol ":"
                              ty <- parseType
                              symbol "="
                              liftM ((flip TmAbbBind) (Just ty)) parseTerm
          completeTyAbbBind var 
                         = do symbol "="
                              ty <- parseType
                              return $ TyAbbBind ty
          getType t      = do ctx <- getState
                              case evalState (runErrorT (typeof t)) ctx of
                                Left err -> return Nothing
                                Right ty -> return $ Just ty
parseAbbBind forLetrec
    = do var <- identifier <|> symbol "_"
         -- For a letrec, we need to temporarily add a binding, so that
         -- we can lookup this variable while parsing the body.  
         -- Note that both setState calls use the original Context
         ctx <- getState
         when forLetrec $ setState $ appendBinding var NameBind ctx
         binding <- getBinding var
         setState $ appendBinding var binding ctx
         return $ TmBind var binding
    where getBinding var = if (isUpper $ var !! 0)
                           then (try $ completeTyAbbBind var) <|>
                                (return TyVarBind)
                           else withType <|> withoutType
          withoutType    = do symbol "="
                              t <- parseTerm
                              liftM (TmAbbBind t) (getType t)
          withType       = do symbol ":"
                              ty <- parseType
                              symbol "="
                              liftM ((flip TmAbbBind) (Just ty)) parseTerm
          completeTyAbbBind var 
                         = do symbol "="
                              ty <- parseType
                              return $ TyAbbBind ty
          getType t      = do ctx <- getState
                              case evalState (runErrorT (typeof t)) ctx of
                                Left err -> return Nothing
                                Right ty -> return $ Just ty