import' :: IParser Module.UserImport
import' =
  expecting "an import" $
  do  try (reserved "import")
      preName <- whitespace
      names <- dotSep1 capVar
      method' <- method names
      return ((,) preName names, method')
  where
    method :: [UppercaseIdentifier] -> IParser Module.ImportMethod
    method originalName =
      Module.ImportMethod
        <$> option Nothing (Just <$> as' originalName)
        <*> option ([], ([], Var.ClosedListing)) exposing

    as' :: [UppercaseIdentifier] -> IParser (Comments, PreCommented UppercaseIdentifier)
    as' moduleName =
      do  preAs <- try (whitespace <* reserved "as")
          postAs <- whitespace
          (,) preAs <$> (,) postAs <$> capVar <?> ("an alias for module `" ++ show moduleName ++ "`") -- TODO: do something correct instead of show

    exposing :: IParser (Comments, PreCommented (Var.Listing Module.DetailedListing))
    exposing =
      do  preExposing <- try (whitespace <* reserved "exposing")
          postExposing <- whitespace
          imports <- listing detailedListing
          return (preExposing, (postExposing, imports))
import' :: IParser Module.UserImport
import' =
  expecting "an import" $
  do  try (reserved "import")
      preName <- whitespace
      names <- dotSep1 capVar
      method' <- method names
      return ((,) preName names, method')
  where
    method :: [UppercaseIdentifier] -> IParser Module.ImportMethod
    method originalName =
      Module.ImportMethod
        <$> option Nothing (Just <$> as' originalName)
        <*> option ([], ([], Var.ClosedListing)) exposing

    as' :: [UppercaseIdentifier] -> IParser (Comments, PreCommented UppercaseIdentifier)
    as' moduleName =
      do  preAs <- try (whitespace <* reserved "as")
          postAs <- whitespace
          (,) preAs <$> (,) postAs <$> capVar <?> ("an alias for module `" ++ show moduleName ++ "`") -- TODO: do something correct instead of show

    exposing :: IParser (Comments, PreCommented (Var.Listing Module.DetailedListing))
    exposing =
      do  preExposing <- try (whitespace <* reserved "exposing")
          postExposing <- whitespace
          imports <- listing detailedListing
          return (preExposing, (postExposing, imports))
import' =
  expecting "an import" $
  do  try (reserved "import")
      preName <- whitespace
      names <- dotSep1 capVar
      method' <- method names
      return ((,) preName names, method')
  where
    method :: [UppercaseIdentifier] -> IParser Module.ImportMethod
    method originalName =
      Module.ImportMethod
        <$> option Nothing (Just <$> as' originalName)
        <*> option ([], ([], Var.ClosedListing)) exposing

    as' :: [UppercaseIdentifier] -> IParser (Comments, PreCommented UppercaseIdentifier)
    as' moduleName =
      do  preAs <- try (whitespace <* reserved "as")
          postAs <- whitespace
          (,) preAs <$> (,) postAs <$> capVar <?> ("an alias for module `" ++ show moduleName ++ "`") -- TODO: do something correct instead of show

    exposing :: IParser (Comments, PreCommented (Var.Listing Module.DetailedListing))
    exposing =
      do  preExposing <- try (whitespace <* reserved "exposing")
          postExposing <- whitespace
          imports <- listing detailedListing
          return (preExposing, (postExposing, imports))