{-| Common interface to various Fortran parsers.

Each parser exports various Happy-generated functions. All export a top-level
'ProgramFile' parser. Most also export intermediate parsers e.g. for
'Statement's and 'Expression's. Fixed form and free form parsers use different
lexing schemes. And, due to headaches with Fortran's syntax, we usually want to
enforce some post-parse transformations.

This module provides a common wrapper over all that functionality. Internal
combinators are exposed to assist in manually configuring parsers.
-}

module Language.Fortran.Parser
  (
  -- * Main parsers (ProgramFile, with transformation)
    byVer, byVerWithMods
  , f66, f77, f77e, f77l, f90, f95, f2003

  -- * Main parsers without post-parse transformation
  , byVerNoTransform
  , f66NoTransform, f77NoTransform, f77eNoTransform, f77lNoTransform
    , f90NoTransform, f95NoTransform, f2003NoTransform

  -- * Other parsers
  , f90Expr
  , byVerFromFilename

  -- ** Statement
  , byVerStmt
  , f66StmtNoTransform, f77StmtNoTransform, f77eStmtNoTransform
    , f77lStmtNoTransform, f90StmtNoTransform, f95StmtNoTransform
    , f2003StmtNoTransform
  , byVerInclude
  , f66IncludesNoTransform, f77IncludesNoTransform, f77eIncludesNoTransform
  , f77lIncludesNoTransform, f90IncludesNoTransform, f95IncludesNoTransform
  , f2003IncludesNoTransform

  -- * Various combinators
  , transformAs, defaultTransformation
  , Parser, ParseErrorSimple(..)
  , StateInit, ParserMaker, makeParser, makeParserFixed, makeParserFree
  , initParseStateFixed, initParseStateFree
  , initParseStateFixedExpr, initParseStateFreeExpr
  , parseUnsafe
  , collectTokensSafe, collectTokens
  , throwIOLeft

  -- * F77 with inlined includes
  -- $f77includes
  , byVerInlineIncludes
  , f66InlineIncludes, f77InlineIncludes, f77eInlineIncludes
  , f77lInlineIncludes, f90InlineIncludes , f95InlineIncludes
  , f2003InlineIncludes
  ) where

import Language.Fortran.AST
import Language.Fortran.Parser.Monad

import qualified Language.Fortran.Parser.Fixed.Fortran66  as F66
import qualified Language.Fortran.Parser.Fixed.Fortran77  as F77
import qualified Language.Fortran.Parser.Free.Fortran90   as F90
import qualified Language.Fortran.Parser.Free.Fortran95   as F95
import qualified Language.Fortran.Parser.Free.Fortran2003 as F2003
import qualified Language.Fortran.Parser.Fixed.Lexer as Fixed
import qualified Language.Fortran.Parser.Free.Lexer  as Free
import Language.Fortran.Version
import Language.Fortran.Util.Position
import Language.Fortran.Util.ModFile
import Language.Fortran.Transformation.Monad
import qualified Language.Fortran.Transformation.Grouping                 as Trans
import qualified Language.Fortran.Transformation.Disambiguation.Function  as Trans
import qualified Language.Fortran.Transformation.Disambiguation.Intrinsic as Trans

import qualified Data.ByteString.Char8 as B
import Data.Data

import Control.Monad.State
import qualified Data.Map as Map
import           Data.Map ( Map )
import Data.Generics.Uniplate.Operations ( descendBiM )
import Control.Exception ( throwIO, Exception )
import System.FilePath ( (</>) )
import System.Directory ( doesFileExist )

-- | Our common Fortran parser type takes a filename and input, and returns
--   either a normalized error (tokens are printed) or an untransformed
--   'ProgramFile'.
type Parser a = String -> B.ByteString -> Either ParseErrorSimple a

-- Provides a way to aggregate errors that come
-- from parses with different token types
data ParseErrorSimple = ParseErrorSimple
  { ParseErrorSimple -> Position
errorPos      :: Position
  , ParseErrorSimple -> [Char]
errorFilename :: String
  , ParseErrorSimple -> [Char]
errorMsg      :: String
  } deriving anyclass (Show ParseErrorSimple
Typeable ParseErrorSimple
(Typeable ParseErrorSimple, Show ParseErrorSimple) =>
(ParseErrorSimple -> SomeException)
-> (SomeException -> Maybe ParseErrorSimple)
-> (ParseErrorSimple -> [Char])
-> Exception ParseErrorSimple
SomeException -> Maybe ParseErrorSimple
ParseErrorSimple -> [Char]
ParseErrorSimple -> SomeException
forall e.
(Typeable e, Show e) =>
(e -> SomeException)
-> (SomeException -> Maybe e) -> (e -> [Char]) -> Exception e
$ctoException :: ParseErrorSimple -> SomeException
toException :: ParseErrorSimple -> SomeException
$cfromException :: SomeException -> Maybe ParseErrorSimple
fromException :: SomeException -> Maybe ParseErrorSimple
$cdisplayException :: ParseErrorSimple -> [Char]
displayException :: ParseErrorSimple -> [Char]
Exception)

instance Show ParseErrorSimple where
  show :: ParseErrorSimple -> [Char]
