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 :: ParserOpts -> String -> Bool
isStmt ParserOpts
pflags String
stmt =
  case forall thing. P thing -> ParserOpts -> String -> ParseResult thing
parseThing P (Maybe
     (GenLocated
        SrcSpanAnnA
        (StmtLR GhcPs GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs)))))
Parser.parseStmt ParserOpts
pflags String
stmt of
    Lexer.POk PState
_ Maybe
  (GenLocated
     SrcSpanAnnA
     (StmtLR GhcPs GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))))
_ -> Bool
True
    Lexer.PFailed PState
_ -> Bool
False

-- | Returns @True@ if passed string has an import declaration.
hasImport :: ParserOpts -> String -> Bool
hasImport :: ParserOpts -> String -> Bool
hasImport ParserOpts
pflags String
stmt =
  case forall thing. P thing -> ParserOpts -> String -> ParseResult thing
parseThing P (Located HsModule)
Parser.parseModule ParserOpts
pflags String
stmt of
    Lexer.POk PState
_ Located HsModule
thing -> forall {l}. GenLocated l HsModule -> Bool
hasImports Located HsModule
thing
    Lexer.PFailed PState
_ -> Bool
False
  where
    hasImports :: GenLocated l HsModule -> Bool
hasImports = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsModule -> [LImportDecl GhcPs]
hsmodImports forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l e. GenLocated l e -> e
unLoc

-- | Returns @True@ if passed string is an import declaration.
isImport :: ParserOpts -> String -> Bool
isImport :: ParserOpts -> String -> Bool
isImport ParserOpts
pflags String
stmt =
  case forall thing. P thing -> ParserOpts -> String -> ParseResult thing
parseThing P (GenLocated SrcSpanAnnA (ImportDecl GhcPs))
Parser.parseImport ParserOpts
pflags String
stmt of
    Lexer.POk PState
_ GenLocated SrcSpanAnnA (ImportDecl GhcPs)
_ -> Bool
True
    Lexer.PFailed PState
_ -> Bool
False

-- | Returns @True@ if passed string is a declaration but __/not a splice/__.
isDecl :: ParserOpts -> String -> Bool
isDecl :: ParserOpts -> String -> Bool
isDecl ParserOpts
pflags String
stmt =
  case forall thing. P thing -> ParserOpts -> String -> ParseResult thing
parseThing P (GenLocated SrcSpanAnnA (HsDecl GhcPs))
Parser.parseDeclaration ParserOpts
pflags String
stmt of
    Lexer.POk PState
_ GenLocated SrcSpanAnnA (HsDecl GhcPs)
thing ->
      case forall l e. GenLocated l e -> e
unLoc GenLocated SrcSpanAnnA (HsDecl GhcPs)
thing of
        SpliceD XSpliceD GhcPs
_ SpliceDecl GhcPs
_ -> Bool
False
        HsDecl GhcPs
_ -> Bool
True
    Lexer.PFailed PState
_ -> Bool
False

parseThing :: Lexer.P thing -> ParserOpts -> String -> Lexer.ParseResult thing
parseThing :: forall thing. P thing -> ParserOpts -> String -> ParseResult thing
parseThing P thing
parser ParserOpts
opts String
stmt = do
  let buf :: StringBuffer
buf = String -> StringBuffer
stringToStringBuffer String
stmt
      loc :: RealSrcLoc
loc = FastString -> Int -> Int -> RealSrcLoc
mkRealSrcLoc (String -> FastString
fsLit String
"<interactive>") Int
1 Int
1

  forall a. P a -> PState -> ParseResult a
Lexer.unP P thing
parser (ParserOpts -> StringBuffer -> RealSrcLoc -> PState
Lexer.initParserState ParserOpts
opts StringBuffer
buf RealSrcLoc
loc)