content: module GHC.Parser.Utils
      ( isStmt
      , hasImport
      , isImport
      , isDecl
      )
  where
  
  import GHC.Prelude
  import GHC.Hs
  import GHC.Data.StringBuffer
  import GHC.Data.FastString
  import GHC.Types.SrcLoc
  
  import qualified GHC.Parser.Lexer as Lexer (P (..), ParseResult(..), unP, initParserState)
  import GHC.Parser.Lexer (ParserOpts)
  import qualified GHC.Parser       as Parser (parseStmt, parseModule, parseDeclaration, parseImport)
  
  
  -- | Returns @True@ if passed string is a statement.
  isStmt :: ParserOpts -> String -> Bool
  isStmt pflags stmt =
    case parseThing Parser.parseStmt pflags stmt of
      Lexer.POk _ _ -> True
      Lexer.PFailed _ -> False
  
  -- | Returns @True@ if passed string has an import declaration.
  hasImport :: ParserOpts -> String -> Bool
  hasImport pflags stmt =
    case parseThing Parser.parseModule pflags stmt of
      Lexer.POk _ thing -> hasImports thing
      Lexer.PFailed _ -> False
    where
      hasImports = not . null . hsmodImports . unLoc
  
  -- | Returns @True@ if passed string is an import declaration.
  isImport :: ParserOpts -> String -> Bool
  isImport pflags stmt =
    case parseThing Parser.parseImport pflags stmt of
      Lexer.POk _ _ -> True
      Lexer.PFailed _ -> False
  
  -- | Returns @True@ if passed string is a declaration but __/not a splice/__.
  isDecl :: ParserOpts -> String -> Bool
  isDecl pflags stmt =
    case parseThing Parser.parseDeclaration pflags stmt of
      Lexer.POk _ thing ->
        case unLoc thing of
          SpliceD _ _ -> False
          _ -> True
      Lexer.PFailed _ -> False
  
  parseThing :: Lexer.P thing -> ParserOpts -> String -> Lexer.ParseResult thing
  parseThing parser opts stmt = do
    let buf = stringToStringBuffer stmt
        loc = mkRealSrcLoc (fsLit "<interactive>") 1 1
  
    Lexer.unP parser (Lexer.initParserState opts buf loc)
  