packages feed

fortran-src 0.4.2 → 0.4.3

raw patch · 20 files changed

+724/−326 lines, 20 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Language.Fortran.AST: AList :: a -> SrcSpan -> [t a] -> AList t a
- Language.Fortran.AST: aCons :: t a -> AList t a -> AList t a
- Language.Fortran.AST: aMap :: (t a -> r a) -> AList t a -> AList r a
- Language.Fortran.AST: aReverse :: AList t a -> AList t a
- Language.Fortran.AST: aStrip :: AList t a -> [t a]
- Language.Fortran.AST: aStrip' :: Maybe (AList t a) -> [t a]
- Language.Fortran.AST: class (Spanned a, Spanned b) => SpannedPair a b
- Language.Fortran.AST: data AList t a
- Language.Fortran.AST: fromList :: Spanned (t a) => a -> [t a] -> AList t a
- Language.Fortran.AST: fromList' :: Spanned (t a) => a -> [t a] -> Maybe (AList t a)
- Language.Fortran.AST: fromReverseList :: Spanned (t ()) => [t ()] -> AList t ()
- Language.Fortran.AST: fromReverseList' :: Spanned (t ()) => [t ()] -> Maybe (AList t ())
- Language.Fortran.AST: getTransSpan :: SpannedPair a b => a -> b -> SrcSpan
- Language.Fortran.AST: infixr 5 `aCons`
- Language.Fortran.AST: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData (t a)) => Control.DeepSeq.NFData (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance (Data.Typeable.Internal.Typeable t, Data.Data.Data a, Data.Data.Data (t a)) => Data.Data.Data (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance (GHC.Classes.Eq a, GHC.Classes.Eq (t a)) => GHC.Classes.Eq (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance (GHC.Show.Show a, GHC.Show.Show (t a)) => GHC.Show.Show (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.AST.SpannedPair a [[b]]
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.AST.SpannedPair a [b]
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.AST.SpannedPair a b
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (Data.Either.Either a b)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (GHC.Maybe.Maybe a, b)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (a, GHC.Maybe.Maybe b)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (a, b)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (GHC.Maybe.Maybe a, GHC.Maybe.Maybe b, GHC.Maybe.Maybe c)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (GHC.Maybe.Maybe a, b, c)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (a, GHC.Maybe.Maybe b, GHC.Maybe.Maybe c)
- Language.Fortran.AST: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (a, b, c)
- Language.Fortran.AST: instance (Text.PrettyPrint.GenericPretty.Out a, Text.PrettyPrint.GenericPretty.Out (t a)) => Text.PrettyPrint.GenericPretty.Out (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance Control.DeepSeq.NFData Language.Fortran.Version.FortranVersion
- Language.Fortran.AST: instance GHC.Base.Functor t => GHC.Base.Functor (Language.Fortran.AST.AList t)
- Language.Fortran.AST: instance GHC.Generics.Generic (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance Language.Fortran.AST.Annotated (Language.Fortran.AST.AList t)
- Language.Fortran.AST: instance Language.Fortran.Util.FirstParameter.FirstParameter (Language.Fortran.AST.AList t a) a
- Language.Fortran.AST: instance Language.Fortran.Util.Position.Spanned (Language.Fortran.AST.AList t a)
- Language.Fortran.AST: instance Language.Fortran.Util.Position.Spanned a => Language.Fortran.Util.Position.Spanned [a]
- Language.Fortran.AST: instance Language.Fortran.Util.SecondParameter.SecondParameter (Language.Fortran.AST.AList t a) Language.Fortran.Util.Position.SrcSpan
- Language.Fortran.AST: instance Text.PrettyPrint.GenericPretty.Out Language.Fortran.Version.FortranVersion
- Language.Fortran.Parser.Any: after :: (b -> c) -> (t -> a -> b) -> t -> a -> c
- Language.Fortran.PrettyPrint: instance Language.Fortran.PrettyPrint.Pretty (e a) => Language.Fortran.PrettyPrint.Pretty (Language.Fortran.AST.AList e a)
+ Language.Fortran.AST: StStatic :: a -> SrcSpan -> AList Declarator a -> Statement a
+ Language.Fortran.AST: instance Language.Fortran.AST.Annotated (Language.Fortran.AST.AList.AList t)
+ Language.Fortran.AST.AList: AList :: a -> SrcSpan -> [t a] -> AList t a
+ Language.Fortran.AST.AList: aCons :: t a -> AList t a -> AList t a
+ Language.Fortran.AST.AList: aMap :: (t a -> r a) -> AList t a -> AList r a
+ Language.Fortran.AST.AList: aReverse :: AList t a -> AList t a
+ Language.Fortran.AST.AList: aStrip :: AList t a -> [t a]
+ Language.Fortran.AST.AList: aStrip' :: Maybe (AList t a) -> [t a]
+ Language.Fortran.AST.AList: data AList t a
+ Language.Fortran.AST.AList: fromList :: Spanned (t a) => a -> [t a] -> AList t a
+ Language.Fortran.AST.AList: fromList' :: Spanned (t a) => a -> [t a] -> Maybe (AList t a)
+ Language.Fortran.AST.AList: fromReverseList :: Spanned (t ()) => [t ()] -> AList t ()
+ Language.Fortran.AST.AList: fromReverseList' :: Spanned (t ()) => [t ()] -> Maybe (AList t ())
+ Language.Fortran.AST.AList: infixr 5 `aCons`
+ Language.Fortran.AST.AList: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData (t a)) => Control.DeepSeq.NFData (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance (Data.Typeable.Internal.Typeable t, Data.Data.Data a, Data.Data.Data (t a)) => Data.Data.Data (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance (GHC.Classes.Eq a, GHC.Classes.Eq (t a)) => GHC.Classes.Eq (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance (GHC.Show.Show a, GHC.Show.Show (t a)) => GHC.Show.Show (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance (Text.PrettyPrint.GenericPretty.Out a, Text.PrettyPrint.GenericPretty.Out (t a)) => Text.PrettyPrint.GenericPretty.Out (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance GHC.Base.Functor t => GHC.Base.Functor (Language.Fortran.AST.AList.AList t)
+ Language.Fortran.AST.AList: instance GHC.Generics.Generic (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance Language.Fortran.Util.FirstParameter.FirstParameter (Language.Fortran.AST.AList.AList t a) a
+ Language.Fortran.AST.AList: instance Language.Fortran.Util.Position.Spanned (Language.Fortran.AST.AList.AList t a)
+ Language.Fortran.AST.AList: instance Language.Fortran.Util.SecondParameter.SecondParameter (Language.Fortran.AST.AList.AList t a) Language.Fortran.Util.Position.SrcSpan
+ Language.Fortran.Lexer.FixedForm: TPercent :: SrcSpan -> Token
+ Language.Fortran.Lexer.FixedForm: TStatic :: SrcSpan -> Token
+ Language.Fortran.Parser.Fortran2003: fortran2003ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran2003: fortran2003ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran66: fortran66ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran66: fortran66ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran77: extended77ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran77: extended77ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran77: fortran77ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran77: fortran77ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran77: legacy77ParserWithIncludesWithTransforms :: [Transformation] -> [String] -> ByteString -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))
+ Language.Fortran.Parser.Fortran77: legacy77ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran77: legacy77ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran90: fortran90ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran90: fortran90ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran95: fortran95ParserWithModFilesWithTransforms :: [Transformation] -> ModFiles -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.Parser.Fortran95: fortran95ParserWithTransforms :: [Transformation] -> ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)
+ Language.Fortran.PrettyPrint: instance Language.Fortran.PrettyPrint.Pretty (e a) => Language.Fortran.PrettyPrint.Pretty (Language.Fortran.AST.AList.AList e a)
+ Language.Fortran.Transformer: defaultTransformations :: FortranVersion -> [Transformation]
+ Language.Fortran.Util.Position: class (Spanned a, Spanned b) => SpannedPair a b
+ Language.Fortran.Util.Position: getTransSpan :: SpannedPair a b => a -> b -> SrcSpan
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (Data.Either.Either a b)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (GHC.Maybe.Maybe a, b)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (a, GHC.Maybe.Maybe b)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.Spanned (a, b)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.SpannedPair a [[b]]
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.SpannedPair a [b]
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b) => Language.Fortran.Util.Position.SpannedPair a b
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (GHC.Maybe.Maybe a, GHC.Maybe.Maybe b, GHC.Maybe.Maybe c)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (GHC.Maybe.Maybe a, b, c)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (a, GHC.Maybe.Maybe b, GHC.Maybe.Maybe c)
+ Language.Fortran.Util.Position: instance (Language.Fortran.Util.Position.Spanned a, Language.Fortran.Util.Position.Spanned b, Language.Fortran.Util.Position.Spanned c) => Language.Fortran.Util.Position.Spanned (a, b, c)
+ Language.Fortran.Util.Position: instance Language.Fortran.Util.Position.Spanned a => Language.Fortran.Util.Position.Spanned [a]
+ Language.Fortran.Version: instance Control.DeepSeq.NFData Language.Fortran.Version.FortranVersion
+ Language.Fortran.Version: instance Text.PrettyPrint.GenericPretty.Out Language.Fortran.Version.FortranVersion
- Language.Fortran.Parser.Any: parserVersions :: [(FortranVersion, Parser)]
+ Language.Fortran.Parser.Any: parserVersions :: FortranVersion -> Parser
- Language.Fortran.Parser.Any: parserWithModFilesVersions :: [(FortranVersion, ParserWithModFiles)]
+ Language.Fortran.Parser.Any: parserWithModFilesVersions :: FortranVersion -> ParserWithModFiles

Files

CHANGELOG.md view
@@ -1,3 +1,18 @@+### 0.4.3 (May 25, 2021)++  * Add Haddock documentation to AST module. Many parts of the AST now have+    commentary on meaning and usage, and the Haddock page is sectioned.+  * Add STATIC statement (should be similar/identical to SAVE attribute) to+    fixed-form lexer, support in Fortran 77 Extended parser.+  * Rewrite post-parse transformation handling. Parser modules now export more+    parsers which allow you to select post-parse transformations to apply,+    intended to enable quicker parsing if you know you don't need to certain+    transformations.+  * Support percent data references in fixed-form lexer, enable in Fortran 77+    parser+  * Now also testing on GHC 9.0+  * Cache INCLUDE-ed files to avoid unnecessary re-parsing+ ### 0.4.2 (March 03, 2021)    * `FortranVersion` from `ParserMonad` moved to its own module
README.md view
@@ -1,5 +1,4 @@ # fortran-src- ![CI status badge](https://github.com/camfort/fortran-src/workflows/CI/badge.svg)  Provides lexing, parsing, and basic analyses of Fortran code covering standards: FORTRAN 66, FORTRAN 77, Fortran 90, Fortran 95 and part of Fortran 2003. Includes data flow and basic block analysis, a renamer, and type analysis. For example usage, see the 'camfort' project (https://github.com/camfort/camfort), which uses fortran-src as its front end.@@ -22,23 +21,47 @@                               --show-flows-to=AST-BLOCK-ID     dump a graph showing flows-to information from the given AST-block ID; prefix with 's' for supergraph                               --show-flows-from=AST-BLOCK-ID   dump a graph showing flows-from information from the given AST-block ID; prefix with 's' for supergraph -## Installation+## Usage/Installation+fortran-src is available on Hackage. Stackage has a very old version and is+definitely not what you want, but you can specify a newer Hackage version in+`stack.yaml`. -### Build from source+### As a dependency+Reference `fortran-src` in your (Stack/Cabal) project dependencies. If you're+using Stack, you can stuff a Hackage reference into `stack.yaml` using+`extra-deps`, like: -Stack 2.x is required for building. *(Stack 1.x may work with minor alternations -- you may have to download the resolver manually.)*+```yaml+resolver: ...+... -Clone the repository and install [Stack](https://docs.haskellstack.org/en/stable/README/).+extra-deps:+- ...+- fortran-src-$VERSION+``` +### As a CLI tool+If you have Cabal properly configured, you should be able install fortran-src+from Hackage:+ ```-stack setup-stack build+cabal install fortran-src ``` -### Using Cabal+Otherwise, we suggest building from source if you want to use the fortran-src+CLI tool. See [#Build from source](#build-from-source) for details. -Install [Cabal](https://www.haskell.org/cabal/).+## Development+As of 2021-04-28, fortran-src supports and is regularly tested on **GHC 8.6,+8.8, 8.10 and 9.0**. Releases prior to/newer than those may have issues. We+welcome fixes that would let us support a wider range of compilers. +### Build from source+#### Stack+Stack 2.x is required. *(Stack 1.x may work with minor alternations+-- you may have to download the resolver manually.)*+ ```-cabal install fortran-src+stack setup+stack build ```
fortran-src.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 50aa4fb72aab53b1e5d449fa390ff3290fb26bd9bf9297a7cac174a79ef92b3f+-- hash: f5d7e99716015530592de9c1b2546f0d2ad31a230d0574adb8385118e8bdba1f  name:           fortran-src-version:        0.4.2+version:        0.4.3 synopsis:       Parsers and analyses for Fortran standards 66, 77, 90 and 95. description:    Provides lexing, parsing, and basic analyses of Fortran code covering standards: FORTRAN 66, FORTRAN 77, Fortran 90, and Fortran 95 and some legacy extensions. Includes data flow and basic block analysis, a renamer, and type analysis. For example usage, see the 'camfort' project, which uses fortran-src as its front end. category:       Language@@ -35,6 +35,7 @@       Language.Fortran.Analysis.BBlocks       Language.Fortran.Analysis.DataFlow       Language.Fortran.AST+      Language.Fortran.AST.AList       Language.Fortran.Version       Language.Fortran.LValue       Language.Fortran.Intrinsics
src/Language/Fortran/AST.hs view
@@ -5,11 +5,114 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-}--- orphans are instances of package-natives-{-# OPTIONS_GHC -Wno-orphans #-} -module Language.Fortran.AST where+-- This module holds the data types used to represent Fortran code of various+-- versions.+--+-- fortran-src supports Fortran 66 through to Fortran 2003, and uses the same+-- types to represent them. The Fortran standard was largely refined as it grew,+-- often assimilating popular compiler extensions for the previous standard. We+-- try to be as permissible as reasonable when parsing; similarly, this AST+-- keeps close to the syntax, and includes statements, expressions, types etc.+-- only applicable to certain (newer) versions of Fortran.+--+-- Useful Fortran standard references:+--+--   * Fortran 77 ANSI standard: ANSI X3.9-1978+--   * Fortran 90 ANSI standard: ANSI X3.198-1992 (also ISO/IEC 1539:1991)+--   * Fortran 90 Handbook (J. Adams)+--+-- (The Fortran 66 ANSI standard lacks detail, and isn't as useful as the later+-- standards for implementing the language.)+--+-- /Some comments aren't reflected in the Haddock documentation, so you may also+-- wish to view this file's source./ +module Language.Fortran.AST+  (+  -- * AST nodes and types+  -- ** Statements and expressions+    ProgramFile(..)+  , ProgramUnit(..)+  , Block(..)+  , Statement(..)+  , Expression(..)+  , Index(..)+  , Value(..)+  , UnaryOp(..)+  , BinaryOp(..)++  -- ** Types and declarations+  , Name+  , BaseType(..)+  , CharacterLen(..)+  , TypeSpec(..)+  , Declarator(..)+  , Selector(..)+  , DimensionDeclarator(..)++  -- ** Annotated node list (re-export)+  , module Language.Fortran.AST.AList++  -- ** Other+  , Attribute(..)+  , Prefix(..)+  , Suffix(..)+  , ProcDecl(..)+  , ProcInterface(..)+  , Comment(..)+  , ForallHeader(..)+  , Only(..)+  , MetaInfo(..)+  , Prefixes+  , Suffixes+  , PrefixSuffix+  , ModuleNature(..)+  , Use(..)+  , Argument(..)+  , Intent(..)+  , ControlPair(..)+  , AllocOpt(..)+  , ImpList(..)+  , ImpElement(..)+  , CommonGroup(..)+  , Namelist(..)+  , DataGroup(..)+  , StructureItem(..)+  , UnionMap(..)+  , FormatItem(..)+  , FlushSpec(..)+  , DoSpecification(..)+  , ProgramUnitName(..)++  -- * Node annotations & related typeclasses+  , A0+  , Annotated(..)+  , Labeled(..)+  , Conditioned(..)+  , Named(..)++  -- * Helpers+  , charLenSelector+  , validPrefixSuffix+  , emptyPrefixes+  , emptySuffixes+  , emptyPrefixSuffix+  , nonExecutableStatement+  , nonExecutableStatementBlock+  , executableStatement+  , executableStatementBlock+  , setInitialisation++  -- ** Assorted getters & setters+  , pfSetFilename+  , pfGetFilename+  , programUnitBody+  , updateProgramUnitBody+  , programUnitSubprograms++  ) where+ import Prelude hiding (init) import Data.Data import Data.Generics.Uniplate.Data ()@@ -17,61 +120,35 @@ import Data.Binary import Control.DeepSeq import Text.PrettyPrint.GenericPretty-import Language.Fortran.ParserMonad (FortranVersion(..))+import Language.Fortran.Version (FortranVersion(..))  import Language.Fortran.Util.Position import Language.Fortran.Util.FirstParameter import Language.Fortran.Util.SecondParameter-+import Language.Fortran.AST.AList +-- | The empty annotation. type A0 = ()  type Name = String --- AST is polymorphic on some type a as that type is used for arbitrary--- annotations---- Many AST nodes such as executable statements, declerations, etc. may--- appear in lists, hence a dedicated annotated list type is defined-data AList t a = AList a SrcSpan [t a] deriving (Eq, Show, Data, Typeable, Generic)-instance Functor t => Functor (AList t) where-  fmap f (AList a s xs) = AList (f a) s (map (fmap f) xs)----- Convert non-empty list to AList.-fromList :: Spanned (t a) => a -> [ t a ] -> AList t a-fromList a xs = AList a (getSpan xs) xs---- Nothing iff list is empty-fromList' :: Spanned (t a) => a -> [ t a ] -> Maybe (AList t a)-fromList' _ [] = Nothing-fromList' a xs = Just $ fromList a xs--fromReverseList :: Spanned (t ()) => [ t () ] -> AList t ()-fromReverseList = fromList () . reverse--fromReverseList' :: Spanned (t ()) => [ t () ] -> Maybe (AList t ())-fromReverseList' = fromList' () . reverse--aCons :: t a -> AList t a -> AList t a-aCons x (AList a s xs) = AList a s $ x:xs--infixr 5 `aCons`--aReverse :: AList t a -> AList t a-aReverse (AList a s xs) = AList a s $ reverse xs--aStrip :: AList t a -> [t a]-aStrip (AList _ _ l) = l--aStrip' :: Maybe (AList t a) -> [t a]-aStrip' Nothing = []-aStrip' (Just a) = aStrip a--aMap :: (t a -> r a) -> AList t a -> AList r a-aMap f (AList a s xs) = AList a s (map f xs)-+-------------------------------------------------------------------------------- -- Basic AST nodes+--------------------------------------------------------------------------------++-- | Type name referenced in syntax.+--+-- In many Fortran specs and compilers, certain types are actually "synonyms"+-- for other types with specified kinds. The primary example is DOUBLE PRECISION+-- being equivalent to REAL(8). Type kinds were introduced in Fortran 90, and it+-- should be safe to replace all instances of DOUBLE PRECISION with REAL(8) in+-- Fortran 90 code. However, type kinds weren't present in (standard) Fortran+-- 77, so this equivalence was detached from the user.+--+-- In any case, it's unclear how strong the equivalence is and whether it can+-- be retroactively applied to previous standards. We choose to parse types+-- directly, and handle those transformations during type analysis, where we+-- assign most scalars a kind (see 'Analysis.SemType'). data BaseType =     TypeInteger   | TypeReal@@ -111,9 +188,24 @@       -- FIXME: some references refer to things like kind=kanji but I can't find any spec for it       | otherwise                                    = Nothing +-- | The type specification of a declaration statement, containing the syntactic+--   type name and kind selector.+--+-- See HP's F90 spec pg.24. data TypeSpec a = TypeSpec a SrcSpan BaseType (Maybe (Selector a))   deriving (Eq, Show, Data, Typeable, Generic, Functor) +-- | The "kind selector" of a declaration statement.+--+-- HP's F90 spec (pg.24) actually differentiates between "kind selectors" and+-- "char selectors", where char selectors can specify a length (alongside kind),+-- and the default meaning of an unlabelled kind parameter (the 8 in INTEGER(8))+-- is length instead of kind. We handle this correctly in the parsers, but place+-- both into this 'Selector' type.+--+-- The upshot is, length is invalid for non-CHARACTER types, and the parser+-- guarantees that it will be Nothing. For CHARACTER types, both maybe or may+-- not be present. data Selector a = --                   Maybe length         | Maybe kind   Selector a SrcSpan (Maybe (Expression a)) (Maybe (Expression a))@@ -299,6 +391,7 @@   | StVolatile            a SrcSpan (AList Declarator a)   | StData                a SrcSpan (AList DataGroup a)   | StAutomatic           a SrcSpan (AList Declarator a)+  | StStatic              a SrcSpan (AList Declarator a)   | StNamelist            a SrcSpan (AList Namelist a)   | StParameter           a SrcSpan (AList Declarator a)   | StExternal            a SrcSpan (AList Expression a)@@ -308,7 +401,11 @@   | StFormat              a SrcSpan (AList FormatItem a)   | StImplicit            a SrcSpan (Maybe (AList ImpList a))   | StEntry               a SrcSpan (Expression a) (Maybe (AList Expression a)) (Maybe (Expression a))+   | StInclude             a SrcSpan (Expression a) (Maybe [Block a])+  -- ^ Nothing indicates an yet-to-be processed include. (The F77 parser parses+  -- Nothing, then fills out each include statement in a post-parse step.)+   | StDo                  a SrcSpan (Maybe String) (Maybe (Expression a)) (Maybe (DoSpecification a))   | StDoWhile             a SrcSpan (Maybe String) (Maybe (Expression a)) (Expression a)   | StEnddo               a SrcSpan (Maybe String)@@ -545,16 +642,45 @@   | ValColon                   -- see R402 / C403 in Fortran2003 spec.   deriving (Eq, Show, Data, Typeable, Generic, Functor) +-- | Declarators.+--+-- Declaration statements can have multiple variables on the right of the double+-- colon, separated by commas. A 'Declarator' identifies a single one of these.+--+-- Each declared variable can have an initializing expression. These expressions+-- are defined in HP's F90 spec to be /initialization expressions/, which are+-- specialized constant expressions.+--+-- The length expressions here are defined in HP's F90 spec to be specifications+-- expressions, which are scalar integer expressions with a bunch of+-- restrictions similar to initialization expressions.+--+-- 'Declarator's are also used for some less-used syntax that let you set+-- variable attributes using statements, like:+--+--     integer arr+--     dimension arr(10)+--+-- Some of these only set part of the 'Declarator' (e.g. @parameter@ only sets+-- the initial value).+--+-- Syntax note: length is set like @character :: str*10@, dimensions are set+-- like @integer :: arr(10)@. Careful to not get confused.+--+-- Note that according to HP's F90 spec, lengths may only be specified for+-- CHARACTER types. So for any declarations that aren't 'TypeCharacter' in the+-- outer 'TypeSpec', the length expression should be Nothing. However, this is+-- not enforced by the AST or parser, so be warned. data Declarator a =     DeclVariable a SrcSpan-                 (Expression a) -- Variable-                 (Maybe (Expression a)) -- Length (character)-                 (Maybe (Expression a)) -- Initial value+                 (Expression a) -- ^ Variable+                 (Maybe (Expression a)) -- ^ Length (character)+                 (Maybe (Expression a)) -- ^ Initial value   | DeclArray a SrcSpan-              (Expression a) -- Array-              (AList DimensionDeclarator a) -- Dimensions-              (Maybe (Expression a)) -- Length (character)-              (Maybe (Expression a)) -- Initial value+              (Expression a) -- ^ Array+              (AList DimensionDeclarator a) -- ^ Dimensions+              (Maybe (Expression a)) -- ^ Length (character)+              (Maybe (Expression a)) -- ^ Initial value   deriving (Eq, Show, Data, Typeable, Generic, Functor)  setInitialisation :: Declarator a -> Expression a -> Declarator a@@ -565,6 +691,7 @@ -- do nothing when there is already a value setInitialisation d _ = d +-- | Dimension declarator stored in @dimension@ attributes and 'Declarator's. data DimensionDeclarator a =   DimensionDeclarator a SrcSpan (Maybe (Expression a)) (Maybe (Expression a))   deriving (Eq, Show, Data, Typeable, Generic, Functor)@@ -614,7 +741,6 @@    modifyAnnotation f x = setAnnotation (f (getAnnotation x)) x -instance FirstParameter (AList t a) a instance FirstParameter (ProgramUnit a) a instance FirstParameter (Prefix a) a instance FirstParameter (Suffix a) a@@ -644,7 +770,6 @@ instance FirstParameter (ControlPair a) a instance FirstParameter (AllocOpt a) a -instance SecondParameter (AList t a) SrcSpan instance SecondParameter (ProgramUnit a) SrcSpan instance SecondParameter (Prefix a) SrcSpan instance SecondParameter (Suffix a) SrcSpan@@ -702,7 +827,6 @@ instance Annotated ControlPair instance Annotated AllocOpt -instance Spanned (AList t a) instance Spanned (ProgramUnit a) instance Spanned (Prefix a) instance Spanned (Suffix a)@@ -740,78 +864,6 @@    setSpan _ _ = error "Cannot set span to a program unit" -instance (Spanned a) => Spanned [a] where-  getSpan [] = error "Trying to find how long an empty list spans for."-  getSpan [x]   = getSpan x-  getSpan (x:xs) = getTransSpan x (last xs)-  setSpan _ _ = error "Cannot set span to an array"--instance (Spanned a, Spanned b) => Spanned (a, Maybe b) where-  getSpan (x, Just y) = getTransSpan x y-  getSpan (x,_) = getSpan x-  setSpan _ = undefined--instance (Spanned a, Spanned b) => Spanned (Maybe a, b) where-  getSpan (Just x,y) = getTransSpan x y-  getSpan (_,y) = getSpan y-  setSpan _ = undefined--instance (Spanned a, Spanned b) => Spanned (Either a b) where-  getSpan (Left x) = getSpan x-  getSpan (Right x) = getSpan x-  setSpan _ = undefined--instance {-# OVERLAPPABLE #-} (Spanned a, Spanned b) => Spanned (a, b) where-  getSpan (x,y) = getTransSpan x y-  setSpan _ = undefined--instance {-# OVERLAPPING #-}(Spanned a, Spanned b, Spanned c) => Spanned (Maybe a, Maybe b, Maybe c) where-  getSpan (Just x,_,Just z) = getTransSpan x z-  getSpan (Just x,Just y,Nothing) = getTransSpan x y-  getSpan (Nothing,Just y,Just z) = getTransSpan y z-  getSpan (Just x,Nothing,Nothing) = getSpan x-  getSpan (Nothing,Just y,Nothing) = getSpan y-  getSpan (Nothing,Nothing,Just z) = getSpan z-  getSpan (Nothing,Nothing,Nothing) = undefined-  setSpan _ = undefined--instance {-# OVERLAPPING #-}(Spanned a, Spanned b, Spanned c) => Spanned (a, Maybe b, Maybe c) where-  getSpan (x,_,Just z) = getTransSpan x z-  getSpan (x,Just y,Nothing) = getTransSpan x y-  getSpan (x,Nothing,Nothing) = getSpan x-  setSpan _ = undefined--instance {-# OVERLAPPING #-} (Spanned a, Spanned b, Spanned c) => Spanned (Maybe a, b, c) where-  getSpan (Just x,_,z) = getTransSpan x z-  getSpan (_,y,z) = getSpan (y,z)-  setSpan _ = undefined--instance {-# OVERLAPPABLE #-} (Spanned a, Spanned b, Spanned c) => Spanned (a, b, c) where-  getSpan (x,_,z) = getTransSpan x z-  setSpan _ = undefined--class (Spanned a, Spanned b) => SpannedPair a b where-  getTransSpan :: a -> b -> SrcSpan--instance {-# OVERLAPPABLE #-} (Spanned a, Spanned b) => SpannedPair a b where-  getTransSpan x y = SrcSpan l1 l2'-    where SrcSpan l1 _ = getSpan x-          SrcSpan _ l2' = getSpan y--instance {-# OVERLAPS #-} (Spanned a, Spanned b) => SpannedPair a [b] where-  getTransSpan x [] = getSpan x-  getTransSpan x y = SrcSpan l1 l2'-    where SrcSpan l1 _ = getSpan x-          SrcSpan _ l2' = getSpan y--instance {-# OVERLAPS #-} (Spanned a, Spanned b) => SpannedPair a [[b]] where-  getTransSpan x [] = getSpan x-  getTransSpan x y | all null y = getSpan x-  getTransSpan x y | any null y = getTransSpan x (filter (not . null) y)-  getTransSpan x y = SrcSpan l1 l2'-    where SrcSpan l1 _ = getSpan x-          SrcSpan _ l2' = getSpan y- class Labeled f where   getLabel :: f a -> Maybe (Expression a)   getLastLabel :: f a -> Maybe (Expression a)@@ -885,13 +937,11 @@   -- Identity function if first arg is nameless or second arg is comment.   setName _ a = a -instance Out FortranVersion instance Out MetaInfo instance Out a => Out (ProgramFile a) instance Out a => Out (ProgramUnit a) instance Out a => Out (Prefix a) instance Out a => Out (Suffix a)-instance (Out a, Out (t a)) => Out (AList t a) instance Out a => Out (Statement a) instance Out a => Out (ProcDecl a) instance Out a => Out (ProcInterface a)@@ -981,7 +1031,6 @@ nonExecutableStatementBlock _ BlInterface{} = True nonExecutableStatementBlock _ _ = False -instance (NFData a, NFData (t a)) => NFData (AList t a) instance NFData a => NFData (ProgramFile a) instance NFData a => NFData (ProgramUnit a) instance NFData a => NFData (Block a)@@ -1015,7 +1064,6 @@ instance NFData a => NFData (StructureItem a) instance NFData a => NFData (UnionMap a) instance NFData MetaInfo-instance NFData FortranVersion instance NFData CharacterLen instance NFData BaseType instance NFData UnaryOp
+ src/Language/Fortran/AST/AList.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}++module Language.Fortran.AST.AList where++import Language.Fortran.Util.FirstParameter+import Language.Fortran.Util.SecondParameter+import Language.Fortran.Util.Position (Spanned, SrcSpan(..), getSpan)++import Data.Data    (Data, Typeable)+import GHC.Generics (Generic)+import Control.DeepSeq (NFData)+import Text.PrettyPrint.GenericPretty (Out)++-- | A location-tagged list of @t a@s (@t@ decorated with an @a@ annotation).+--+-- The AST is polymorphic on some type @a@, which is used for arbitrary+-- annotations. Since many AST nodes use lists (e.g. executable statements,+-- declarations), we define a dedicated annotated list type to reuse.+--+-- Note that the list itself also holds an @a@ annotation.+data AList t a = AList a SrcSpan [t a] deriving (Eq, Show, Data, Typeable, Generic)+instance Functor t => Functor (AList t) where+  fmap f (AList a s xs) = AList (f a) s (map (fmap f) xs)++instance FirstParameter (AList t a) a+instance SecondParameter (AList t a) SrcSpan+instance Spanned (AList t a)+instance (Out a, Out (t a)) => Out (AList t a)+instance (NFData a, NFData (t a)) => NFData (AList t a)++-- | Convert a non-empty list to an 'AList'.+fromList :: Spanned (t a) => a -> [ t a ] -> AList t a+fromList a xs = AList a (getSpan xs) xs++-- | Convert a list to an 'AList', returning Nothing iff the list is empty.+fromList' :: Spanned (t a) => a -> [ t a ] -> Maybe (AList t a)+fromList' _ [] = Nothing+fromList' a xs = Just $ fromList a xs++fromReverseList :: Spanned (t ()) => [ t () ] -> AList t ()+fromReverseList = fromList () . reverse++fromReverseList' :: Spanned (t ()) => [ t () ] -> Maybe (AList t ())+fromReverseList' = fromList' () . reverse++aCons :: t a -> AList t a -> AList t a+aCons x (AList a s xs) = AList a s $ x:xs++infixr 5 `aCons`++aReverse :: AList t a -> AList t a+aReverse (AList a s xs) = AList a s $ reverse xs++aStrip :: AList t a -> [t a]+aStrip (AList _ _ l) = l++aStrip' :: Maybe (AList t a) -> [t a]+aStrip' Nothing = []+aStrip' (Just a) = aStrip a++aMap :: (t a -> r a) -> AList t a -> AList r a+aMap f (AList a s xs) = AList a s (map f xs)
src/Language/Fortran/Analysis/ModGraph.hs view
@@ -86,7 +86,7 @@       iter path = do         contents <- liftIO $ flexReadFile path         let version = fromMaybe (deduceFortranVersion path) mversion-        let (Just parserF0) = lookup version parserWithModFilesVersions+        let parserF0 = parserWithModFilesVersions version         let parserF m b s = fromRight (parserF0 m b s)         fileMods <- liftIO $ decodeModFiles includeDirs         let mods = map snd fileMods
src/Language/Fortran/Lexer/FixedForm.x view
@@ -55,7 +55,7 @@ @id = $letter $alphanumeric{0,5} @label = $digit{1,5} -@idLegacy = [$letter \_ \%] [$alphanumericExtended \$]*+@idLegacy = [$letter \_] [$alphanumericExtended \$]*  @datatype = "integer" | "real" | "doubleprecision" | "complex" | "logical"           -- legacy extensions@@ -85,8 +85,9 @@    <0,st,keyword,iif,assn,doo> \n              { resetPar >> toSC 0 >> addSpan TNewline }   <0,st,keyword,iif,assn,doo> \r              ;-  <0,st,keyword,iif,assn,doo> ";"             { resetPar >> toSC keyword >> addSpan TNewline } +  <st,keyword,iif,assn,doo> ";"               { resetPar >> toSC keyword >> addSpan TNewline }+   <st> "("                                    { addSpan TLeftPar }   <keyword> "(" / { legacy77P }               { addSpan TLeftPar }   <iif> "("                                   { incPar >> addSpan TLeftPar }@@ -97,6 +98,7 @@   <st,iif> "/)" / { formatExtendedP }         { addSpan TRightArrayPar }   <st,iif,doo,keyword> ","                    { addSpan TComma }   <st,iif,keyword> "."                        { addSpan TDot }+  <st,iif,keyword> "%"                        { addSpan TPercent }   <keyword> "." / { legacy77P }               { addSpan TDot }   <st,iif> ":" / { fortran77P }               { addSpan TColon } @@ -196,6 +198,7 @@   -- Tokens related to data initalization statement   <keyword> "data"                            { toSC st >> addSpan TData  }   <keyword> "automatic" / { legacy77P }       { toSC st >> addSpan TAutomatic  }+  <keyword> "static" / { legacy77P }          { toSC st >> addSpan TStatic }    -- Tokens related to format statement   <keyword> "format"                          { toSC fmt >> enterFormat >> addSpan TFormat  }@@ -729,6 +732,7 @@            | TRightArrayPar       SrcSpan            | TComma               SrcSpan            | TDot                 SrcSpan+           | TPercent             SrcSpan            | TColon               SrcSpan            | TInclude             SrcSpan            | TProgram             SrcSpan@@ -793,6 +797,7 @@            | TNone                SrcSpan            | TParameter           SrcSpan            | TData                SrcSpan+           | TStatic              SrcSpan            | TAutomatic           SrcSpan            | TFormat              SrcSpan            | TBlob                SrcSpan String
src/Language/Fortran/Parser/Any.hs view
@@ -1,3 +1,17 @@+{-# LANGUAGE LambdaCase #-}++-- | = Note on these parsers+--+-- Seperate parsers are provided for different Fortran versions. A few parsers+-- are provided for each version, offering built-in defaults or allowing you to+-- configure them yourself. They can be identified by their suffix:+--+--   * @parser@: all defaults (without mod files, default transformations)+--   * @parserWithModFiles@: select mod files, default transformations+--   * @parserWithTransforms@: without mod files, select transformations+--   * @parserWithModFilesWithTransforms@: select mod files, select transformations+--+ module Language.Fortran.Parser.Any where  import Language.Fortran.AST@@ -16,53 +30,57 @@ import qualified Data.ByteString.Char8 as B  type Parser = B.ByteString -> String -> Either ParseErrorSimple (ProgramFile A0)-parserVersions :: [(FortranVersion, Parser)]-parserVersions =-  [ (Fortran66, fromParseResult `after` fortran66Parser)-  , (Fortran77, fromParseResult `after` fortran77Parser)-  , (Fortran77Extended, fromParseResult `after` extended77Parser)-  , (Fortran77Legacy, fromParseResult `after` legacy77Parser)-  , (Fortran90, fromParseResult `after` fortran90Parser)-  , (Fortran95, fromParseResult `after` fortran95Parser)-  , (Fortran2003, fromParseResult `after` fortran2003Parser) ]+parserVersions :: FortranVersion -> Parser+parserVersions = \case+  Fortran66         -> fromParseResult `after` fortran66Parser+  Fortran77         -> fromParseResult `after` fortran77Parser+  Fortran77Extended -> fromParseResult `after` extended77Parser+  Fortran77Legacy   -> fromParseResult `after` legacy77Parser+  Fortran90         -> fromParseResult `after` fortran90Parser+  Fortran95         -> fromParseResult `after` fortran95Parser+  Fortran2003       -> fromParseResult `after` fortran2003Parser+  _                 -> error "no parser available for requested Fortran version"+  where+    after :: (b -> c) -> (t -> a -> b) -> t -> a -> c+    after g f x = g . f x  type ParserWithModFiles = ModFiles -> B.ByteString -> String -> Either ParseErrorSimple (ProgramFile A0)-parserWithModFilesVersions :: [(FortranVersion, ParserWithModFiles)]-parserWithModFilesVersions =-  [ (Fortran66, \m s -> fromParseResult . fortran66ParserWithModFiles m s)-  , (Fortran77, \m s -> fromParseResult . fortran77ParserWithModFiles m s)-  , (Fortran77Extended, \m s -> fromParseResult . extended77ParserWithModFiles m s)-  , (Fortran77Legacy, \m s -> fromParseResult . legacy77ParserWithModFiles m s)-  , (Fortran90, \m s -> fromParseResult . fortran90ParserWithModFiles m s)-  , (Fortran95, \m s -> fromParseResult . fortran95ParserWithModFiles m s)-  , (Fortran2003, \m s -> fromParseResult . fortran2003ParserWithModFiles m s) ]--after :: (b -> c) -> (t -> a -> b) -> t -> a -> c-after g f x = g . f x+parserWithModFilesVersions :: FortranVersion -> ParserWithModFiles+parserWithModFilesVersions = \case+  Fortran66         -> helper fortran66ParserWithModFiles+  Fortran77         -> helper fortran77ParserWithModFiles+  Fortran77Extended -> helper extended77ParserWithModFiles+  Fortran77Legacy   -> helper legacy77ParserWithModFiles+  Fortran90         -> helper fortran90ParserWithModFiles+  Fortran95         -> helper fortran95ParserWithModFiles+  Fortran2003       -> helper fortran2003ParserWithModFiles+  _                 -> error "no parser available for requested Fortran version"+  where+    helper parser m s = fromParseResult . parser m s  -- | Deduce the type of parser from the filename and parse the -- contents of the file. fortranParser :: Parser-fortranParser contents filename = do-   let Just parserF = lookup (deduceFortranVersion filename) parserVersions-   parserF contents filename+fortranParser contents filename =+   let parserF = parserVersions (deduceFortranVersion filename)+    in parserF contents filename  -- | Deduce the type of parser from the filename and parse the -- contents of the file, within the context of given "mod files". fortranParserWithModFiles :: ParserWithModFiles-fortranParserWithModFiles mods contents filename = do-   let Just parserF = lookup (deduceFortranVersion filename) parserWithModFilesVersions-   parserF mods contents filename+fortranParserWithModFiles mods contents filename =+   let parserF = parserWithModFilesVersions (deduceFortranVersion filename)+    in parserF mods contents filename  -- | Given a FortranVersion, parse the contents of the file. fortranParserWithVersion :: FortranVersion -> Parser-fortranParserWithVersion v contents filename = do-   let Just parserF = lookup v parserVersions-   parserF contents filename+fortranParserWithVersion v contents filename =+   let parserF = parserVersions v+    in parserF contents filename  -- | Given a FortranVersion, parse the contents of the file, within -- the context of given "mod files". fortranParserWithModFilesAndVersion :: FortranVersion -> ParserWithModFiles-fortranParserWithModFilesAndVersion v mods contents filename = do-   let Just parserF = lookup v parserWithModFilesVersions-   parserF mods contents filename+fortranParserWithModFilesAndVersion v mods contents filename =+   let parserF = parserWithModFilesVersions v+    in parserF mods contents filename
src/Language/Fortran/Parser/Fortran2003.y view
@@ -4,7 +4,9 @@ module Language.Fortran.Parser.Fortran2003 ( functionParser                                            , statementParser                                            , fortran2003Parser+                                           , fortran2003ParserWithTransforms                                            , fortran2003ParserWithModFiles+                                           , fortran2003ParserWithModFilesWithTransforms                                            ) where  import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST@@ -1286,29 +1288,29 @@ unitNameCheck _ _ = return ()  parse = runParse programParser+defTransforms = defaultTransformations Fortran2003 -transformations2003 =-  [ GroupLabeledDo-  , GroupDo-  , GroupIf-  , GroupCase-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]+fortran2003Parser+    :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran2003Parser = fortran2003ParserWithTransforms defTransforms -fortran2003Parser ::-     B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran2003Parser sourceCode filename =-    (pfSetFilename filename . transform transformations2003) <$> parse parseState-  where-    parseState = initParseState sourceCode Fortran2003 filename+fortran2003ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran2003ParserWithTransforms =+    flip fortran2003ParserWithModFilesWithTransforms emptyModFiles -fortran2003ParserWithModFiles ::-     ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran2003ParserWithModFiles mods sourceCode filename =-    fmap (pfSetFilename filename . transform) $ parse parseState+fortran2003ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran2003ParserWithModFiles = fortran2003ParserWithModFilesWithTransforms defTransforms++fortran2003ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran2003ParserWithModFilesWithTransforms transforms mods sourceCode filename =+    fmap (pfSetFilename filename . transformWithModFiles mods transforms) $ parse parseState   where-    transform = transformWithModFiles mods transformations2003     parseState = initParseState sourceCode Fortran2003 filename  parseError :: Token -> LexAction a
src/Language/Fortran/Parser/Fortran66.y view
@@ -1,10 +1,13 @@ -- -*- Mode: Haskell -*-+-- vim: ft=haskell { module Language.Fortran.Parser.Fortran66 ( expressionParser                                          , statementParser                                          , fortran66Parser-                                         , fortran66ParserWithModFiles )-where+                                         , fortran66ParserWithTransforms+                                         , fortran66ParserWithModFiles+                                         , fortran66ParserWithModFilesWithTransforms+                                         ) where  import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST @@ -504,22 +507,31 @@       expStr  = case exp of { Just (_, s) -> s ; _ -> "" } in     ExpValue () span2 (ValReal $ i1Str ++ dotStr ++ i2Str ++ expStr) -transformations66 =-  [ GroupLabeledDo-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]+parse = runParse programParser+defTransforms = defaultTransformations Fortran66 -fortran66Parser ::-     B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran66Parser = fortran66ParserWithModFiles emptyModFiles+fortran66Parser+    :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran66Parser = fortran66ParserWithTransforms defTransforms -fortran66ParserWithModFiles ::-    ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran66ParserWithModFiles mods sourceCode filename =-    fmap (pfSetFilename filename . transformWithModFiles mods transformations66) $ parse parseState+fortran66ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran66ParserWithTransforms =+    flip fortran66ParserWithModFilesWithTransforms emptyModFiles++fortran66ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran66ParserWithModFiles =+    fortran66ParserWithModFilesWithTransforms defTransforms++fortran66ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran66ParserWithModFilesWithTransforms transforms mods sourceCode filename =+    fmap (pfSetFilename filename . transformWithModFiles mods transforms) $ parse parseState   where-    parse = runParse programParser     parseState = initParseState sourceCode Fortran66 filename  parseError :: Token -> LexAction a
src/Language/Fortran/Parser/Fortran77.y view
@@ -4,13 +4,21 @@   ( expressionParser   , statementParser   , fortran77Parser-  , extended77Parser-  , legacy77Parser-  , includeParser+  , fortran77ParserWithTransforms   , fortran77ParserWithModFiles+  , fortran77ParserWithModFilesWithTransforms+  , extended77Parser+  , extended77ParserWithTransforms   , extended77ParserWithModFiles+  , extended77ParserWithModFilesWithTransforms+  , legacy77Parser+  , legacy77ParserWithTransforms   , legacy77ParserWithModFiles+  , legacy77ParserWithModFilesWithTransforms   , legacy77ParserWithIncludes+  , legacy77ParserWithIncludesWithTransforms+  , includeParser+   ) where  import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST@@ -19,6 +27,7 @@ import Data.List import Data.Maybe (isNothing, fromJust) import qualified Data.ByteString.Char8 as B+import qualified Data.Map as M import Language.Fortran.Util.Position import Language.Fortran.Util.ModFile import Language.Fortran.ParserMonad@@ -49,6 +58,7 @@   '/)'                  { TRightArrayPar _ }   ','                   { TComma _ }   '.'                   { TDot _ }+  '%'                   { TPercent _ }   ':'                   { TColon _ }   include               { TInclude _ }   program               { TProgram _ }@@ -121,6 +131,7 @@   none                  { TNone _ }   data                  { TData _ }   automatic             { TAutomatic _ }+  static                { TStatic _ }   format                { TFormat _ }   blob                  { TBlob _ _ }   int                   { TInt _ _ }@@ -492,6 +503,7 @@ | pointer POINTER_LIST { StPointer () (getTransSpan $1 $2) (fromReverseList $2) } | data DATA_GROUPS { StData () (getTransSpan $1 $2) (fromReverseList $2) } | automatic DECLARATORS { StAutomatic () (getTransSpan $1 $2) (aReverse $2) }+| static DECLARATORS { StStatic () (getTransSpan $1 $2) (aReverse $2) } -- Following is a fake node to make arbitrary FORMAT statements parsable. -- Must be fixed in the future. TODO | format blob@@ -783,7 +795,15 @@ -- Expression all by itself subsumes all other callable expressions. CALLABLE_EXPRESSION :: { Argument A0 } CALLABLE_EXPRESSION-: id '=' EXPRESSION+-- Explicitly parse special intrinsics for argument passing types+: '%' id '(' EXPRESSION ')'+  { let { args = AList () (getSpan $4) $ [Argument () (getSpan $4) Nothing $4];+          TId _ name = $2;+          intr = ExpFunctionCall () (getTransSpan $1 $5)+                   (ExpValue () (getTransSpan $1 $2) (ValIntrinsic ('%':name)))+                   (Just args) }+    in Argument () (getTransSpan $1 $5) Nothing intr }+| id '=' EXPRESSION   { let TId span keyword = $1     in Argument () (getTransSpan span $3) (Just keyword) $3 } | EXPRESSION  { Argument () (getSpan $1) Nothing $1 }@@ -897,6 +917,8 @@ SUBSCRIPT : SUBSCRIPT '.' VARIABLE   { ExpDataRef () (getTransSpan $1 $3) $1 $3 }+| SUBSCRIPT '%' VARIABLE+  { ExpDataRef () (getTransSpan $1 $3) $1 $3 } | SUBSCRIPT '(' ')'   { ExpFunctionCall () (getTransSpan $1 $3) $1 Nothing } | SUBSCRIPT '(' INDICIES ')'@@ -1059,74 +1081,102 @@  parse = runParse programParser -transformations77 =-  [ GroupLabeledDo-  , GroupIf-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]-fortran77Parser ::-    B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran77Parser = fortran77ParserWithModFiles emptyModFiles+defTransforms77  = defaultTransformations Fortran77+defTransforms77e = defaultTransformations Fortran77Extended+defTransforms77l = defaultTransformations Fortran77Legacy -fortran77ParserWithModFiles ::-    ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran77ParserWithModFiles mods sourceCode filename =+fortran77Parser+    :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran77Parser = fortran77ParserWithTransforms defTransforms77++fortran77ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran77ParserWithTransforms =+    flip fortran77ParserWithModFilesWithTransforms emptyModFiles++fortran77ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran77ParserWithModFiles =+    fortran77ParserWithModFilesWithTransforms defTransforms77++fortran77ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran77ParserWithModFilesWithTransforms transforms mods sourceCode filename =     fmap (pfSetFilename filename . transform) $ parse parseState   where-    transform  = transformWithModFiles mods transformations77+    transform  = transformWithModFiles mods transforms     parseState = initParseState sourceCode Fortran77Extended filename -transformations77Extended =-  [ GroupLabeledDo-  , GroupDo-  , GroupIf-  , GroupCase-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]-extended77Parser ::-    B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-extended77Parser = extended77ParserWithModFiles emptyModFiles+extended77Parser+    :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+extended77Parser = extended77ParserWithTransforms defTransforms77e -extended77ParserWithModFiles ::-    ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-extended77ParserWithModFiles mods sourceCode filename =+extended77ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+extended77ParserWithTransforms =+    flip extended77ParserWithModFilesWithTransforms emptyModFiles++extended77ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+extended77ParserWithModFiles =+    extended77ParserWithModFilesWithTransforms defTransforms77e++extended77ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+extended77ParserWithModFilesWithTransforms transforms mods sourceCode filename =     fmap (pfSetFilename filename . transform) $ parse parseState   where-    transform = transformWithModFiles mods transformations77Extended+    transform = transformWithModFiles mods transforms     parseState = initParseState sourceCode Fortran77Extended filename -transformations77Legacy =-  [ GroupLabeledDo-  , GroupDo-  , GroupIf-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]-legacy77Parser ::-    B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-legacy77Parser = legacy77ParserWithModFiles emptyModFiles+legacy77Parser+    :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+legacy77Parser = legacy77ParserWithTransforms defTransforms77l -legacy77ParserWithModFiles ::-    ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-legacy77ParserWithModFiles mods sourceCode filename =+legacy77ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+legacy77ParserWithTransforms = flip legacy77ParserWithModFilesWithTransforms emptyModFiles++legacy77ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+legacy77ParserWithModFiles =+    legacy77ParserWithModFilesWithTransforms defTransforms77l++legacy77ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+legacy77ParserWithModFilesWithTransforms transforms mods sourceCode filename =     fmap (pfSetFilename filename . transform) $ parse parseState   where-    transform = transformWithModFiles mods transformations77Legacy+    transform = transformWithModFiles mods transforms     parseState = initParseState sourceCode Fortran77Legacy filename -legacy77ParserWithIncludes ::-  [String] -> B.ByteString -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))-legacy77ParserWithIncludes incs sourceCode filename =+legacy77ParserWithIncludes+    :: [String]+    -> B.ByteString -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))+legacy77ParserWithIncludes =+    legacy77ParserWithIncludesWithTransforms defTransforms77l++legacy77ParserWithIncludesWithTransforms+    :: [Transformation] -> [String]+    -> B.ByteString -> String -> IO (ParseResult AlexInput Token (ProgramFile A0))+legacy77ParserWithIncludesWithTransforms transforms incs sourceCode filename =     fmap (pfSetFilename filename . transform) <$> doParse   where     doParse = case parse parseState of       ParseFailed e -> return (ParseFailed e)       ParseOk p x -> do-        p' <- descendBiM (inlineInclude Fortran77Legacy incs []) p+        p' <- evalStateT (descendBiM (inlineInclude Fortran77Legacy incs []) p) M.empty         return (ParseOk p' x)-    transform = transformWithModFiles emptyModFiles transformations77Legacy+    transform = transformWithModFiles emptyModFiles transforms     parseState = initParseState sourceCode Fortran77Legacy filename  includeParser ::@@ -1137,16 +1187,22 @@     -- ensure the file ends with a newline..     parseState = initParseState (sourceCode `B.snoc` '\n') version filename -inlineInclude :: FortranVersion -> [String] -> [String] -> Statement A0 -> IO (Statement A0)+inlineInclude :: FortranVersion -> [String] -> [String] -> Statement A0 ->+  StateT (M.Map String [Block A0]) IO (Statement A0) inlineInclude fv dirs seen st = case st of   StInclude a s e@(ExpValue _ _ (ValString path)) Nothing -> do     if notElem path seen then do-      inc <- readInDirs dirs path-      case includeParser fv inc path of-        ParseOk blocks _ -> do-          blocks' <- descendBiM (inlineInclude fv dirs (path:seen)) blocks-          return $ StInclude a s e (Just blocks')-        ParseFailed e -> throwIO e+      incMap <- get+      case M.lookup path incMap of+        Just blocks' -> pure $ StInclude a s e (Just blocks')+        Nothing -> do+          inc <- liftIO $ readInDirs dirs path+          case includeParser fv inc path of+            ParseOk blocks _ -> do+              blocks' <- descendBiM (inlineInclude fv dirs (path:seen)) blocks+              modify (M.insert path blocks')+              return $ StInclude a s e (Just blocks')+            ParseFailed e -> liftIO $ throwIO e     else return st   _ -> return st 
src/Language/Fortran/Parser/Fortran90.y view
@@ -3,7 +3,9 @@ module Language.Fortran.Parser.Fortran90 ( statementParser                                          , functionParser                                          , fortran90Parser+                                         , fortran90ParserWithTransforms                                          , fortran90ParserWithModFiles+                                         , fortran90ParserWithModFilesWithTransforms                                          ) where  import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST@@ -1079,24 +1081,28 @@ unitNameCheck _ _ = return ()  parse = runParse programParser--transformations90 =-  [ GroupLabeledDo-  , GroupDo-  , GroupIf-  , GroupCase-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]+defTransforms = defaultTransformations Fortran90  fortran90Parser ::     B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran90Parser = fortran90ParserWithModFiles emptyModFiles+fortran90Parser = fortran90ParserWithTransforms defTransforms -fortran90ParserWithModFiles ::-    ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran90ParserWithModFiles mods sourceCode filename =-    fmap (pfSetFilename filename . transformWithModFiles mods transformations90) $ parse parseState+fortran90ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran90ParserWithTransforms =+    flip fortran90ParserWithModFilesWithTransforms emptyModFiles++fortran90ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran90ParserWithModFiles = fortran90ParserWithModFilesWithTransforms defTransforms++fortran90ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran90ParserWithModFilesWithTransforms transforms mods sourceCode filename =+    fmap (pfSetFilename filename . transformWithModFiles mods transforms) $ parse parseState   where     parseState = initParseState sourceCode Fortran90 filename 
src/Language/Fortran/Parser/Fortran95.y view
@@ -3,9 +3,12 @@ module Language.Fortran.Parser.Fortran95 ( functionParser                                          , statementParser                                          , fortran95Parser+                                         , fortran95ParserWithTransforms                                          , fortran95ParserWithModFiles+                                         , fortran95ParserWithModFilesWithTransforms                                          ) where + import Prelude hiding (EQ,LT,GT) -- Same constructors exist in the AST import Control.Monad.State import Data.Maybe (fromMaybe, isJust)@@ -1146,29 +1149,29 @@ unitNameCheck _ _ = return ()  parse = runParse programParser+defTransforms = defaultTransformations Fortran95 -transformations95 =-  [ GroupLabeledDo-  , GroupDo-  , GroupIf-  , GroupCase-  , DisambiguateIntrinsic-  , DisambiguateFunction-  ]+fortran95Parser+    :: B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran95Parser = fortran95ParserWithTransforms defTransforms -fortran95Parser ::-     B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran95Parser sourceCode filename =-    (pfSetFilename filename . transform transformations95) <$> parse parseState-  where-    parseState = initParseState sourceCode Fortran95 filename+fortran95ParserWithTransforms+    :: [Transformation]+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran95ParserWithTransforms =+    flip fortran95ParserWithModFilesWithTransforms emptyModFiles -fortran95ParserWithModFiles ::-     ModFiles -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)-fortran95ParserWithModFiles mods sourceCode filename =-    fmap (pfSetFilename filename . transform) $ parse parseState+fortran95ParserWithModFiles+    :: ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran95ParserWithModFiles = fortran95ParserWithModFilesWithTransforms defTransforms++fortran95ParserWithModFilesWithTransforms+    :: [Transformation] -> ModFiles+    -> B.ByteString -> String -> ParseResult AlexInput Token (ProgramFile A0)+fortran95ParserWithModFilesWithTransforms transforms mods sourceCode filename =+    fmap (pfSetFilename filename . transformWithModFiles mods transforms) $ parse parseState   where-    transform = transformWithModFiles mods transformations95     parseState = initParseState sourceCode Fortran95 filename  parseError :: Token -> LexAction a
src/Language/Fortran/PrettyPrint.hs view
@@ -486,6 +486,10 @@       | v == Fortran77Extended = "automatic" <+> pprint' v decls       | otherwise = tooOld v "Automatic statement" Fortran90 +    pprint' v (StStatic _ _ decls)+      | v == Fortran77Extended = "static" <+> pprint' v decls+      | otherwise = tooOld v "Static statement" Fortran90+     pprint' v (StNamelist _ _ namelist)       | v >= Fortran90 = "namelist" <+> pprint' v namelist       | otherwise = tooOld v "Namelist statement" Fortran90
src/Language/Fortran/Transformer.hs view
@@ -1,7 +1,12 @@-module Language.Fortran.Transformer ( transform, transformWithModFiles-                                    , Transformation(..) ) where+{-# LANGUAGE LambdaCase #-} -import Data.Maybe (fromJust)+module Language.Fortran.Transformer+  ( transform+  , transformWithModFiles+  , Transformation(..)+  , defaultTransformations+  ) where+ import Data.Map (empty) import Data.Data @@ -11,6 +16,7 @@ import Language.Fortran.Transformation.Disambiguation.Intrinsic import Language.Fortran.Transformation.Grouping import Language.Fortran.AST (ProgramFile)+import Language.Fortran.Version (FortranVersion(..))  data Transformation =     GroupForall@@ -22,23 +28,38 @@   | DisambiguateIntrinsic   deriving (Eq) -transformationMapping :: Data a => [ (Transformation, Transform a ()) ]-transformationMapping =-  [ (GroupForall, groupForall)-  , (GroupIf, groupIf)-  , (GroupCase, groupCase)-  , (GroupDo, groupDo)-  , (GroupLabeledDo, groupLabeledDo)-  , (DisambiguateFunction, disambiguateFunction)-  , (DisambiguateIntrinsic, disambiguateIntrinsic)-  ]+transformationMapping :: Data a => Transformation -> Transform a ()+transformationMapping = \case+  GroupForall           -> groupForall+  GroupIf               -> groupIf+  GroupCase             -> groupCase+  GroupDo               -> groupDo+  GroupLabeledDo        -> groupLabeledDo+  DisambiguateFunction  -> disambiguateFunction+  DisambiguateIntrinsic -> disambiguateIntrinsic  transformWithModFiles :: Data a => ModFiles -> [ Transformation ] -> ProgramFile a -> ProgramFile a transformWithModFiles mods trs = runTransform (combinedTypeEnv mods) (combinedModuleMap mods) trans   where-    trans = mapM_ (\t -> fromJust $ lookup t transformationMapping) trs+    trans = mapM_ transformationMapping trs  transform :: Data a => [ Transformation ] -> ProgramFile a -> ProgramFile a transform trs = runTransform empty empty trans   where-    trans = mapM_ (\t -> fromJust $ lookup t transformationMapping) trs+    trans = mapM_ transformationMapping trs++-- | The default post-parse AST transformations for each Fortran version.+defaultTransformations :: FortranVersion -> [Transformation]+defaultTransformations = \case+  Fortran66 ->+    [ GroupLabeledDo+    , DisambiguateIntrinsic+    , DisambiguateFunction+    ]+  Fortran77         -> GroupIf   : defaultTransformations Fortran66+  Fortran77Legacy   -> GroupDo   : defaultTransformations Fortran77+  Fortran77Extended -> GroupCase : defaultTransformations Fortran77Legacy+  Fortran90   -> defaultTransformations Fortran77Extended+  Fortran95   -> defaultTransformations Fortran77Extended+  Fortran2003 -> defaultTransformations Fortran77Extended+  Fortran2008 -> defaultTransformations Fortran2003
src/Language/Fortran/Util/Position.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE DeriveGeneric #-}  module Language.Fortran.Util.Position where@@ -91,3 +93,77 @@    default setSpan :: (SecondParameter a SrcSpan) => SrcSpan -> a -> a   setSpan = setSecondParameter++class (Spanned a, Spanned b) => SpannedPair a b where+  getTransSpan :: a -> b -> SrcSpan++--------------------------------------------------------------------------------++instance (Spanned a) => Spanned [a] where+  getSpan [] = error "Trying to find how long an empty list spans for."+  getSpan [x]   = getSpan x+  getSpan (x:xs) = getTransSpan x (last xs)+  setSpan _ _ = error "Cannot set span to an array"++instance (Spanned a, Spanned b) => Spanned (a, Maybe b) where+  getSpan (x, Just y) = getTransSpan x y+  getSpan (x,_) = getSpan x+  setSpan _ = undefined++instance (Spanned a, Spanned b) => Spanned (Maybe a, b) where+  getSpan (Just x,y) = getTransSpan x y+  getSpan (_,y) = getSpan y+  setSpan _ = undefined++instance (Spanned a, Spanned b) => Spanned (Either a b) where+  getSpan (Left x) = getSpan x+  getSpan (Right x) = getSpan x+  setSpan _ = undefined++instance {-# OVERLAPPABLE #-} (Spanned a, Spanned b) => Spanned (a, b) where+  getSpan (x,y) = getTransSpan x y+  setSpan _ = undefined++instance {-# OVERLAPPING #-}(Spanned a, Spanned b, Spanned c) => Spanned (Maybe a, Maybe b, Maybe c) where+  getSpan (Just x,_,Just z) = getTransSpan x z+  getSpan (Just x,Just y,Nothing) = getTransSpan x y+  getSpan (Nothing,Just y,Just z) = getTransSpan y z+  getSpan (Just x,Nothing,Nothing) = getSpan x+  getSpan (Nothing,Just y,Nothing) = getSpan y+  getSpan (Nothing,Nothing,Just z) = getSpan z+  getSpan (Nothing,Nothing,Nothing) = undefined+  setSpan _ = undefined++instance {-# OVERLAPPING #-}(Spanned a, Spanned b, Spanned c) => Spanned (a, Maybe b, Maybe c) where+  getSpan (x,_,Just z) = getTransSpan x z+  getSpan (x,Just y,Nothing) = getTransSpan x y+  getSpan (x,Nothing,Nothing) = getSpan x+  setSpan _ = undefined++instance {-# OVERLAPPING #-} (Spanned a, Spanned b, Spanned c) => Spanned (Maybe a, b, c) where+  getSpan (Just x,_,z) = getTransSpan x z+  getSpan (_,y,z) = getSpan (y,z)+  setSpan _ = undefined++instance {-# OVERLAPPABLE #-} (Spanned a, Spanned b, Spanned c) => Spanned (a, b, c) where+  getSpan (x,_,z) = getTransSpan x z+  setSpan _ = undefined++instance {-# OVERLAPPABLE #-} (Spanned a, Spanned b) => SpannedPair a b where+  getTransSpan x y = SrcSpan l1 l2'+    where SrcSpan l1 _ = getSpan x+          SrcSpan _ l2' = getSpan y++instance {-# OVERLAPS #-} (Spanned a, Spanned b) => SpannedPair a [b] where+  getTransSpan x [] = getSpan x+  getTransSpan x y = SrcSpan l1 l2'+    where SrcSpan l1 _ = getSpan x+          SrcSpan _ l2' = getSpan y++instance {-# OVERLAPS #-} (Spanned a, Spanned b) => SpannedPair a [[b]] where+  getTransSpan x [] = getSpan x+  getTransSpan x y | all null y = getSpan x+  getTransSpan x y | any null y = getTransSpan x (filter (not . null) y)+  getTransSpan x y = SrcSpan l1 l2'+    where SrcSpan l1 _ = getSpan x+          SrcSpan _ l2' = getSpan y
src/Language/Fortran/Version.hs view
@@ -14,8 +14,10 @@ import           Data.Char (toLower) import           Data.List (isInfixOf, isSuffixOf, find) -import Data.Data (Data, Typeable)+import Data.Data    (Data, Typeable) import GHC.Generics (Generic)+import Control.DeepSeq (NFData)+import Text.PrettyPrint.GenericPretty (Out)  data FortranVersion = Fortran66                     | Fortran77@@ -36,6 +38,9 @@   show Fortran95         = "Fortran 95"   show Fortran2003       = "Fortran 2003"   show Fortran2008       = "Fortran 2008"++instance Out    FortranVersion+instance NFData FortranVersion  fortranVersionAliases :: [(String, FortranVersion)] fortranVersionAliases = [ ("66" , Fortran66)
src/Main.hs view
@@ -105,7 +105,7 @@     (path:_, actionOpt) -> do       contents <- flexReadFile path       let version = fromMaybe (deduceFortranVersion path) (fortranVersion opts)-      let (Just parserF0) = lookup version parserWithModFilesVersions+      let parserF0 = parserWithModFilesVersions version       let parserF m b s = fromRight (parserF0 m b s)       let outfmt = outputFormat opts       mods <- decodeModFiles $ includeDirs opts@@ -244,7 +244,7 @@ compileFileToMod mvers mods path moutfile = do   contents <- flexReadFile path   let version = fromMaybe (deduceFortranVersion path) mvers-  let (Just parserF0) = lookup version parserWithModFilesVersions+  let parserF0 = parserWithModFilesVersions version   let parserF m b s = fromRight (parserF0 m b s)   let mmap = combinedModuleMap mods   let tenv = combinedTypeEnv mods
test/Language/Fortran/Lexer/FixedFormSpec.hs view
@@ -226,6 +226,9 @@         resetSrcSpan (collectFixedTokens' Fortran77Legacy "      integer i; integer j")           `shouldBe` resetSrcSpan [TType u "integer", TId u "i", TNewline u, TType u "integer", TId u "j", TEOF u] +      it "does not lex ';' as a line-terminator in first 6 columns" $+        safeLex66 "; integer i; integer j" `shouldBe` Nothing+       it "lexes subscripts in assignments" $         resetSrcSpan (collectFixedTokens' Fortran77Legacy "      x(0,0) = 0")           `shouldBe` resetSrcSpan [TId u "x", TLeftPar u, TInt u "0", TComma u, TInt u "0", TRightPar u, TOpAssign u, TInt u "0", TEOF u]
test/Language/Fortran/Parser/Fortran77/ParserSpec.hs view
@@ -34,7 +34,7 @@   fromParseResultUnsafe $ includeParser Fortran77Legacy (B.pack sourceCode) "<unknown>"  pParser :: String -> ProgramFile ()-pParser source = fromParseResultUnsafe $ fortran77Parser (B.pack source) "<unknown>"+pParser source = fromParseResultUnsafe $ legacy77Parser (B.pack source) "<unknown>"  spec :: Spec spec =@@ -286,6 +286,26 @@             st = StStructure () u (Just "foo") $ AList () u [innerst]         resetSrcSpan (slParser src) `shouldBe` st +      it "parses structure data references " $ do+        let src = init $ unlines [ "      print *, foo % bar"+                                 , "      print *, foo.bar" ]+            expStar = ExpValue () u ValStar+            foobar = ExpDataRef () u (ExpValue () u (ValVariable "foo")) (ExpValue () u (ValVariable "bar"))+            blStmt = BlStatement () u Nothing $ StPrint () u expStar $ Just $ AList () u [foobar]+        resetSrcSpan (iParser src) `shouldBe` [ blStmt, blStmt ]++      it "parse special intrinsics to arguments" $ do+        let blStmt stmt = BlStatement () u Nothing stmt+            var = ExpValue () u . ValVariable+            ext = blStmt $ StExternal () u $ AList () u [var "bar"]+            arg = Just . AList () u . pure . Argument () u Nothing+            valBar = ExpFunctionCall () u (ExpValue () u (ValIntrinsic "%val"))+                     $ arg $ var "baz"+            call = blStmt $ StCall () u (var "bar") $ arg valBar+            pu = ProgramFile mi77 [ PUSubroutine () u (Nothing, Nothing) "foo"+                                   (Just $ AList () u [var "baz"]) [ ext, call ] Nothing ]+        resetSrcSpan (pParser exampleProgram3) `shouldBe` pu+       it "parses character declarations with unspecfied lengths" $ do         let src = "      character s*(*)"             st = StDeclaration () u (TypeSpec () u (TypeCharacter Nothing Nothing) Nothing) Nothing $@@ -348,6 +368,14 @@             tgt3 = ExpSubscript () u (ExpDataRef () u (ExpValue () u (ValVariable "x")) (ExpValue () u (ValVariable "foo"))) (AList () u [mkIdx "0"])             st3 = StExpressionAssign () u tgt3 (ExpValue () u (ValInteger "0"))         resetSrcSpan (slParser src3) `shouldBe` st3+      it "parses automatic and static statements" $ do+        let decl = DeclVariable () u (varGen "x") Nothing Nothing+            autoStmt = StAutomatic () u (AList () u [decl])+            staticStmt = StStatic () u (AList () u [decl])+            autoSrc =  "      automatic x"+            staticSrc = "      static x"+        resetSrcSpan (slParser autoSrc) `shouldBe` autoStmt+        resetSrcSpan (slParser staticSrc) `shouldBe` staticStmt  exampleProgram1 :: String exampleProgram1 = unlines@@ -360,6 +388,13 @@   [ "      block data hello"   , "      integer x"   , "      end" ]++exampleProgram3 :: String+exampleProgram3 = unlines+  [ "      subroutine foo(baz)"+  , "      external bar"+  , "      call bar(%val(baz))"+  , "      end subroutine foo"]  -- Local variables: -- mode: haskell