show ParseErrorSimple
err = ParseErrorSimple -> [Char]
errorFilename ParseErrorSimple
err [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
", " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Position -> [Char]
forall a. Show a => a -> [Char]
show (ParseErrorSimple -> Position
errorPos ParseErrorSimple
err) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
": " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ ParseErrorSimple -> [Char]
errorMsg ParseErrorSimple
err

-- | May be used to lift parse results into IO and force unwrap.
throwIOLeft :: (Exception e, MonadIO m) => Either e a -> m a
throwIOLeft :: forall e (m :: * -> *) a.
(Exception e, MonadIO m) =>
Either e a -> m a
throwIOLeft = \case Right a
a -> a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
                    Left  e
e -> IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ e -> IO a
forall e a. Exception e => e -> IO a
throwIO e
e

--------------------------------------------------------------------------------

byVer :: FortranVersion -> Parser (ProgramFile A0)
byVer :: FortranVersion -> Parser (ProgramFile A0)
byVer = \case
  FortranVersion
Fortran66         -> Parser (ProgramFile A0)
f66
  FortranVersion
Fortran77         -> Parser (ProgramFile A0)
f77
  FortranVersion
Fortran77Extended -> Parser (ProgramFile A0)
f77e
  FortranVersion
Fortran77Legacy   -> Parser (ProgramFile A0)
f77l
  FortranVersion
Fortran90         -> Parser (ProgramFile A0)
f90
  FortranVersion
Fortran95         -> Parser (ProgramFile A0)
f95
  FortranVersion
Fortran2003       -> Parser (ProgramFile A0)
f2003
  FortranVersion
v                 -> [Char] -> Parser (ProgramFile A0)
forall a. HasCallStack => [Char] -> a
error ([Char] -> Parser (ProgramFile A0))
-> [Char] -> Parser (ProgramFile A0)
forall a b. (a -> b) -> a -> b
$  [Char]
"Language.Fortran.Parser.byVer: "
                             [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
"no parser available for requested version: "
                             [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> FortranVersion -> [Char]
forall a. Show a => a -> [Char]
show FortranVersion
v

byVerWithMods :: ModFiles -> FortranVersion -> Parser (ProgramFile A0)
byVerWithMods :: ModFiles -> FortranVersion -> Parser (ProgramFile A0)
byVerWithMods ModFiles
mods = \case
  FortranVersion
Fortran66         -> ModFiles -> Parser (ProgramFile A0)
f66Mods ModFiles
mods
  FortranVersion
Fortran77         -> ModFiles -> Parser (ProgramFile A0)
f77Mods ModFiles
mods
  FortranVersion
Fortran77Extended -> ModFiles -> Parser (ProgramFile A0)
f77eMods ModFiles
mods
  FortranVersion
Fortran77Legacy   -> ModFiles -> Parser (ProgramFile A0)
f77lMods ModFiles
mods
  FortranVersion
Fortran90         -> ModFiles -> Parser (ProgramFile A0)
f90Mods ModFiles
mods
  FortranVersion
Fortran95         -> ModFiles -> Parser (ProgramFile A0)
f95Mods ModFiles
mods
  FortranVersion
Fortran2003       -> ModFiles -> Parser (ProgramFile A0)
f2003Mods ModFiles
mods
  FortranVersion
v                 -> [Char] -> Parser (ProgramFile A0)
forall a. HasCallStack => [Char] -> a
error ([Char] -> Parser (ProgramFile A0))
-> [Char] -> Parser (ProgramFile A0)
forall a b. (a -> b) -> a -> b
$ [Char]
"Language.Fortran.Parser.byVerWithMods: no parser available for requested version: " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> FortranVersion -> [Char]
forall a. Show a => a -> [Char]
show FortranVersion
v

f66, f77, f77e, f77l, f90, f95, f2003 :: Parser (ProgramFile A0)
f66 :: Parser (ProgramFile A0)
f66   = ModFiles -> Parser (ProgramFile A0)
f66Mods   []
f77 :: Parser (ProgramFile A0)
f77   = ModFiles -> Parser (ProgramFile A0)
f77Mods   []
f77e :: Parser (ProgramFile A0)
f77e  = ModFiles -> Parser (ProgramFile A0)
f77eMods  []
f77l :: Parser (ProgramFile A0)
f77l  = ModFiles -> Parser (ProgramFile A0)
f77lMods  []
f90 :: Parser (ProgramFile A0)
f90   = ModFiles -> Parser (ProgramFile A0)
f90Mods   []
f95 :: Parser (ProgramFile A0)
f95   = ModFiles -> Parser (ProgramFile A0)
f95Mods   []
f2003 :: Parser (ProgramFile A0)
f2003 = ModFiles -> Parser (ProgramFile A0)
f2003Mods []

f66Mods, f77Mods, f77eMods, f77lMods, f90Mods, f95Mods, f2003Mods
    :: ModFiles -> Parser (ProgramFile A0)
f66Mods :: ModFiles -> Parser (ProgramFile A0)
f66Mods   = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran66         Parser (ProgramFile A0)
f66NoTransform
f77Mods :: ModFiles -> Parser (ProgramFile A0)
f77Mods   = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran77         Parser (ProgramFile A0)
f77NoTransform
f77eMods :: ModFiles -> Parser (ProgramFile A0)
f77eMods  = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran77Extended Parser (ProgramFile A0)
f77eNoTransform
f77lMods :: ModFiles -> Parser (ProgramFile A0)
f77lMods  = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran77Legacy   Parser (ProgramFile A0)
f77lNoTransform
f90Mods :: ModFiles -> Parser (ProgramFile A0)
f90Mods   = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran90         Parser (ProgramFile A0)
f90NoTransform
f95Mods :: ModFiles -> Parser (ProgramFile A0)
f95Mods   = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran95         Parser (ProgramFile A0)
f95NoTransform
f2003Mods :: ModFiles -> Parser (ProgramFile A0)
f2003Mods = FortranVersion
-> Parser (ProgramFile A0) -> ModFiles -> Parser (ProgramFile A0)
forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
Fortran2003       Parser (ProgramFile A0)
f2003NoTransform

f66NoTransform, f77NoTransform, f77eNoTransform, f77lNoTransform,
  f90NoTransform, f95NoTransform, f2003NoTransform
    :: Parser (ProgramFile A0)
f66NoTransform :: Parser (ProgramFile A0)
f66NoTransform   = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (ProgramFile A0)
F66.programParser   FortranVersion
Fortran66
f77NoTransform :: Parser (ProgramFile A0)
f77NoTransform   = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (ProgramFile A0)
F77.programParser   FortranVersion
Fortran77
f77eNoTransform :: Parser (ProgramFile A0)
f77eNoTransform  = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (ProgramFile A0)
F77.programParser   FortranVersion
Fortran77Extended
f77lNoTransform :: Parser (ProgramFile A0)
f77lNoTransform  = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (ProgramFile A0)
F77.programParser   FortranVersion
Fortran77Legacy
f90NoTransform :: Parser (ProgramFile A0)
f90NoTransform   = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFree  LexAction (ProgramFile A0)
F90.programParser   FortranVersion
Fortran90
f95NoTransform :: Parser (ProgramFile A0)
f95NoTransform   = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFree  LexAction (ProgramFile A0)
F95.programParser   FortranVersion
Fortran95
f2003NoTransform :: Parser (ProgramFile A0)
f2003NoTransform = ParserMaker AlexInput Token (ProgramFile A0)
forall a. ParserMaker AlexInput Token a
makeParserFree  LexAction (ProgramFile A0)
F2003.programParser FortranVersion
Fortran2003

f66StmtNoTransform, f77StmtNoTransform, f77eStmtNoTransform, f77lStmtNoTransform,
  f90StmtNoTransform, f95StmtNoTransform, f2003StmtNoTransform
    :: Parser (Statement A0)
f66StmtNoTransform :: Parser (Statement A0)
f66StmtNoTransform   = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (Statement A0)
F66.statementParser   FortranVersion
Fortran66
f77StmtNoTransform :: Parser (Statement A0)
f77StmtNoTransform   = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (Statement A0)
F77.statementParser   FortranVersion
Fortran77
f77eStmtNoTransform :: Parser (Statement A0)
f77eStmtNoTransform  = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (Statement A0)
F77.statementParser   FortranVersion
Fortran77Extended
f77lStmtNoTransform :: Parser (Statement A0)
f77lStmtNoTransform  = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction (Statement A0)
F77.statementParser   FortranVersion
Fortran77Legacy
f90StmtNoTransform :: Parser (Statement A0)
f90StmtNoTransform   = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFree  LexAction (Statement A0)
F90.statementParser   FortranVersion
Fortran90
f95StmtNoTransform :: Parser (Statement A0)
f95StmtNoTransform   = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFree  LexAction (Statement A0)
F95.statementParser   FortranVersion
Fortran95
f2003StmtNoTransform :: Parser (Statement A0)
f2003StmtNoTransform = ParserMaker AlexInput Token (Statement A0)
forall a. ParserMaker AlexInput Token a
makeParserFree  LexAction (Statement A0)
F2003.statementParser FortranVersion
Fortran2003

byVerStmt :: FortranVersion -> Parser (Statement A0)
byVerStmt :: FortranVersion -> Parser (Statement A0)
byVerStmt = \case
  FortranVersion
Fortran66         -> Parser (Statement A0)
f66StmtNoTransform
  FortranVersion
Fortran77         -> Parser (Statement A0)
f77StmtNoTransform
  FortranVersion
Fortran77Extended -> Parser (Statement A0)
f77eStmtNoTransform
  FortranVersion
Fortran77Legacy   -> Parser (Statement A0)
f77lStmtNoTransform
  FortranVersion
Fortran90         -> Parser (Statement A0)
f90StmtNoTransform
  FortranVersion
Fortran95         -> Parser (Statement A0)
f95StmtNoTransform
  FortranVersion
Fortran2003       -> Parser (Statement A0)
f2003StmtNoTransform
  FortranVersion
v                 -> [Char] -> Parser (Statement A0)
forall a. HasCallStack => [Char] -> a
error ([Char] -> Parser (Statement A0))
-> [Char] -> Parser (Statement A0)
forall a b. (a -> b) -> a -> b
$  [Char]
"Language.Fortran.Parser.byVerStmt: "
                             [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
"no parser available for requested version: "
                             [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> FortranVersion -> [Char]
forall a. Show a => a -> [Char]
show FortranVersion
v
byVerNoTransform :: FortranVersion -> Parser (ProgramFile A0)
byVerNoTransform :: FortranVersion -> Parser (ProgramFile A0)
byVerNoTransform = \case
  FortranVersion
Fortran66         -> Parser (ProgramFile A0)
f66NoTransform
  FortranVersion
Fortran77         -> Parser (ProgramFile A0)
f77NoTransform
  FortranVersion
Fortran77Legacy   -> Parser (ProgramFile A0)
f77lNoTransform
  FortranVersion
Fortran77Extended -> Parser (ProgramFile A0)
f77eNoTransform
  FortranVersion
Fortran90         -> Parser (ProgramFile A0)
f90NoTransform
  FortranVersion
Fortran95         -> Parser (ProgramFile A0)
f90NoTransform
  FortranVersion
Fortran2003       -> Parser (ProgramFile A0)
f2003NoTransform
  FortranVersion
v                 -> [Char] -> Parser (ProgramFile A0)
forall a. HasCallStack => [Char] -> a
error ([Char] -> Parser (ProgramFile A0))
-> [Char] -> Parser (ProgramFile A0)
forall a b. (a -> b) -> a -> b
$  [Char]
"Language.Fortran.Parser.byVerNoTransform: "
                           [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
"no parser available for requested version: "
                           [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> FortranVersion -> [Char]
forall a. Show a => a -> [Char]
show FortranVersion
v

f90Expr :: Parser (Expression A0)
f90Expr :: Parser (Expression A0)
f90Expr = StateInit AlexInput -> ParserMaker AlexInput Token (Expression A0)
forall ai tok a.
(Loc ai, LastToken ai tok, Show tok) =>
StateInit ai -> ParserMaker ai tok a
makeParser StateInit AlexInput
initParseStateFreeExpr LexAction (Expression A0)
F90.expressionParser FortranVersion
Fortran90

-- | Obtain a Fortran parser by assuming the version from the filename provided.
byVerFromFilename :: Parser (ProgramFile A0)
byVerFromFilename :: Parser (ProgramFile A0)
byVerFromFilename [Char]
fn = FortranVersion -> Parser (ProgramFile A0)
byVer FortranVersion
v [Char]
fn
  where v :: FortranVersion
v = [Char] -> FortranVersion
deduceFortranVersion [Char]
fn

--------------------------------------------------------------------------------

transformAs
    :: Data a
    => FortranVersion -> Parser (ProgramFile a) -> ModFiles
    -> Parser (ProgramFile a)
transformAs :: forall a.
Data a =>
FortranVersion
-> Parser (ProgramFile a) -> ModFiles -> Parser (ProgramFile a)
transformAs FortranVersion
fv Parser (ProgramFile a)
p ModFiles
mods [Char]
fn ByteString
bs = do
    ProgramFile a
pf <- Parser (ProgramFile a)
p [Char]
fn ByteString
bs
    let pf' :: ProgramFile a
pf' = [Char] -> ProgramFile a -> ProgramFile a
forall a. [Char] -> ProgramFile a -> ProgramFile a
pfSetFilename [Char]
fn ProgramFile a
pf
    ProgramFile a -> Either ParseErrorSimple (ProgramFile a)
forall a. a -> Either ParseErrorSimple a
forall (m :: * -> *) a. Monad m => a -> m a
return (ProgramFile a -> Either ParseErrorSimple (ProgramFile a))
-> ProgramFile a -> Either ParseErrorSimple (ProgramFile a)
forall a b. (a -> b) -> a -> b
$ ProgramFile a -> ProgramFile a
transform ProgramFile a
pf'
  where transform :: ProgramFile a -> ProgramFile a
transform = TypeEnvExtended
-> ModuleMap -> Transform a A0 -> ProgramFile a -> ProgramFile a
forall a.
Data a =>
TypeEnvExtended
-> ModuleMap -> Transform a A0 -> ProgramFile a -> ProgramFile a
runTransform (ModFiles -> TypeEnvExtended
combinedTypeEnv ModFiles
mods)
                                 (ModFiles -> ModuleMap
combinedModuleMap ModFiles
mods)
                                 (FortranVersion -> Transform a A0
forall a. Data a => FortranVersion -> Transform a A0
defaultTransformation FortranVersion
fv)

-- | The default post-parse AST transformation for each Fortran version.
--
-- Formed by composing transformations end-to-end.
--
-- Note that some transformations are noncommutative e.g. labeled DO grouping
-- must be done before block DO grouping.
defaultTransformation :: Data a => FortranVersion -> Transform a ()
defaultTransformation :: forall a. Data a => FortranVersion -> Transform a A0
defaultTransformation = \case
  FortranVersion
Fortran66         -> [Transform a A0] -> Transform a A0
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m A0
sequence_ [ Transform a A0
forall a. Data a => Transform a A0
Trans.groupLabeledDo
                                 , Transform a A0
forall a. Data a => Transform a A0
Trans.disambiguateIntrinsic
                                 , Transform a A0
forall a. Data a => Transform a A0
Trans.disambiguateFunction ]
  FortranVersion
Fortran77         -> FortranVersion -> Transform a A0
forall a. Data a => FortranVersion -> Transform a A0
defaultTransformation FortranVersion
Fortran66
  FortranVersion
Fortran77Legacy   -> [Transform a A0] -> Transform a A0
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m A0
sequence_ [ Transform a A0
forall a. Data a => Transform a A0
Trans.groupLabeledDo
                                 , Transform a A0
forall a. Data a => Transform a A0
Trans.groupDo
                                 , Transform a A0
forall a. Data a => Transform a A0
Trans.disambiguateIntrinsic
                                 , Transform a A0
forall a. Data a => Transform a A0
Trans.disambiguateFunction ]
  FortranVersion
_ -> FortranVersion -> Transform a A0
forall a. Data a => FortranVersion -> Transform a A0
defaultTransformation FortranVersion
Fortran77Legacy

--------------------------------------------------------------------------------

type StateInit s = String -> FortranVersion -> B.ByteString -> ParseState s
type ParserMaker ai tok a = Parse ai tok a -> FortranVersion -> Parser a

makeParser
    :: (Loc ai, LastToken ai tok, Show tok)
    => StateInit ai -> ParserMaker ai tok a
makeParser :: forall ai tok a.
(Loc ai, LastToken ai tok, Show tok) =>
StateInit ai -> ParserMaker ai tok a
makeParser StateInit ai
fInitState Parse ai tok a
p FortranVersion
fv [Char]
fn = ParseResult ai tok a -> Either ParseErrorSimple a
forall c b a.
Show c =>
ParseResult b c a -> Either ParseErrorSimple a
fromParseResult (ParseResult ai tok a -> Either ParseErrorSimple a)
-> (ByteString -> ParseResult ai tok a)
-> ByteString
-> Either ParseErrorSimple a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parse ai tok a -> ParseState ai -> ParseResult ai tok a
forall b c a.
(Loc b, LastToken b c, Show c) =>
Parse b c a -> ParseState b -> ParseResult b c a
runParse Parse ai tok a
p (ParseState ai -> ParseResult ai tok a)
-> (ByteString -> ParseState ai)
-> ByteString
-> ParseResult ai tok a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateInit ai
fInitState [Char]
fn FortranVersion
fv

makeParserFixed :: ParserMaker Fixed.AlexInput Fixed.Token a
makeParserFixed :: forall a. ParserMaker AlexInput Token a
makeParserFixed = StateInit AlexInput -> ParserMaker AlexInput Token a
forall ai tok a.
(Loc ai, LastToken ai tok, Show tok) =>
StateInit ai -> ParserMaker ai tok a
makeParser StateInit AlexInput
initParseStateFixed

makeParserFree :: ParserMaker Free.AlexInput Free.Token a
makeParserFree :: forall a. ParserMaker AlexInput Token a
makeParserFree = StateInit AlexInput -> ParserMaker AlexInput Token a
forall ai tok a.
(Loc ai, LastToken ai tok, Show tok) =>
StateInit ai -> ParserMaker ai tok a
makeParser StateInit AlexInput
initParseStateFree

initParseStateFixed :: StateInit Fixed.AlexInput
initParseStateFixed :: StateInit AlexInput
initParseStateFixed [Char]
fn FortranVersion
fv ByteString
bs = [Char] -> FortranVersion -> AlexInput -> ParseState AlexInput
forall ai. [Char] -> FortranVersion -> ai -> ParseState ai
initParseState [Char]
fn FortranVersion
fv AlexInput
ai
  where ai :: AlexInput
ai = [Char] -> FortranVersion -> ByteString -> AlexInput
Fixed.vanillaAlexInput [Char]
fn FortranVersion
fv ByteString
bs

initParseStateFree :: StateInit Free.AlexInput
initParseStateFree :: StateInit AlexInput
initParseStateFree [Char]
fn FortranVersion
fv ByteString
bs = [Char] -> FortranVersion -> AlexInput -> ParseState AlexInput
forall ai. [Char] -> FortranVersion -> ai -> ParseState ai
initParseState [Char]
fn FortranVersion
fv AlexInput
ai
  where ai :: AlexInput
ai = [Char] -> ByteString -> AlexInput
Free.vanillaAlexInput [Char]
fn ByteString
bs

-- | Initialize free-form parser state with the lexer configured for standalone
--   expression parsing.
--
-- The free-form lexer needs a non-default start code for lexing standaloe
-- expressions.
initParseStateFreeExpr :: StateInit Free.AlexInput
initParseStateFreeExpr :: StateInit AlexInput
initParseStateFreeExpr [Char]
fn FortranVersion
fv ByteString
bs = ParseState AlexInput
st
  { psAlexInput = ai { Free.aiStartCode = Free.StartCode Free.scN Free.Return } }
  where
    ai :: AlexInput
ai = [Char] -> ByteString -> AlexInput
Free.vanillaAlexInput [Char]
fn ByteString
bs
    st :: ParseState AlexInput
st = StateInit AlexInput
initParseStateFree [Char]
fn FortranVersion
fv ByteString
bs

-- checked in generated file: 1=assn, 4=iif, 6=st
-- 6, 1, 4 seem best in order. Looks like 6 is correct.
-- TODO guesswork, relies on internal behaviour :/
initParseStateFixedExpr :: StateInit Fixed.AlexInput
initParseStateFixedExpr :: StateInit AlexInput
initParseStateFixedExpr [Char]
fn FortranVersion
fv ByteString
bs = ParseState AlexInput
st
  { psAlexInput = ai { Fixed.aiStartCode = 6
                     , Fixed.aiWhiteSensitiveCharCount = 0 } }
  where
    ai :: AlexInput
ai = [Char] -> FortranVersion -> ByteString -> AlexInput
Fixed.vanillaAlexInput [Char]
fn FortranVersion
fv ByteString
bs
    st :: ParseState AlexInput
st = StateInit AlexInput
initParseStateFixed [Char]
fn FortranVersion
fv ByteString
bs

-- | Convenience wrapper to easily use a parser unsafely.
--
-- This throws a catchable runtime IO exception, which is used in the tests.
parseUnsafe :: Parser a -> B.ByteString -> a
parseUnsafe :: forall a. Parser a -> ByteString -> a
parseUnsafe Parser a
p ByteString
bs =
    case Parser a
p [Char]
"<unknown>" ByteString
bs of
      Left ParseErrorSimple
err -> [Char] -> a
forall a. [Char] -> a
throwIOError ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$  [Char]
"Language.Fortran.Parser.parseUnsafe: "
                               [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
"parse error: " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> ParseErrorSimple -> [Char]
forall a. Show a => a -> [Char]
show ParseErrorSimple
err
      Right a
a -> a
a

-- | Helper for preparing initial parser state for the different lexers.
initParseState :: FilePath -> FortranVersion -> ai -> ParseState ai
initParseState :: forall ai. [Char] -> FortranVersion -> ai -> ParseState ai
initParseState [Char]
fn FortranVersion
fv ai
ai = ParseState
  { psAlexInput :: ai
psAlexInput = ai
ai
  , psVersion :: FortranVersion
psVersion = FortranVersion
fv
  , psFilename :: [Char]
psFilename = [Char]
fn
  , psParanthesesCount :: ParanthesesCount
psParanthesesCount = Integer -> Bool -> ParanthesesCount
ParanthesesCount Integer
0 Bool
False
  , psContext :: [Context]
psContext = [ Context
ConStart ] }

--------------------------------------------------------------------------------

{- $f77includes
The Fortran 77 parser can parse and inline includes at parse time. Parse errors
are thrown as IO exceptions.

Can be cleaned up and generalized to use for other parsers.
-}

f66InlineIncludes, f77InlineIncludes, f77eInlineIncludes, f77lInlineIncludes,
  f90InlineIncludes, f95InlineIncludes, f2003InlineIncludes
  :: [FilePath] -> ModFiles -> String -> B.ByteString -> IO (ProgramFile A0)
f66InlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f66InlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran66
f77lInlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f77lInlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran77Legacy
f77eInlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f77eInlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran77Extended
f77InlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f77InlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran77
f90InlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f90InlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran90
f95InlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f95InlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran95
f2003InlineIncludes :: [[Char]] -> ModFiles -> [Char] -> ByteString -> IO (ProgramFile A0)
f2003InlineIncludes = FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
Fortran2003

byVerInlineIncludes
    :: FortranVersion -> [FilePath] -> ModFiles -> String -> B.ByteString
    -> IO (ProgramFile A0)
byVerInlineIncludes :: FortranVersion
-> [[Char]]
-> ModFiles
-> [Char]
-> ByteString
-> IO (ProgramFile A0)
byVerInlineIncludes FortranVersion
version [[Char]]
incs ModFiles
mods [Char]
fn ByteString
bs = do
  case FortranVersion -> Parser (ProgramFile A0)
byVerNoTransform FortranVersion
version [Char]
fn ByteString
bs of
    Left ParseErrorSimple
e -> IO (ProgramFile A0) -> IO (ProgramFile A0)
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ProgramFile A0) -> IO (ProgramFile A0))
-> IO (ProgramFile A0) -> IO (ProgramFile A0)
forall a b. (a -> b) -> a -> b
$ ParseErrorSimple -> IO (ProgramFile A0)
forall e a. Exception e => e -> IO a
throwIO ParseErrorSimple
e
    Right ProgramFile A0
pf -> do
      let pf' :: ProgramFile A0
pf' = [Char] -> ProgramFile A0 -> ProgramFile A0
forall a. [Char] -> ProgramFile a -> ProgramFile a
pfSetFilename [Char]
fn ProgramFile A0
pf
      ProgramFile A0
pf'' <- StateT (Map [Char] [Block A0]) IO (ProgramFile A0)
-> Map [Char] [Block A0] -> IO (ProgramFile A0)
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT ((Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0))
-> ProgramFile A0
-> StateT (Map [Char] [Block A0]) IO (ProgramFile A0)
forall from to (m :: * -> *).
(Biplate from to, Applicative m) =>
(to -> m to) -> from -> m from
forall (m :: * -> *).
Applicative m =>
(Statement A0 -> m (Statement A0))
-> ProgramFile A0 -> m (ProgramFile A0)
descendBiM (FortranVersion
-> [[Char]]
-> [[Char]]
-> Statement A0
-> StateT (Map [Char] [Block A0]) IO (Statement A0)
parserInlineIncludes FortranVersion
version [[Char]]
incs []) ProgramFile A0
pf') Map [Char] [Block A0]
forall k a. Map k a
Map.empty
      let pf''' :: ProgramFile A0
pf''' = TypeEnvExtended
-> ModuleMap -> Transform A0 A0 -> ProgramFile A0 -> ProgramFile A0
forall a.
Data a =>
TypeEnvExtended
-> ModuleMap -> Transform a A0 -> ProgramFile a -> ProgramFile a
runTransform (ModFiles -> TypeEnvExtended
combinedTypeEnv ModFiles
mods)
                                (ModFiles -> ModuleMap
combinedModuleMap ModFiles
mods)
                                (FortranVersion -> Transform A0 A0
forall a. Data a => FortranVersion -> Transform a A0
defaultTransformation FortranVersion
version)
                                ProgramFile A0
pf''
      ProgramFile A0 -> IO (ProgramFile A0)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ProgramFile A0
pf'''

-- Internal function to go through the includes and inline them
parserInlineIncludes
    :: FortranVersion -> [FilePath] -> [FilePath] -> Statement A0
    -> StateT (Map String [Block A0]) IO (Statement A0)
parserInlineIncludes :: FortranVersion
-> [[Char]]
-> [[Char]]
-> Statement A0
-> StateT (Map [Char] [Block A0]) IO (Statement A0)
parserInlineIncludes FortranVersion
version [[Char]]
dirs = [[Char]]
-> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
go
  where
    go :: [[Char]]
-> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
go [[Char]]
seen Statement A0
st = case Statement A0
st of
      StInclude A0
a SrcSpan
s e :: Expression A0
e@(ExpValue A0
_ SrcSpan
_ (ValString [Char]
path)) Maybe [Block A0]
Nothing -> do
        if [Char]
path [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [[Char]]
seen then do
          Map [Char] [Block A0]
incMap <- StateT (Map [Char] [Block A0]) IO (Map [Char] [Block A0])
forall s (m :: * -> *). MonadState s m => m s
get
          case [Char] -> Map [Char] [Block A0] -> Maybe [Block A0]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup [Char]
path Map [Char] [Block A0]
incMap of
            Just [Block A0]
blocks' -> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a. a -> StateT (Map [Char] [Block A0]) IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0))
-> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a b. (a -> b) -> a -> b
$ A0 -> SrcSpan -> Expression A0 -> Maybe [Block A0] -> Statement A0
forall a.
a -> SrcSpan -> Expression a -> Maybe [Block a] -> Statement a
StInclude A0
a SrcSpan
s Expression A0
e ([Block A0] -> Maybe [Block A0]
forall a. a -> Maybe a
Just [Block A0]
blocks')
            Maybe [Block A0]
Nothing -> do
              ([Char]
fullPath, ByteString
incBs) <- IO ([Char], ByteString)
-> StateT (Map [Char] [Block A0]) IO ([Char], ByteString)
forall a. IO a -> StateT (Map [Char] [Block A0]) IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ([Char], ByteString)
 -> StateT (Map [Char] [Block A0]) IO ([Char], ByteString))
-> IO ([Char], ByteString)
-> StateT (Map [Char] [Block A0]) IO ([Char], ByteString)
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char] -> IO ([Char], ByteString)
readInDirs [[Char]]
dirs [Char]
path
              case FortranVersion -> Parser [Block A0]
byVerInclude FortranVersion
version [Char]
fullPath ByteString
incBs of
                Right [Block A0]
blocks -> do
                  [Block A0]
blocks' <- (Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0))
-> [Block A0] -> StateT (Map [Char] [Block A0]) IO [Block A0]
forall from to (m :: * -> *).
(Biplate from to, Applicative m) =>
(to -> m to) -> from -> m from
forall (m :: * -> *).
Applicative m =>
(Statement A0 -> m (Statement A0)) -> [Block A0] -> m [Block A0]
descendBiM ([[Char]]
-> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
go ([Char]
path[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:[[Char]]
seen)) [Block A0]
blocks
                  (Map [Char] [Block A0] -> Map [Char] [Block A0])
-> StateT (Map [Char] [Block A0]) IO A0
forall s (m :: * -> *). MonadState s m => (s -> s) -> m A0
modify ([Char]
-> [Block A0] -> Map [Char] [Block A0] -> Map [Char] [Block A0]
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert [Char]
path [Block A0]
blocks')
                  Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a. a -> StateT (Map [Char] [Block A0]) IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0))
-> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a b. (a -> b) -> a -> b
$ A0 -> SrcSpan -> Expression A0 -> Maybe [Block A0] -> Statement A0
forall a.
a -> SrcSpan -> Expression a -> Maybe [Block a] -> Statement a
StInclude A0
a SrcSpan
s Expression A0
e ([Block A0] -> Maybe [Block A0]
forall a. a -> Maybe a
Just [Block A0]
blocks')
                Left ParseErrorSimple
err -> IO (Statement A0)
-> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a. IO a -> StateT (Map [Char] [Block A0]) IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Statement A0)
 -> StateT (Map [Char] [Block A0]) IO (Statement A0))
-> IO (Statement A0)
-> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a b. (a -> b) -> a -> b
$ ParseErrorSimple -> IO (Statement A0)
forall e a. Exception e => e -> IO a
throwIO ParseErrorSimple
err
        else Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a. a -> StateT (Map [Char] [Block A0]) IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Statement A0
st
      Statement A0
_ -> Statement A0 -> StateT (Map [Char] [Block A0]) IO (Statement A0)
forall a. a -> StateT (Map [Char] [Block A0]) IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Statement A0
st

f66IncludesNoTransform, f77IncludesNoTransform, f77eIncludesNoTransform,
  f77lIncludesNoTransform, f90IncludesNoTransform, f95IncludesNoTransform,
  f2003IncludesNoTransform
  :: Parser [Block A0]
f66IncludesNoTransform :: Parser [Block A0]
f66IncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction [Block A0]
F66.includesParser FortranVersion
Fortran66
f77IncludesNoTransform :: Parser [Block A0]
f77IncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction [Block A0]
F77.includesParser FortranVersion
Fortran77
f77eIncludesNoTransform :: Parser [Block A0]
f77eIncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction [Block A0]
F77.includesParser FortranVersion
Fortran77Extended
f77lIncludesNoTransform :: Parser [Block A0]
f77lIncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFixed LexAction [Block A0]
F77.includesParser FortranVersion
Fortran77Legacy
f90IncludesNoTransform :: Parser [Block A0]
f90IncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFree LexAction [Block A0]
F90.includesParser FortranVersion
Fortran90
f95IncludesNoTransform :: Parser [Block A0]
f95IncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFree LexAction [Block A0]
F95.includesParser FortranVersion
Fortran95
f2003IncludesNoTransform :: Parser [Block A0]
f2003IncludesNoTransform = ParserMaker AlexInput Token [Block A0]
forall a. ParserMaker AlexInput Token a
makeParserFree LexAction [Block A0]
F2003.includesParser FortranVersion
Fortran2003

byVerInclude :: FortranVersion -> Parser [Block A0]
byVerInclude :: FortranVersion -> Parser [Block A0]
byVerInclude = \case
  FortranVersion
Fortran66         -> Parser [Block A0]
f66IncludesNoTransform
  FortranVersion
Fortran77         -> Parser [Block A0]
f77IncludesNoTransform
  FortranVersion
Fortran77Extended -> Parser [Block A0]
f77eIncludesNoTransform
  FortranVersion
Fortran77Legacy   -> Parser [Block A0]
f77lIncludesNoTransform
  FortranVersion
Fortran90         -> Parser [Block A0]
f90IncludesNoTransform
  FortranVersion
Fortran95         -> Parser [Block A0]
f95IncludesNoTransform
  FortranVersion
Fortran2003       -> Parser [Block A0]
f2003IncludesNoTransform
  FortranVersion
v                 -> [Char] -> Parser [Block A0]
forall a. HasCallStack => [Char] -> a
error ([Char] -> Parser [Block A0]) -> [Char] -> Parser [Block A0]
forall a b. (a -> b) -> a -> b
$  [Char]
"Language.Fortran.Parser.byVerInclude: "
                           [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
"no parser available for requested version: "
                           [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> FortranVersion -> [Char]
forall a. Show a => a -> [Char]
show FortranVersion
v

readInDirs :: [String] -> String -> IO (String, B.ByteString)
readInDirs :: [[Char]] -> [Char] -> IO ([Char], ByteString)
readInDirs [] [Char]
f = [Char] -> IO ([Char], ByteString)
forall a. [Char] -> IO a
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> IO ([Char], ByteString))
-> [Char] -> IO ([Char], ByteString)
forall a b. (a -> b) -> a -> b
$ [Char]
"cannot find file: " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
f
readInDirs ([Char]
d:[[Char]]
ds) [Char]
f = do
  let path :: [Char]
path = [Char]
d[Char] -> ShowS
</>[Char]
f
  Bool
b <- [Char] -> IO Bool
doesFileExist [Char]
path
  if Bool
b then
    ([Char]
path,) (ByteString -> ([Char], ByteString))
-> IO ByteString -> IO ([Char], ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO ByteString
B.readFile [Char]
path
  else
    [[Char]] -> [Char] -> IO ([Char], ByteString)
readInDirs [[Char]]
ds [Char]
f

--------------------------------------------------------------------------------

-------------------------------------------------------------------------------
-- Generic token collection and functions (inherited from ParserMonad)
-------------------------------------------------------------------------------

collectTokens
    :: forall a b
    .  (Loc b, Tok a, LastToken b a, Show a)
    => Parse b a a -> ParseState b -> [a]
collectTokens :: forall a b.
(Loc b, Tok a, LastToken b a, Show a) =>
Parse b a a -> ParseState b -> [a]
collectTokens Parse b a a
lexer ParseState b
initState =
    Parse b a [a] -> ParseState b -> [a]
forall b c a.
(Loc b, LastToken b c, Show c) =>
Parse b c a -> ParseState b -> a
evalParse (ParseState b -> Parse b a [a]
_collectTokens ParseState b
initState) ParseState b
forall a. HasCallStack => a
undefined
  where
    _collectTokens :: ParseState b -> Parse b a [a]
    _collectTokens :: ParseState b -> Parse b a [a]
_collectTokens ParseState b
st = do
      let (a
_token, ParseState b
_st) = Parse b a a -> ParseState b -> (a, ParseState b)
forall b c a.
(Loc b, LastToken b c, Show c) =>
Parse b c a -> ParseState b -> (a, ParseState b)
runParseUnsafe Parse b a a
lexer ParseState b
st
      if a -> Bool
forall a. Tok a => a -> Bool
eofToken a
_token
      then [a] -> Parse b a [a]
forall a. a -> Parse b a a
forall (m :: * -> *) a. Monad m => a -> m a
return [a
_token]
      else do
        [a]
_tokens <- ParseState b -> Parse b a [a]
_collectTokens ParseState b
_st
        [a] -> Parse b a [a]
forall a. a -> Parse b a a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> Parse b a [a]) -> [a] -> Parse b a [a]
forall a b. (a -> b) -> a -> b
$ a
_tokena -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
_tokens

collectTokensSafe
    :: forall a b
    .  (Loc b, Tok a, LastToken b a, Show a)
    => Parse b a a -> ParseState b -> Maybe [a]
collectTokensSafe :: forall a b.
(Loc b, Tok a, LastToken b a, Show a) =>
Parse b a a -> ParseState b -> Maybe [a]
collectTokensSafe Parse b a a
lexer ParseState b
initState =
    Parse b a (Maybe [a]) -> ParseState b -> Maybe [a]
forall b c a.
(Loc b, LastToken b c, Show c) =>
Parse b c a -> ParseState b -> a
evalParse (ParseState b -> Parse b a (Maybe [a])
_collectTokens ParseState b
initState) ParseState b
forall a. HasCallStack => a
undefined
  where
    _collectTokens :: ParseState b -> Parse b a (Maybe [a])
    _collectTokens :: ParseState b -> Parse b a (Maybe [a])
_collectTokens ParseState b
st =
      case Parse b a a -> ParseState b -> ParseResult b a a
forall b c a. Parse b c a -> ParseState b -> ParseResult b c a
unParse Parse b a a
lexer ParseState b
st of
        ParseOk a
_token ParseState b
_st ->
          if a -> Bool
forall a. Tok a => a -> Bool
eofToken a
_token
          then Maybe [a] -> Parse b a (Maybe [a])
forall a. a -> Parse b a a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [a] -> Parse b a (Maybe [a]))
-> Maybe [a] -> Parse b a (Maybe [a])
forall a b. (a -> b) -> a -> b
$ [a] -> Maybe [a]
forall a. a -> Maybe a
Just [a
_token]
          else do
            Maybe [a]
_mTokens <- ParseState b -> Parse b a (Maybe [a])
_collectTokens ParseState b
_st
            case Maybe [a]
_mTokens of
              Just [a]
_tokens -> Maybe [a] -> Parse b a (Maybe [a])
forall a. a -> Parse b a a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [a] -> Parse b a (Maybe [a]))
-> Maybe [a] -> Parse b a (Maybe [a])
forall a b. (a -> b) -> a -> b
$ [a] -> Maybe [a]
forall a. a -> Maybe a
Just ([a] -> Maybe [a]) -> [a] -> Maybe [a]
forall a b. (a -> b) -> a -> b
$ a
_tokena -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
_tokens
              Maybe [a]
_ -> Maybe [a] -> Parse b a (Maybe [a])
forall a. a -> Parse b a a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [a]
forall a. Maybe a
Nothing
        ParseResult b a a
_ -> Maybe [a] -> Parse b a (Maybe [a])
forall a. a -> Parse b a a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [a]
forall a. Maybe a
Nothing

fromParseResult :: (Show c) => ParseResult b c a -> Either ParseErrorSimple a
fromParseResult :: forall c b a.
Show c =>
ParseResult b c a -> Either ParseErrorSimple a
fromParseResult (ParseOk a
a ParseState b
_)     = a -> Either ParseErrorSimple a
forall a b. b -> Either a b
Right a
a
fromParseResult (ParseFailed ParseError b c
err) =
    ParseErrorSimple -> Either ParseErrorSimple a
forall a b. a -> Either a b
Left ParseErrorSimple
      { errorPos :: Position
errorPos = ParseError b c -> Position
forall {k} (a :: k) b. ParseError a b -> Position
errPos ParseError b c
err
      , errorFilename :: [Char]
errorFilename = ParseError b c -> [Char]
forall {k} (a :: k) b. ParseError a b -> [Char]
errFilename ParseError b c
err
      , errorMsg :: [Char]
errorMsg = ParseError b c -> [Char]
forall {k} (a :: k) b. ParseError a b -> [Char]
errMsg ParseError b c
err [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"\n" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe c -> [Char]
forall a. Show a => Maybe a -> [Char]
tokenMsg (ParseError b c -> Maybe c
forall {k} (a :: k) b. ParseError a b -> Maybe b
errLastToken ParseError b c
err)  }