-- | Interface to the Futhark parser.
module Language.Futhark.Parser
  ( parseFuthark,
    parseExp,
    parseModExp,
    parseType,
    parseDecOrExpIncrM,
    SyntaxError (..),
  )
where

import Data.Text qualified as T
import Language.Futhark.Parser.Parser
import Language.Futhark.Prop
import Language.Futhark.Syntax

-- | Parse an entire Futhark program from the given 'T.Text', using
-- the 'FilePath' as the source name for error messages.
parseFuthark ::
  FilePath ->
  T.Text ->
  Either SyntaxError UncheckedProg
parseFuthark :: FilePath -> Text -> Either SyntaxError UncheckedProg
parseFuthark = forall a. ParserMonad a -> FilePath -> Text -> Either SyntaxError a
parse ParserMonad UncheckedProg
prog

-- | Parse an Futhark expression from the given 'String', using the
-- 'FilePath' as the source name for error messages.
parseExp ::
  FilePath ->
  T.Text ->
  Either SyntaxError UncheckedExp
parseExp :: FilePath -> Text -> Either SyntaxError UncheckedExp
parseExp = forall a. ParserMonad a -> FilePath -> Text -> Either SyntaxError a
parse ParserMonad UncheckedExp
expression

-- | Parse a Futhark module expression from the given 'String', using the
-- 'FilePath' as the source name for error messages.
parseModExp ::
  FilePath ->
  T.Text ->
  Either SyntaxError (ModExpBase NoInfo Name)
parseModExp :: FilePath -> Text -> Either SyntaxError (ModExpBase NoInfo Name)
parseModExp = forall a. ParserMonad a -> FilePath -> Text -> Either SyntaxError a
parse ParserMonad (ModExpBase NoInfo Name)
modExpression

-- | Parse an Futhark type from the given 'String', using the
-- 'FilePath' as the source name for error messages.
parseType ::
  FilePath ->
  T.Text ->
  Either SyntaxError UncheckedTypeExp
parseType :: FilePath -> Text -> Either SyntaxError UncheckedTypeExp
parseType = forall a. ParserMonad a -> FilePath -> Text -> Either SyntaxError a
parse ParserMonad UncheckedTypeExp
futharkType

-- | Parse an Futhark expression incrementally from monadic actions, using the
-- 'FilePath' as the source name for error messages.
parseExpIncrM ::
  Monad m =>
  m T.Text ->
  FilePath ->
  T.Text ->
  m (Either SyntaxError UncheckedExp)
parseExpIncrM :: forall (m :: * -> *).
Monad m =>
m Text -> FilePath -> Text -> m (Either SyntaxError UncheckedExp)
parseExpIncrM m Text
fetch FilePath
file Text
program =
  forall (m :: * -> *) a. Monad m => m Text -> ReadLineMonad a -> m a
getLinesFromM m Text
fetch forall a b. (a -> b) -> a -> b
$ forall a.
ParserMonad a
-> FilePath -> Text -> ReadLineMonad (Either SyntaxError a)
parseInMonad ParserMonad UncheckedExp
expression FilePath
file Text
program

-- | Parse either an expression or a declaration incrementally;
-- favouring declarations in case of ambiguity.
parseDecOrExpIncrM ::
  Monad m =>
  m T.Text ->
  FilePath ->
  T.Text ->
  m (Either SyntaxError (Either UncheckedDec UncheckedExp))
parseDecOrExpIncrM :: forall (m :: * -> *).
Monad m =>
m Text
-> FilePath
-> Text
-> m (Either SyntaxError (Either UncheckedDec UncheckedExp))
parseDecOrExpIncrM m Text
fetch FilePath
file Text
input =
  case forall a.
ParserMonad a
-> FilePath -> Text -> ReadLineMonad (Either SyntaxError a)
parseInMonad ParserMonad UncheckedDec
declaration FilePath
file Text
input of
    Value Left {} -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. b -> Either a b
Right forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *).
Monad m =>
m Text -> FilePath -> Text -> m (Either SyntaxError UncheckedExp)
parseExpIncrM m Text
fetch FilePath
file Text
input
    Value (Right UncheckedDec
d) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left UncheckedDec
d
    GetLine Maybe Text -> ReadLineMonad (Either SyntaxError UncheckedDec)
_ -> do
      Text
l <- m Text
fetch
      forall (m :: * -> *).
Monad m =>
m Text
-> FilePath
-> Text
-> m (Either SyntaxError (Either UncheckedDec UncheckedExp))
parseDecOrExpIncrM m Text
fetch FilePath
file forall a b. (a -> b) -> a -> b
$ Text
input forall a. Semigroup a => a -> a -> a
<> Text
"\n" forall a. Semigroup a => a -> a -> a
<> Text
l